喜马拉雅会员过期了,我用 AI Coding 做了一个听书 APP
起因
我有个习惯,每天晚上睡觉前都要听会儿书,伴着声音入睡。喜马拉雅用了挺久,直到前几天突然弹窗:会员过期了。看了一眼续费价格,犹豫了一下,转念一想——我自己就是做开发的,最近 AI 辅助编程又确实好用,干脆自己写一个得了。
需求很简单:能导入 TXT/EPUB,能用高质量的语音合成朗读,有定时关闭功能(睡前刚需),跨平台能用就行。
开发过程
翻了一下 Git 记录,从第一次提交到现在大概一周时间,基本都是下班后和周末在搞。下面按时间线捋一遍。
4月15日 - 项目初始化
init: .
选了 Flutter 作为技术栈,主要是看中它的跨平台能力,一套代码能同时跑 Android 和 Windows。用的是 Riverpod 做状态管理,go_router 做路由,freezed 做数据类序列化。项目就这么开始了。
4月16日 - 核心功能落地
feat: 微软ttsfeat: android自动更新feat: windows端/feat: win托盘
听书 APP 最关键的就是语音合成。调研了一圈,选了微软的 Edge TTS 作为主力引擎——效果好,免费,接入也不复杂。同时保留了系统自带的本地 TTS 作为兜底方案,断网时也能用。
自动更新这块花了点心思。因为不走应用商店分发,需要自己实现完整的更新流程:启动时请求服务端接口拿最新版本信息,比对本地 versionCode,有新版本就弹一个更新弹窗,展示更新日志。用户点"立即更新"后,用 Dio 下载 APK,下载过程中有一个实时百分比进度条和已下载/总大小的文字提示(比如 12.3 MB / 25.1 MB),下载完成后通过 MethodChannel 调用原生端拉起系统安装界面。整个过程用户不需要打开浏览器,也不需要手动找文件。
同一天把 Windows 桌面端也跑通了,加了系统托盘支持。这样手机和电脑都能用,坐在电脑前工作的时候也能挂着听。
4月17日 - 补齐短板
feat: 局域网传书fix: 修复.epub导入问题fix: 修复TTS听书跳段bug并优化体验feat: 数据统计
有了 TTS,下一个问题是怎么方便地把书导进去。做了一个局域网传书(Wi-Fi 传书)功能:手机端在本地启动一个 HTTP 服务器,页面上显示一个 IP 地址(比如 http://192.168.1.105:8080),同一 Wi-Fi 下的电脑浏览器打开这个地址就能直接上传文件,传完后页面会实时显示"本次已成功接收 X 本书"。退出页面时服务自动关闭,不用管。
这天还修了两个比较烦人的 bug:EPUB 格式解析有一些边界情况没处理好,以及 TTS 播放时偶尔会跳过某些段落。
另外加了一个数据统计页面,这块做得比较完整:
- 核心指标卡片:今日时长、累计总时长、连续阅读天数、单日最高纪录、日均时长、阅读天数,六个指标一目了然
- 阅读走势图:支持近7天/30天/半年/一年切换,柱状图展示每天的阅读时长
- 年度日历热力图:模仿 GitHub 的 contribution 图,绿色深浅表示每天阅读量的多少,过去一年的阅读习惯一眼就能看出来
- 24小时热力图:统计哪个时间段读书最多,会告诉你"分析发现,22:00 ~ 23:00 是您进入书海的最佳时段"
- 书籍阅读排行:按每本书的累计听书时长排序,带进度条
- 阅读进度总览:书架上每本书读到百分之多少,读完的打绿色勾
- 里程碑成就:类似游戏成就系统,比如"累计阅读 10 小时"、"连续 7 天阅读"之类的,解锁了的和待解锁的分区展示
算是给自己一个正反馈机制,看到热力图变绿也会更有动力继续听。
4月20日 - 体验优化
feat: TTS自然发音优化 - 韵律控制/文本预处理/段落停顿/设置持久化feat: Edge TTS 离线缓存与预下载系统feat: 添加隐藏书籍功能
这一天改动量最大。
发音优化。直接把原文丢给 TTS 读,效果其实一般——省略号会被读成"点点点点点点",破折号也处理得很奇怪,段落之间没有停顿一口气读完。于是加了一层文本预处理:多个省略号合并成逗号停顿,破折号替换为短停顿,书名号周围的多余空格清理掉。语音设置面板做成了一个底部弹出的 Sheet,可以调节语速(0.25x ~ 2.0x)、语调(低/正常/偏高/高)、段落间停顿时间(0 ~ 2秒)。还加了个"智能跳过"开关,可以自动跳过广告水印等非正文内容,以及选择性跳过"第X章"之类的标题行。所有设置都做了持久化。
定时关闭(睡眠定时器)。这个是听书场景的刚需——睡前听书总不能一直放到天亮。做了预设的 15/30/60 分钟快捷按钮,也支持自定义输入任意分钟数。倒计时会实时显示在播放栏上。比较有意思的是两个细节:一是最后 60 秒会自动渐弱音量(线性从 1.0 降到 0.1),不会突然断掉;二是接入了加速度传感器做了摇一摇重置——如果定时快到了但你还没睡着,摇一下手机就能重新开始计时,不用亮屏操作。
离线缓存。在线合成虽然方便,但地铁里没网就没法用了。做了一套完整的离线缓存系统:
- 支持提前批量预下载后续章节的音频,在书架页长按书籍就能选择预下载
- 10 路并发下载,实时显示已下载/总数和进度
- 缓存按书籍 ID 分目录存储,每个段落一个 mp3 文件
- 做了参数指纹校验——如果你换了语音或调了语速,会自动清除旧缓存重新生成,保证缓存和当前设置一致
- 支持按书籍清理缓存、一键清理全部缓存、清理已听过段落的缓存
- 缓存管理页面能看到每本书占了多少存储空间
隐藏书架。长按书籍弹出操作菜单,可以选择隐藏。隐藏的书不会出现在主书架上,需要从侧边抽屉进入"隐藏书架"才能看到。有些书不太想让别人看到,你懂的。
4月21日 - 接入豆包 TTS
feat: TTS架构重构feat: integrate Volcengine (Doubao) TTS engine with unified cache system
Edge TTS 虽然够用,但我想试试火山引擎(豆包)的语音合成,在中文语境下音色更多样一些。
为了同时支持多个 TTS 引擎,先把原来写得比较耦合的 TTS 模块重构了一遍:抽出了 TtsPlaybackService 统一管理播放状态和段落推进逻辑,TtsSettingsService 管理所有引擎的设置和语音选择,TtsCacheService 提供了一个 downloadAndCacheGeneric 方法,接受自定义的下载函数,这样不管底层是 Edge TTS 还是火山引擎,缓存层的逻辑都是复用的。
现在语音设置面板顶部有三个 ChoiceChip 可以切换引擎(本地/微软/豆包),每个引擎下面列出各自的语音列表,分男声女声分组,每个语音旁边有试听按钮。豆包引擎需要配置 API Key,面板里直接就能设置。切换语音时如果正在播放,会自动从当前段落重新开始朗读。
最终形态
总结一下目前这个 APP(叫"耗子伴读")有什么:
- 书籍管理:支持 TXT/EPUB 导入,Wi-Fi 局域网传书,书架网格展示带阅读进度条
- 三引擎 TTS:微软 Edge TTS(免费、高质量)、火山引擎豆包(中文音色丰富)、系统本地 TTS(离线兜底)
- 精细调参:语速、语调、段落停顿时间均可调,智能跳过广告/章节标题
- 睡眠定时:15/30/60 分钟或自定义,最后一分钟音量渐弱,摇一摇重置计时
- 离线缓存:批量预下载、10路并发、参数指纹校验、缓存管理
- 数据统计:日历热力图、24小时时段热力图、书籍排行、里程碑成就
- 隐藏书架:长按隐藏,私密阅读
- 跨平台:Android(自动更新)+ Windows(系统托盘)
- 听书历史:时间线记录每一次听书会话
回头看
一周时间,从空项目到一个功能还算完整的听书工具。放在以前,这个工作量一个人业余时间搞,怎么也得一两个月。
AI 辅助编程在这个过程中确实减少了很多重复劳动,尤其是在并发控制、文件流处理、平台适配这些偏模板化但又容易写出 bug 的地方。但它也不是万能的——架构怎么拆、功能取舍、bug 排查的思路,这些还是得自己想清楚。AI 更像一个手速很快的搭档,你说清楚要什么,它能快速帮你实现,但"要什么"这个问题本身,还是得靠自己。
总之,一次会员到期,倒是逼出来一个完全按自己需求定制的听书工具。现在每晚睡前听着自己做的 APP 入睡,体验比之前还好——没广告,不用续费,定时关闭和音量渐弱都是按自己的习惯来的。
代码目前还没有开源,有些细节还在打磨,比如书源管理、云同步、更完善的 EPUB 排版支持等。等功能再完善一些,代码整理干净了再放出来。