网球进化 开源 · v0.1

开源 · MIT · 在你自己的 Mac 上跑

47 分钟的网球录像,
3 分 49 秒的角标集锦。

网球进化会把一段很长的手机录像里每个回合单独剪出来,把拍数、地点、拍摄钟点和片源时间点烧进画面,交付前逐项自检。素材全程留在你自己的机器上——不上传、不注册、不经过任何云。

这次真实运行:47 分 29 秒的 iPhone 源片进去,从 5 个最长回合拼出一条 3 分 49 秒的成片出来。

01 / 角标

同样的素材,说话的是角标。

每一段片段都带着这一回合的拍数、球馆、钟点,以及它在源片里的位置——所以哪怕脱离了上下文,一段片段依然说得清楚。

demo-reel.mp4

切换时会保留播放位置,你能看到同一帧带角标和不带角标的样子。 PNG 叠加 · Pillow

02 / 成片

先看成片,再拿自己的录像跑一遍。

这里的每一段视频都是工具的真实输出,不是效果图。hero 上的数字来自一次 47 分钟的手机录像;下面播放器里是一段更短的 CC0 素材,走的是同一条流水线。

reel_labeled.mp4 · h.264 · 1280×720 · 1:39 · 角标已烧录

示例素材:CC0 片段,走的是同一条流水线——源片 2:16,四个回合,成片 1:39。

无损片段 · 010:28

clip-01.mp4

逐位流拷贝,角标已烧进画面。

无损片段 · 020:19

clip-02.mp4

切在关键帧上,尾部不会丢参考帧。

无损片段 · 030:23

clip-03.mp4

不重编码,也就没有代际损失。

这些是无损流拷贝——切在关键帧上,没有重编码。示例素材本身是 SDR;换成真实 iPhone HDR 录像时,10 位 HLG 画面和旋转元数据会原样保留。

03 / 流水线

四步,其中一步是「拒绝走捷径」。

有意思的决定都在边缘上:一刀允许切在哪里、几段怎么拼起来、什么才算真的做完。

  1. 拿来一份高光列表

    任何能给出时间区间的工具都能用:sliceapp 导出的文本、你自己的检测器,或者手敲的一份 txt。检测刻意放在流程之外。

    txt · json
  2. 切在关键帧上,而不是毫秒上

    流拷贝是逐位精确的,HDR、10 位色深和旋转元数据都能留住;切点会对齐到最近的关键帧,所以整条流水线从不为了「更准」去重编码片段。

    -c copy
  3. 一次成型地拼接

    回合先 trim 再 concat,合成一次编码。最顺手的那种 concat demuxer 写法实测会留下 1.01 秒的永久音画偏移和 HEVC 坏参考帧,所以这个工具拒绝它,并把问题报出来。

    trim → concat
  4. 自检通过才算交付

    每个产物都要检查:解码零错误、起始偏移为零、音画时长一致、首尾不是黑帧、音频不是静音。任一项失败,命令就以非零退出码结束。

    manifest.json

04 / 产物

你会拿到什么。

一次运行一个目录。没有藏起来的工程文件:成片、片段、角标图层和报告就摆在一起。

  • reel_labeled.mp4带角标的成片——你要上传的就是这个。
  • reel_plain.mp4同一版拼装,画面干净,留给你自己加字幕。
  • clips/一个回合一条无损切片,原始 HDR,方向已烧进画面。
  • labels/*.png透明角标图层,任何剪辑软件里都能复用。
  • highlights.normalized.json这次实际用到的片段清单。
  • manifest.json全部参数和每一项自检结果。
manifest 就是契约:每个参数、每一项自检结果,机器可读。 非零退出码代表自检失败——脚本和 Agent 不用把视频看完,也能相信这次运行。
解码零错误 起始偏移 音画时长一致 预期时长 首尾非黑帧 音频非静音

角标放大看

网球回合画面上放大的角标:拍数、球馆、钟点,以及这一回合在源片里的时间点。
拍数
14这一回合的击球数,也是排序依据。
地点
用 --place 传进去的值——这段示例里是 Riverside Tennis Club。
钟点
录制开始时间加回合偏移,时区由你指定。
片源
0:02这段回合在原文件里的位置。

05 / 安装

一行命令安装。

还没发布到 PyPI,直接从仓库装。ffmpeg 要自己在 PATH 里——工具不会偷偷替你打包 40 MB 的 ffmpeg。

终端 — 安装 + 运行
# 先装 ffmpeg:brew install ffmpeg  ·  sudo apt install ffmpeg fonts-noto-cjk
pipx install git+https://github.com/bobobo2026/tennis-evolution

# 高光列表可以来自 sliceapp、你自己的检测器,或者手敲
tennis-evolution all IMG_5155.MOV --highlights highlights.txt --top 5 --place "你的球馆" --timezone Asia/Shanghai --outdir out

需要 Python 3.11 以上和 ffmpeg/ffprobe,macOS 与 Linux 均可。源码、issue 和完整的流水线笔记在 GitHub。

06 / 隐私

素材永远不出本机。

一场完整比赛里有你的朋友、你的球馆和你的失误。本地优先不是口号:这里根本没有能接收素材的服务器,也没有队列要排。

素材只留在你的硬盘上

不用账号,不用排队

免费且 MIT 开源

支持 iPhone HDR 视频

07 / 常见问题

经常被问到的几个问题。

下面是短答案。更长的推理——包括具体的 ffmpeg 参数和踩过的坑——都在仓库里。

我需要自己做击球检测吗?

不需要。任何能给出时间区间的列表都能直接用:sliceapp 导出的文本、你自己的检测器,或者手敲的一份 txt。检测刻意放在流程之外——一个只为某间球馆混响调过参的击球计数器,会让整条流水线变脆。

支持 iPhone 拍的 HDR 视频吗?

支持。无损切片会原样保留 HLG、10 位色深和旋转元数据,合集也保留 HLG 色彩标签和 10 位深度。Dolby Vision 的动态元数据 x265 写不回去,重编码时会丢;HDR10/HLG 基础层完好。

只能在 macOS 上用吗?

CLI 在 macOS 和 Linux 上都能跑,需要 ffmpeg 在 PATH 里、Python 3.11 以上。打包好的 Mac 应用在计划中,可以先去 GitHub 点个 Star。

不安装能先看效果吗?

这个页面上所有片段都是预渲染的,可以先看再决定。刻意不做在线生成:那意味着要把你一小时的录像传到别人的服务器上。

跑一次要多久?

47 分钟源片、5 个回合,在 M 系列 Mac 上大约 3 到 5 分钟,绝大部分时间花在那一次 x265 编码上。本机网页版会显示每个阶段的实时进度。

收费吗?

不收费。MIT 开源,源码在 GitHub:不要账号、没有试用期、没有遥测。

还有别的?在 GitHub 上开个 issue ↗