rtc_prd/阶段总结/session_progress.md
seaislee1209 84243f2be4 feat: TTS语音合成 + 唱片架播放状态 + 气泡持续显示 + 音乐Prompt优化
- 接入豆包TTS V1 WebSocket API,支持故事朗读语音合成
- 新增 PillProgressButton 组件(药丸形进度按钮)
- 新增 TTSService 单例,后台生成不中断
- 音频保存到 Capybara audio/ 目录
- 唱片架当前播放歌曲高亮(金色卡片+音波动效+喇叭图标)
- 播放时气泡持续显示当前歌名,暂停后隐藏
- 音乐总监Prompt去固定模板,歌名不再重复
- 新增 API 参考文档(豆包语音合成)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-10 22:51:26 +08:00

13 KiB
Raw Permalink Blame History

Airhub 开发进度存档 🔖

用途:每次对话结束前 / 做完一个阶段后更新此文件。 新对话开始时AI 先读此文件恢复上下文。

最后更新2026-02-10 (第九次对话)


当前阶段HTML → Flutter 迁移 & UI 还原

总体目标

将所有 HTML 原型页面 1:1 还原为 Flutter 原生代码,使 App 脱离 WebView 依赖。

本次完成的工作第三次对话2026-02-06

1. 全局字体修复(最重要)

  • 把全项目所有 fontFamily: 'Inter' 替换为正确字体
  • PRD 规范:标题用 Outfit,正文用 DM SansLogo 用 Press Start 2P
  • 修改了 app_theme.dart:设置 DM Sans 为全局默认字体Outfit 用于 heading styles
  • 修改了 design_tokens.dartAppTextStyles 全部改为 GoogleFonts 调用
  • 修改了 gradient_button.dart:按钮文字改 DM Sans
  • 修改了所有页面文件(共 15+ 个文件),零 Inter 残留

2. 逐页 UI 对齐 HTML 原版

  • settings_page.dart:标题字号 18→16Slider 激活色紫色→暖橙 #FFB088
  • bluetooth_page.dart:标题字号 18→17设备名字号 24→20
  • wifi_config_page.dart:标题字号 18→17
  • home_page.dartMascot 尺寸 280→320px添加 translateX(5%) 偏移
  • device_control_page.dartMascot 阴影色紫→粉,导航栏阴影色紫→中性灰
  • login_page.dart两个版本Logo 字号 26→28
  • product_selection_page.dart:标题字体改 Outfit
  • glass_dialog.dart:对话框标题改 Outfit
  • story files:清除所有 Inter 引用

3. 编译验证通过

  • flutter run -d web-server --web-port=8080 编译成功
  • 浏览器预览所有页面确认正常

第四次对话完成的工作2026-02-07

修复音乐播放功能

  • 问题:音乐页面按播放键只有黑胶唱片旋转动画,完全没有接入 just_audio 播放器
  • 根因music_creation_page.dart 没有导入 just_audio,没有创建 AudioPlayer_togglePlay() 只改 UI 状态不播放音频
  • 修复内容
    • 导入 just_audio 并创建 AudioPlayer 实例
    • initState 中初始化播放器 + 监听 position/duration/playerState 三条流
    • _togglePlay() 现在真正调用 play() / pause()
    • _playTrack() 加载对应 asset 并播放
    • 进度条双向绑定:拖拽时 seek播放时实时更新
    • 播完自动切下一首(循环播放列表)
    • 错误处理 + 语音气泡提示
  • MP3 文件9 首歌已在 assets/www/music/pubspec.yaml 已声明,播放列表用了前 4 首

第五次对话完成的工作2026-02-07

UI 规范化 & 按钮/头部统一

  • 书架页面优化:高度、布局、解锁动画丝滑化
  • 头部统一12 个文件统一为标准头部样式40×40按钮、圆角12、arrow_back_ios_new、17px标题
  • 主按钮统一9 个手写按钮改为 GradientButton 组件(光泽+涟漪+DM Sans
  • GradientButton 规范化默认高度50→48plush字号18→17统一
  • 次级按钮规范化统一高度48、圆角24
  • 全局 ToastSnackBar → iOS 风格 AppToast
  • 新增文档flutter_style_guide.mdFlutter 专属样式规范)
  • 阶段总结阶段总结/phase5_ui_standardization.md
  • 详见 阶段总结/phase5_ui_standardization.md

