【Code With SOLO】4天131次提交,从零做完一款 iOS 网球 AI 训练 App


摘要

用 TRAE SOLO 在 4 天内,独自完成了一款 iOS 网球训练 AI 分析 App 的核心开发。

从架构设计、SwiftUI 界面、Supabase 后端、视频处理管线,到 AI 动作分析对接、多语言国际化……共 131 次 Git 提交、57 个 Swift 文件、约 12,000 行代码,全程只有我一个人,SOLO 是我唯一的队友。

这篇帖子不是教程,是一份真实的过程记录——包括顺的地方,和卡壳的地方。


背景:我为什么做这个

我打网球,但我没有教练,也没有人帮我看动作。市面上的训练 App 要么太简单,要么太贵。我想做一个能用手机摄像头录视频、自动分析击球动作、追踪训练进步的 App——TennisFlow

问题是我一个人开发,工作量非常大:

  • iOS 端要做 UI、本地视频处理、相机权限、通知……
  • 后端要搭 Supabase,写 RLS 安全策略、Storage 管理、Edge Function……
  • 还要对接 AI API 做动作评分,支持 5 种语言……

以前这种项目要么外包,要么组团队。这次我想试试:TRAE SOLO 能不能真正顶一个协作者?


实践过程

Day 1(4月9日):搭架子,5次提交

项目从零开始。先和 SOLO 讨论整体架构:SwiftUI 用什么状态管理方案?要不要引入 ViewModel 层?

SOLO 给出的建议是:用 @Observable + .environment() 注入共享状态,不引入 ViewModel 层,保持 View 层干净。它直接帮我实现了两个核心单例:

  • AuthManager:处理登录态、Keychain 存储、JWT 自动刷新
  • LanguageManager:5 语言 i18n 体系,t(_ key:) 统一调用

这个决策贯穿了后续所有开发,事后证明是对的——没有一个页面因为状态管理出现混乱。


Day 2(4月11日):最猛的一天,57次提交

这一天我几乎一直在和 SOLO 协作,从早到晚。

最复杂的:视频处理管线

我描述了需求:“用户上传训练视频,需要提取关键帧、去重、后台上传,完成后通知用户,任何一步失败都要有反馈。”

SOLO 帮我设计了完整的链路:

VideoFrameExtractor(自适应抽帧)
    → FrameProcessor(感知哈希去重)
        → BackgroundUploadManager(actor,后台并发)
            → UNUserNotificationCenter(本地通知)

其中有一个细节我觉得特别好用——自适应抽帧参数

视频时长 抽帧间隔 最大帧数
< 5s 0.3s 12帧
5–15s 0.5s 15帧
15–30s 1.0s 20帧
30–60s 2.0s 20帧
> 60s 3.0s 15帧

这个设计解决了两个极端:短视频不漏关键帧,长视频不爆内存。我自己想不到这么系统,是 SOLO 主动提出来的。

当天踩的坑:session 卡在 processing

上传完视频,session 状态一直是 “processing”,AI 分析结果始终不来。我把 Edge Function 的日志贴给 SOLO,它很快定位出问题:

豆包 Responses API 的响应结构多了一层 output,代码里解析路径写错了。

// 错误写法
let content = response["choices"][0]["message"]["content"]

// 正确写法(豆包 Responses API 特有结构)
let content = response["output"]["choices"][0]["message"]["content"]

这个 Bug 藏得很深,我自己查文档估计要花半天,SOLO 10 分钟搞定。

当天另一个高光:数据库迁移

原来 Storage 文件全放在用户目录下,路径混乱。需要迁移到规范的子目录结构:

{userID}/{sessionID}/frames/frame_N.jpg   ← 关键帧
{userID}/{sessionID}/images/photo_N.jpg  ← 用户照片
{userID}/{sessionID}/video/original.mp4  ← 压缩视频

SOLO 帮我写了一个 Supabase Edge Function 做一次性迁移(copy + delete),成功迁移了 43 个历史文件。这是我最没把握的环节,全程 SOLO 主导,我主要负责 review 和确认。


