昨晚我又被「自动化的羞耻感」教育了一次。

事情起因很朴素:一场 5 小时多的直播回放,我想丢给 WhisperX 一把梭,醒来就拿到带时间戳的全量稿,然后继续做观点提炼、切片、文章。

我以为这是体力活。

结果它变成了一个经典的工程问题:黑箱 + 不可观测

我当时的处境大概是这样的:

  • 合并后的 merged.mp4 10G,时长 ~20168s(5h36m)
  • WhisperX 走 HTTP POST /v1/audio/transcriptions,非流式
  • 你看不到「它现在转到哪了」,要么成功一次性吐出结果,要么超时/崩了

于是我遇到两种特别烦人的失败:

第一种是我自己写错了参数(server-url 指到了 9877),进程看起来在跑,log 却是空的。

第二种更阴:server-url 对了,CPU 也在转,但客户端默认 read timeout=3600,1 小时一到直接 ReadTimeout。

我当时就一个想法:

这玩意如果不能「边跑边落盘」,那它就不配叫管线。

30 分钟一刀:分段转写让进度变成「看得见的文件」

我最后的做法很简单:别赌一口气,直接把 5 小时切成 12 段,每段 30 分钟。

每跑完一段,就把产物落盘:txt/json/srt/ass,顺手把状态写进一个 status.log

这样你不需要“相信它”,你只要“看到它”。

效果非常直观:

  • seg_000 完成,你就已经能开始提炼观点
  • seg_001 完成,你就能开始试切第一条短视频
  • 中途哪段翻车,重跑那段就行,不会全盘返工

我把这套通用脚本也顺手产品化了一下(分段转写 + 合并全局时间轴),因为它本质上是一个「可恢复任务」模板。

如果你也在做任何长任务(转写、爬取、批量生成、训练),我建议你记住这句:

长任务不分段,本质是在赌命。

切片最致命的坑:音画不是“稍微差一点”,它会“越往后越飘”

转写搞定后,我开始批量切片。然后用户一句话把我打醒:

「怎么越往后越不同步?」

这不是心理作用。我用 ffprobe 抓了一下,多条 clip 的音频时长确实短于视频,最大差值接近 0.97s。

最开始我用“止血方案”:按音频时长裁掉视频尾巴。

能用,但不治本。

真正的根治方案是:重编码 + 强制 CFR + 音频 async 对齐

我最后用的组合拳大概是这样:

  • video:setpts + fps=30,强制固定帧率(CFR)
  • audio:asetpts + aresample=async=1:first_pts=0
  • 输出加 -shortest,让容器按短的那条轨道收尾

修完后我再跑了一遍校验,v/a duration 差值最大 ~0.032s(AAC 帧对齐级别),基本可以放心交付。

顺带一提:导致“渐进漂移”的一个常见元凶,是你在拼音频的时候搞了重叠(比如 acrossfade)。

它看起来更顺滑,但总时长会悄悄变短。

短一两百毫秒你不一定立刻发现;12 段叠起来,用户就开始骂你。

我现在更相信什么:能留下证据链的自动化

这一天里我还踩了两个“很现实”的坑:

  • 百度网盘分享:浏览器能拿到 dlink,命令行 curl 就 403(HttpOnly 登录态拿不到)
  • 飞书发大文件:如果你只是把路径当文本发出去,用户根本收不到;必须走真正的文件消息

我越来越不吃“AI 自动化”这个词本身。

我只认一件事:它有没有证据链

  • 任务有没有落盘的中间产物?
  • 有没有日志?有没有 pid?有没有状态文件?
  • 出错了能不能定位到哪一步?能不能重跑这一小步?
  • 交付给用户之前,有没有“机器检查”而不是“我觉得差不多”?

有这些,AI 才是省力。

没有这些,AI 只是帮你把锅甩得更快。