故事详情页修复

  • loading 页传完整故事内容(不再是占位符)
  • 5 个书架故事补全 content 字段(不再显示 null
  • "重写"按钮改为跳转 loading 页重新生成
  • 内容卡片加圆角和边距,头部 padding 加大
  • footer 去掉多余白色底板
  • content 兜底逻辑:无内容时自动用默认故事

第六次对话完成的工作2026-02-08

故事保存"精灵吸入"动画Genie Suck

  • 实现位置story_detail_page.dart
  • 动画效果:点击"保存故事"后,故事卡片执行三段式吸入动画
    • Phase 10→15%):卡片轻微放大到 1.05"蓄力"张力感)
    • Phase 215%→100%):卡片极速缩小到 0.05、向下移动、模糊 + 淡出
    • 缓动曲线cubic-bezier(0.6, -0.28, 0.735, 0.045)(带回弹的快速吸入)
  • 底部按钮:动画开始时 300ms 渐隐 + 禁用点击
  • 总时长0.8s,动画完成后自动 pop('saved') → 触发书架页 bookPop + 粒子效果
  • 三段式完整链路Genie Suck故事页→ bookPop书架页→ sparkle 粒子(书架页)
  • 编译验证web-server 编译通过,无 lint 错误

第七次对话完成的工作2026-02-08

音乐页心情卡片 UI 全面重做

  • 卡片风格:回归玻璃拟态,每张卡片均匀铺一层淡主题色(不再用左白右彩的丑渐变)
  • 边框优化:去掉彩色粗描边,默认极淡主题色边框,选中才加深
  • 图标简化:去掉 40x40 色块方框,改为裸图标 + 主题色着色,更干净
  • 选中态:右上角 8px 主题色圆点指示器 + 卡片颜色加深 + 阴影发光
  • 标题字号:从 13px 回到 14px对应 HTML 原版
  • 自由创作:恢复白底玻璃质感,与心情卡片明确区分
  • 盲盒惊喜:换紫色调(#D4A0E8+ 颜色更浓 + 斜扫柔光动画3s 循环)

歌词可读性优化

  • 歌词文字不透明度从 0.75 提到 0.92
  • 字号从 11px 提到 12px
  • 歌词区域加暗色圆形遮罩,解决纹路干扰

选中态交互修复

  • 生成完成后自动清除 _selectedMoodIndex,不再残留选中状态

第八次对话完成的工作2026-02-09

音乐生成 API 全链路接入(第七次对话中完成,此处补记)

  • SSE 实时进度:点击心情卡片 → 发 POST 到后端 → SSE 流式推送 lyrics/music/saving/done/error 各阶段
  • MusicGenerationService 单例:生成任务在后台运行,页面切走不中断
  • 切回页面恢复:切回音乐页弹窗通知生成结果,不在其他页面自动播放
  • 进度环动画:环形光晕进度条(匹配 HTML 版视觉)+ 翻面歌词时仍可见
  • 进度条防闪烁:用 _crawlId 取消令牌确保同一时间只有一条爬升动画
  • 超时友好提示:气泡显示"网络开小差了,再试一次~"
  • 歌词清洗:前后端双重清理(去 \n、去 [verse] 等结构标签、去 JSON 引号)
  • 歌名修复:后端优先取 LLM 返回的 song_title,歌词增长至 16-24 行
  • 对话气泡样式:文字垂直居中 + 三角尾巴
  • 通知页展开 bug 修复AnimatedCrossFadeClipRect + AnimatedSize 避免文字竖排

启动时加载历史歌曲

  • 后端/api/playlist 接口扫描 Capybara music/ 目录,返回所有 mp3 + 歌词
  • Service 层MusicGenerationService.fetchPlaylist() 拉取列表
  • 前端initState 异步调用,将服务器歌曲插入唱片架最前面(去重,不重复加载硬编码的 4 首)
  • 当前服务器上有 19 首 AI 生成歌曲 + 4 首原始歌曲,重编译后唱片架不再丢失

故事生成接入豆包 API

  • 后端server.py 新增 /api/create_story 接口SSE 流式调用豆包 Chat API
  • 模型Doubao-Seed-1.6-litedoubao-seed-1-6-lite-250515),关闭深度思考加快响应
  • Promptprompts/story_director.md儿童故事创作大师400-600 字JSON 输出
  • 前端串联
    • StoryGeneratorModal 返回选中素材 Map角色/场景/道具分类)
    • DeviceControlPage 把素材传给 StoryLoadingPage
    • StoryLoadingPage 调真实 APISSE 实时进度(连接→生成→解析→完成)
    • StoryDetailPage 无需改动,已支持接收动态故事数据
  • 故事保存:生成的故事文本保存到 Capybara stories/ 目录
  • 错误处理超时提示、API 异常、空内容兜底,错误时显示"返回重试"按钮

唱片架高度优化

  • 限制唱片架弹窗高度为 3.5 行,超出部分滚动查看
  • 半行露出作为"还有更多"的视觉提示

Windows 编码问题全面修复

  • sys.stdout / sys.stderr 强制 UTF-8Windows 默认 GBK 导致中文乱码)
  • Doubao API 请求体手动 json.dumps + encode("utf-8"),避免 requests 用 GBK 编码
  • SSE 流使用 ensure_ascii=True,确保前端 jsonDecode 100% 正常
  • resp.encoding = "utf-8" 强制豆包返回流按 UTF-8 解码
  • 已清理 4 个编码出错时保存的乱码故事文件