Day 3(4月12日):64次提交,功能收尾

这一天节奏很快,主要在补细节:

媒体 EXIF 提取 + 地点选择

用户上传照片/视频时,自动读取 EXIF 里的拍摄时间和 GPS 坐标,填充到训练记录的日期和地点字段。多张图片时间不一致?弹出冲突解决界面。我描述需求,SOLO 给出了完整的 MediaMetadataExtractor actor 实现。

国际化迁移

项目里有 200+ 个硬编码中文字符串需要迁移到 i18n 体系,支持中/英/法/西/日 5 种语言。光是找出来、归类、写 5 种语言翻译就很繁琐。SOLO 帮我生成了完整的审查报告(CSV 清单 + 优先级分类),当天完成了 P0 优先级的 70+ 个字符串迁移。

一个让我很触动的细节

CHANGELOG 是 SOLO 坚持要我维护的——每次提交前它都会提醒我更新。一开始我觉得麻烦,但现在翻回去看,整个开发脉络清清楚楚,哪天做了什么、解决了什么问题,全都有记录。这个习惯是 SOLO "逼"出来的,我觉得值。


Day 4(4月13日):5次提交,扫尾

处理遗留的 P0/P1 级 Bug:

  • Timer 内存泄漏(onDisappear 没有置 nil)
  • 媒体 URL 签名失败时静默吞掉错误,改为显示 Retry 按钮
  • 后台上传失败无反馈,改为弹 Alert
  • 设计色违规(直接用 Color.orange,改为 tfWarning 主题 token)

这些 Bug 全是 SOLO 在 code review 环节主动标出来的,不是我发现的。


成果展示

4天数据:

指标 数量
Git 提交 131 次
Swift 文件 57 个
代码行数 ~12,000 行
工作日 4 天

主要功能:

  • OTP 手机登录 + GitHub OAuth + Sign in with Apple + JWT 自动刷新
  • 视频关键帧提取 → 感知哈希去重 → 后台上传 → AI 动作评分
  • 训练时间轴(日期分组 + 日历过滤)
  • SessionDetail:评分环 + 关键帧展示 + 灯箱浏览
  • 媒体 EXIF 自动填充 + 地图地点选择
  • Supabase 完整后端(RLS、Storage、Edge Functions)
  • 5 语言国际化(中/英/法/西/日)
  • Sentry 错误监控

总结:SOLO 在这个项目里真正做了什么

说实话,我开始之前对 AI 编程助手有点保留——觉得它可能只能写简单代码,复杂逻辑还是得自己上。

用完这 4 天,我改变了看法。

SOLO 在这个项目里扮演了几个不同角色:

架构顾问:在关键决策点给出有理有据的方向,不是乱给建议,是真的理解 SwiftUI 的约束。

模块级实现者:把需求描述清楚,它能给出结构完整、边界清晰的实现——不是代码片段,是可以直接跑的模块。

主动 Code Reviewer:它会主动指出潜在的内存泄漏、静默错误、硬编码违规,不用我专门去问。

调试加速器:把错误现象和日志描述给它,定位速度远超我自己翻文档。

但有一点我想讲清楚:SOLO 放大的是你已有的工程能力,而不是替代判断力。 我需要 review 每一段代码,需要理解架构决策背后的原因,需要知道什么是好的实现。如果你自己没有判断力,AI 生成的代码只会让你更混乱。

最实用的协作方式我总结成一句话:把需求描述成数据流,不要只说"帮我实现 XX 功能"

比如不说"帮我做视频上传",而是说:

“用户点提交后,流程是:①提取关键帧 ②感知哈希去重 ③后台上传到 Supabase Storage ④触发 Edge Function 调用 AI ⑤任何步骤失败要有用户可见的反馈,不能静默失败。”

这样 SOLO 给出的实现会干净很多,边界也清楚。


4天131次提交,一个人做完了。TRAE SOLO 是认真的队友。

更多还在开发中,如果你也在做独立项目,欢迎交流。

部分截图


个人训练日记

训练分析详情

网球知识库

个人设置页