最近我一直在思考一件事:
现在使用 ChatGPT,是否已经可以不打开 IDE,只通过聊天完成一个真正可用的小项目?
这次我实际尝试了一遍。
最后的结果是,我通过和 ChatGPT 持续对话,做出了一个可以在手机上使用的 VOA 英语学习播放器。
项目已经上线:
它现在包含 VOA Learning English Level 2 的全部 30 课,支持:
整个项目并不复杂,但它很好地展示了一种新的开发方式:
人负责发现真实问题、决定产品边界和验收结果,AI 负责需求整理、编码、测试、提交和部署。
我最近想通过 VOA Learning English 提高英语听力。
其中的 Let’s Learn English – Level 2 系列非常适合我。
VOA 原网站已经提供了:
内容本身已经很好,我并不需要重新制作一套英语课程。
但是使用一段时间后,我遇到了几个问题。
对于英语学习来说,1 倍速有时候稍快。
我更希望使用:
0.70
0.75
0.80
0.85
0.90
但 VOA 原页面没有提供这样的细粒度速度控制。
有些课程我希望连续听很多遍,尤其是在睡前、走路或者做其他事情的时候。
原页面没有“整课循环”功能。
我希望设置:
30 分钟后自动停止
这样睡着以后不会一直播放。
刚开始学习一节课时,我经常需要一边听,一边向下阅读 Conversation。
这时可能需要:
但向下滚动以后,原来的音频播放器已经不在屏幕里了。
一开始,我并没有马上决定开发网站。
我先考虑了几个更简单的方法。
可以把音频下载下来,用 VLC 播放。
VLC 支持:
功能上基本没有问题。
但是课程管理体验不好。
下载后的文件名不直观,音频、视频和字幕分散在不同地方。课程多了以后,很难快速知道自己学到哪一课。
VOA 提供 RSS,我也尝试把它加入 Podcast 客户端。
但实际测试发现,RSS 内容并不完整,客户端里只显示了很少的内容,不能作为完整课程目录使用。
也可以在 VLC 播放,然后再打开 iPhone 时钟,设置“30 分钟后停止播放”。
这个方案能用,但每次都需要在多个 App 之间来回操作。
单独看每一步都不复杂,但长期使用时,这种摩擦会让人越来越不愿意打开它。
于是我意识到,我真正需要的并不是更多功能,而是:
把 VOA 已经存在的视频、音频和文本,放进一个更适合我学习习惯的页面里。
刚开始说“自己做一个英语学习网站”时,这个概念很容易无限扩大。
例如可以继续想到:
这些功能都可能有价值。
但如果第一版就做这些,这个项目很可能几个月都无法真正使用。
所以我和 ChatGPT 先把 MVP 压缩成几个核心功能:
| 第一版需要 | 第一版不做 |
|---|---|
| 课程选择 | 用户账号 |
| 视频播放 | 数据库 |
| 音频播放 | 云同步 |
| 完整对话文本 | AI 翻译 |
| 细粒度倍速 | 单句时间轴 |
| 整课循环 | 发音评分 |
| 睡眠定时 | 原生 App |
| 本地进度保存 | 后台管理系统 |
这个决策非常重要。
最终项目甚至明确规定:
项目运行时只使用原生 HTML、CSS、JavaScript、静态 JSON 和浏览器的 localStorage。
这也是这次项目能够快速完成的主要原因之一。
整个项目的主要目录大致如下:
voa-level-2/
├── index.html
├── css/
│ └── styles.css
├── js/
│ ├── app.js
│ └── core.js
├── data/
│ └── lessons.json
├── scripts/
│ └── import_voa.py
├── tests/
├── docs/
│ └── REQUIREMENTS.md
├── AGENTS.md
└── .github/
└── workflows/
运行时没有服务器。
访问页面时,浏览器只是读取:
index.html
styles.css
app.js
lessons.json
然后直接从 VOA 的媒体地址播放视频和音频。
这意味着它非常适合部署到 GitHub Pages。
音频部分直接使用:
<audio controls preload="metadata"></audio>
视频部分使用:
<video controls playsinline preload="metadata"></video>
没有引入第三方播放器,也没有自己绘制进度条。
这样做有几个重要好处。
Safari 对原生 <audio> 和 <video> 的支持通常比自定义播放方案更稳定。
浏览器原生播放器负责:
项目只补充 VOA 原页面没有的功能。
调整速度只需要:
audio.playbackRate = 0.8;
audio.preservesPitch = true;
整课循环只需要:
audio.loop = true;
前进和后退只需要修改:
audio.currentTime += 10;
audio.currentTime -= 10;
项目没有必要为了视觉上的统一,再重新实现一个播放器。
第一版没有马上导入全部 30 课。
我们先放入了 Lesson 1、Lesson 2 和 Lesson 3。
原因很简单:
在没有验证手机播放体验之前,先不要花时间整理全部数据。
前三课已经足够验证:
我开启 GitHub Pages 后,在手机上实际使用了一遍。
结果比我预期的还好。
页面已经基本就是我想要的工具:
选择课程
↓
播放音频或视频
↓
调整为 0.8 倍速
↓
开启循环
↓
设置 30 分钟停止
↓
向下阅读完整对话
这一步非常关键。
不是先把所有功能做完,再一次性验收,而是:
先完成最小闭环,实际使用,再根据真实感受继续修改。
前三课验证通过后,我提出了第二个要求:
ChatGPT 随后修改了 Python 导入脚本。
导入器会读取 VOA 的课程索引页,然后进入每一节课的页面,提取:
生成的数据结构类似:
{
"id": 1,
"title": "Budget Cuts",
"sourceUrl": "https://learningenglish.voanews.com/...",
"videoUrl": "https://..._1080p.mp4",
"videoQuality": 1080,
"audioUrl": "https://..._hq.mp3",
"audioFormat": "mp3",
"audioBitrate": 128,
"transcript": [
{
"speaker": "Anna",
"text": "..."
}
]
}
网站本身不会在用户打开页面时抓取 VOA。
抓取只在开发阶段运行一次,然后把结果保存到:
data/lessons.json
这样做有几个好处:
现在项目已经包含连续的 Lesson 1–30,并使用 VOA 提供的 1080p 视频。
在导入全部课程时,还遇到了一个特殊情况。
大多数课程都提供:
128 kbps MP3
但 Lesson 8 的页面没有独立 MP3。
最终没有从第三方网站寻找音频,也没有伪造一个地址,而是采用了一个明确记录的回退方案:
例如:
{
"audioFormat": "mp4",
"audioFallbackVideoQuality": 240
}
这件事虽然很小,但它体现了一个重要原则:
数据异常不能静默忽略,而应该明确记录。
完整课程上线以后,我实际使用时又发现了一个问题。
在手机上听音频时,往下滚动阅读字幕,播放器会离开屏幕。
而刚开始学习一课时,我经常需要:
VOA 原网站在手机上有一个不错的行为:
页面往下滚动时,播放器会固定在屏幕底部。
所以我把这个需求告诉了 ChatGPT。
最终确定的界面是:
┌────────────────────────────────┐
│ Lesson 3 · He Said… ↶10 10↷ │
│ [ ▶ ━━━━━━━━━━━━━ 03:21 / 05:00 ]│
└────────────────────────────────┘
实现这个功能时,最重要的技术决定是:
页面中始终只有一个
<audio>。
最容易想到的做法,是在原页面放一个播放器,然后再在底部复制一个迷你播放器。
但这样会产生很多问题:
所以最终采用的方式是:
同一个音频元素,在正常状态下位于页面中;滚动后只是通过 CSS 改成
position: fixed。
HTML 结构大致如下:
<div id="audioDockSlot">
<div id="audioDock">
<div class="audio-dock-toolbar">
<span>Lesson 3 · He Said - She Said</span>
<button>↶10</button>
<button>10↷</button>
</div>
<audio id="audioPlayer" controls></audio>
</div>
</div>
当播放器需要固定时:
.audio-dock.is-docked {
position: fixed;
left: 0;
right: 0;
bottom: 0;
}
项目提交中明确增加了手机底部播放器,并保持复用同一个原生 <audio>。
position: sticky因为播放器在媒体卡片中,而字幕在另一个卡片中。
sticky 通常会受到父容器边界限制,无法一直跟随用户阅读后面的字幕。
所以需要使用:
position: fixed;
元素变成 fixed 以后,会离开正常文档流。
如果不保留原来的高度,下面的页面会突然向上跳动。
所以外部保留了:
<div id="audioDockSlot">
浮动前记录播放器高度,浮动后让占位容器继续保持相同高度。
页面使用 IntersectionObserver 判断原播放器是否已经滚出屏幕。
观察的是占位容器,而不是正在浮动的播放器本身。
否则可能出现:
滚出屏幕
→ 变为 fixed
→ 又进入屏幕
→ 取消 fixed
→ 再次滚出
最终造成播放器闪烁。
浮动条件不是:
audio.paused === false
因为用户在字幕区域暂停后,仍然需要马上继续播放。
所以播放器只要在当前课程中启动过一次,即使暂停,也会继续留在底部。
全面屏 iPhone 底部有 Home Indicator。
因此底部播放器使用:
env(safe-area-inset-bottom)
避免按钮和进度条贴住屏幕最底部。
播放器浮动后,页面底部会增加额外 padding。
这样最后一段字幕仍然可以滚动到播放器上方。
项目原本的提示信息也固定在页面底部。
当播放器出现时,Toast 需要移动到播放器上方,否则两者会重叠。
这次和普通的“让 AI 生成一段代码”不太一样。
整个过程大致是:
发现真实问题
↓
通过聊天描述使用场景
↓
ChatGPT 整理需求文档
↓
限制技术栈和 MVP 范围
↓
读取 GitHub 仓库
↓
创建和修改项目文件
↓
创建分支和提交
↓
运行 GitHub Actions
↓
读取失败日志
↓
修复问题并重新提交
↓
合并到 main
↓
GitHub Pages 自动发布
↓
我在真实手机上使用
↓
继续提供下一轮反馈
我在这个过程中主要做三件事:
ChatGPT 则完成了:
这次过程也并不是 ChatGPT 一次生成代码,然后所有东西都完美运行。
中间出现过几次失败。
例如:
git diff --check 检测到尾随空格;但不同的是,这些错误发生后,ChatGPT 可以继续:
最后项目的正式 CI 成功通过。
GitHub Pages 部署也成功完成。
此外还运行了真实 Chromium 浏览器测试,验证手机宽度和桌面宽度下的浮动播放器行为。
这让我对 AI 编程有了一个更实际的理解:
AI 编程不是“永远不出错”,而是“发现错误、读取反馈、修改和重新验证的循环成本变得很低”。
我认为有几个关键原因。
这个项目不是为了测试 AI 而凭空想出的 Demo。
它来源于我每天可能真正使用的场景。
所以我很容易判断:
项目没有一开始就追求:
英语学习平台
而是只解决:
VOA Level 2 的播放体验
目标越具体,AI 越容易做出符合预期的结果。
项目一开始就明确:
不使用 React
不使用后端
不使用数据库
不使用 Docker
不使用用户系统
这避免了一个几百行就能解决的问题,被扩展成一个复杂系统。
第一次:
视频 + 音频 + 字幕 + 倍速 + 循环 + 定时
第二次:
补齐 30 课 + 1080p
第三次:
字幕阅读时底部浮动播放器
每一轮都很明确。
浏览器自动测试只能验证:
但 iPhone 的:
仍然需要真实设备验证。
AI 可以完成大部分开发,但用户的真实体验仍然是最终标准。
经过这次实践,我认为通过 ChatGPT 和 GitHub 直接开发,特别适合下面这些项目:
这些项目通常有几个共同特点:
它暂时不太适合完全依赖聊天直接上线的场景包括:
这些项目仍然需要更系统的设计、安全审查、代码评审和运维方案。
过去使用 AI 编程时,我更习惯这样的流程:
我在本地打开项目
→ 把一段需求发给 AI
→ AI 返回代码
→ 我复制代码
→ 本地运行
→ 出错后再把错误复制给 AI
这次的体验不同。
ChatGPT 可以直接读取 GitHub 仓库,修改代码,提交分支,运行 CI,查看失败日志,再继续修复。
聊天窗口逐渐变成了一个更高层的开发界面。
我不再需要关心每一行代码怎么写,而是更多考虑:
这并不意味着技术知识不再重要。
恰恰相反,技术判断会更多体现在:
这次实践让我认为,使用 ChatGPT 做小项目时,最有效的方式不是说:
帮我做一个英语学习网站
而是按照下面的顺序:
例如:
我在手机上学习 VOA。
我需要一边听音频,一边向下阅读字幕。
阅读字幕时需要经常暂停和后退。
例如:
VLC 文件不好管理。
RSS 内容不完整。
VLC 和系统定时器需要跨多个 App。
例如:
不需要登录。
不需要数据库。
不需要 AI 翻译。
只需要播放、倍速、循环、定时和字幕。
例如:
手机滚动字幕时播放器固定在底部。
暂停以后播放器不能消失。
后退 10 秒按钮必须有效。
切换视频后浮动播放器自动收起。
需求越接近真实行为,AI 输出的产品越接近真正可用。
这个项目本身并不宏大。
它只是解决了一个很小的问题:
让我能够更方便地使用 VOA Level 2 学习英语。
但它让我看到了一种很有意思的可能性。
未来,很多个人工具不一定需要先学习完整的前端框架,也不一定需要专门组建团队。
一个人可以通过聊天:
对我来说,最有价值的变化不是“AI 能写多少代码”,而是:
一个真实想法从产生到变成可使用产品,中间的阻力正在快速降低。
这次我没有试图做一个庞大的英语学习平台。
我只是解决了自己每天真实遇到的一个问题。
而这也许正是当前使用 AI 开发小项目,最适合的方式。
还没有人评论,抢个沙发吧...