书架加载历史故事

  • 后端/api/stories 接口扫描 Capybara stories/ 返回所有故事标题+内容
  • 前端initState 异步拉取,历史故事排在预设故事之后
  • 保存联动:新生成的故事保存后,真实标题+内容即时加入书架(不再用 mock 数据)
  • 封面区分预设故事显示封面图AI 生成的故事显示淡紫渐变"暂无封面"占位
  • 乱码过滤API 层自动跳过无中文标题的异常文件

第九次对话完成的工作2026-02-10

TTS 语音合成全链路接入(上次对话完成,此处补记)

  • 后端server.py 新增 /api/tts 接口WebSocket 流式调用豆包 TTS V1 API
  • 音色:可爱女生(ICL_zh_female_keainvsheng_tob
  • 前端组件PillProgressButton(药丸形进度按钮)替代旧 RingProgressButton
    • 5 种状态idle / ready / generating / completed / playing / paused / error
    • 进度环动画 + 音波动效 + 发光效果
  • TTSService 单例:后台持续运行,切页面不中断生成
  • 音频保存:生成的 TTS 音频保存到 Capybara audio/ 目录
  • 暂停/续播修复:显式 seek 到暂停位置再 play解决 Web 端从头播放的 bug
  • 按钮状态修复:新增 ready 状态,未播放过的音频显示"播放"而非"继续"
  • 自动播放控制:仅在用户停留在故事页时自动播放,切出页面不自动播

音乐总监 Prompt 优化

  • 歌名去重复:移除固定示例("温泉咔咔乐"等),改为"根据场景自由发挥,不要套用固定模板"
  • 效果AI 每次为相似场景生成不同歌名,唱片架不再出现一堆同名歌曲

唱片架播放状态可视化

  • 卡片高亮:当前播放的歌曲整张卡片变暖金色底 + 金色边框 + 阴影
  • 标题标识:播放中的歌曲标题前加小喇叭图标 + 金色加粗文字
  • 音波动效:播放中的唱片中心叠加跳动音波 CustomPaint 动画

气泡持续显示当前歌名

  • 播放期间气泡始终显示"正在播放: xxx",不再 3 秒后消失
  • 直接点播放按钮(非从唱片架选歌)也会显示歌名
  • 暂停时气泡自动隐藏,切歌时自动更新
  • 使用 _playStickyText 机制,即使其他临时消息弹出后也会恢复播放信息

调研 AI 音乐生成平台

  • 对比了 MiniMax Music 2.5现用、Mureka昆仑万维、天谱乐、ACE-Step
  • 发现 Mureka 有中国站 APIplatform.mureka.cn质量评测超越 Suno V4
  • 用户的朋友用的 Muse AI App 底层就是 Mureka 模型
  • MiniMax 文本模型abab6.5s-chat价格偏高可考虑切豆包
  • 歌词生成费用极低(每次约 0.005 元主要成本在音乐生成1 元/首)

正在做的 / 待办

  • 故事封面方案待定(付费生成 or 免费生成)
  • 考虑将音乐生成从 MiniMax 切换到 Mureka用户在评估中
  • 考虑将歌词生成的 LLM 从 MiniMax abab6.5s-chat 切到豆包(更便宜)
  • 长歌名 fallback 问题LLM 返回空 song_title 时用了用户输入原文当歌名,后续可优化

重复登录页说明

  • lib/features/auth/presentation/pages/login_page.dart — 路由使用,带 Riverpod 认证
  • lib/pages/login_page.dart — 完整 UI 实现,作为参考保留
  • 后续需要把 pages/ 版本的完整 UI 合并到 auth 版本

三步走计划

  1. 修已转换页面的 UI 差异(本次完成)
  2. 🔄 构建音乐创作页面(进行中)
  3. 转换剩余 WebView 页面Profile、收藏、帮助等

开发环境备忘

  • 预览方式flutter run -d web-server --web-port=PORT,用 Cursor 内置浏览器看
  • 镜像源:需设 PUB_HOSTED_URLFLUTTER_STORAGE_BASE_URL 为国内源
  • Android 模拟器已装好VTX 已开,但编译慢,非最终验收不用
  • Flutter web-server 当前运行在端口 8080

关键文件索引

文件 说明
PRD.md 产品需求文档
design_system.md 视觉设计规范
airhub_app/migration_report.md HTML→Flutter 迁移进度 & UI 差异
music-creation.html 音乐创作页面 HTML 原版
阶段总结/task.md "我的"模块任务清单
阶段总结/phase_summary.md 音乐电台功能阶段总结
阶段总结/session_progress.md 👈 就是本文件,开发进度存档