SuperAPI AI 工具集

media-transcription

办公与效率

查看项目

更新于 10-16 09:10

技能介绍

Media Transcription 是一套针对 NAS 上原始会议媒体的持久化、事件驱动转录流水线,版本标识为 media-transcription-pipeline-v2。它由 Inngest 负责编排,语音识别(分块 ASR)使用 MLX Whisper,说话人分离使用 pyannote 进行整文件处理;两者都作为分离的本地 actor 进程运行,因此任何 Inngest 步骤都不会在推理期间一直保持请求打开。该设计于 2026-07-11 建立,背景是 v1 单体方案因请求绑定的 2 小时超时而失败,并遭遇 Whisper 幻觉循环。

运行位置(硬性约束)

仅在 flagg 主机的 worker 上运行(hostFunctionDefinitions,launchd com.joel.system-bus-worker)。需要直接 NFS 挂载 /Volumes/badass-media 以及 rig 检出。

本地推理实现位于 ~/Code/joelhooks/transcript-rig(公开仓库 joelhooks/transcript-rig;可用 TRANSCRIPT_RIG_ROOT 覆盖路径)。NAS 上的原始媒体不可变,流水线只写入派生工件。

从任何其他集群机器:发送事件(Inngest 会将其路由到 flagg 的 worker),或 SSH 到 flagg 检查磁盘上的状态。

启动转录

joelclaw send media/transcription.requested -d '{ "requestId": "req-'$(uuidgen | tr 'A-Z' 'a-z')'", "sourcePath": "/Volumes/badass-media/joel/meetings/<meeting-dir>" }'

requestId 是幂等键,应始终生成新的;重复使用的 id 会被静默去重。可选标志:"publish": false、"index": false(两者默认均为 true)。

sourcePath 必须位于 /Volumes/badass-media/ 下,否则运行会以 NonRetriable 失败。

监控

joelclaw event <event-id> 可获取 run id;joelclaw run <run-id> 查看步骤追踪。编排器步骤保留 NN- 前缀,用于 pi job-monitor 组件(packages/pi-extensions/inngest-monitor)。

进度事件:media/transcription.chunk.completed(每块,含 index/total/cached),终止事件为 media/transcription.completed 或 .failed。

磁盘上的真实状态(flagg):<rig>/.transcript-rig-work/<artifactId>/

orchestration/plan.v1.json — 分块计划(requestId、tracks、chunk ids)

orchestration/actors/<chunkId>/status.v1.json — actor 心跳/状态

orchestration/actors/<chunkId>/actor.log — 推理 stdout/stderr

state.v1.json — rig 阶段(staged → transcribed → … → complete)

editorial/transcript.{md,txt,srt,vtt,tsv} — 最终输出

已发布结果:<sourcePath>/derived/transcripts/current.v1.json 指针加工件目录。

取消

joelclaw send media/transcription.cancelled -d '{"requestId": "<the-request-id>"}'

取消所有运行(cancelOn)并触发 transcription-cleanup-v1,该流程会依次 SIGTERM、等待 10 秒、SIGKILL 活跃 actor 进程组(通过 ps 校验身份,安全应对 PID 复用),并写入 orchestration/cancelled.v1.json,阻止新的 actor 生成。可选地包含 artifactId 以跳过计划扫描。

恢复/重新驱动

使用新的 requestId 和相同的 sourcePath 重新发送 media/transcription.requested。磁盘上所有有效的部分都会被采纳,不会重新计算:

整轨 raw/asr/<sourceId>/asr.json 通过重复筛查 ⇒ 该轨完成。重复的会被隔离(.rejected-<ts>)并重新分块。

已有的分块 WAV 布局(raw/chunked/<sourceId>/chunks/NNN.wav)会被采纳;偏移量由 ffprobe 重新计算。有效的分块 out/<i>/asr.json ⇒ 缓存命中,不生成 actor。

说话人分离 raw/diarization/<sourceId>.jsonl(首行可解析)⇒ 缓存命中。

如果工件此前被取消,需先移除 orchestration/cancelled.v1.json。

失败模式(在 actor 状态/运行错误中带类型)

repetitive_output:Whisper 幻觉循环在 collapse 后仍存在(解码大部分为填充)。动作:重试会重启 actor;确定性循环通常在 collapse-then-screen 后通过。检查分块 WAV——真正静音/损坏的音频会诚实失败。

inference_required:快速 rig 阶段(resume --no-inference)发现缺失的 claim check。动作:推理未完成/采纳;检查分块状态。

cancelled_by_signal:actor 的子进程死于非主动发起的 SIGTERM/SIGKILL(组杀、操作员或 Bun 的进程内信号分派竞态)。动作:取消/回收期间属预期;孤立出现意味着有人手动杀进程。

actor stalled:心跳超过 3 分钟未更新。动作:看门狗自动杀掉并重试。

chunk_result_missing:聚合未找到有效的分块输出。动作:分块所有重试均失败;查看其 actor.log。

mount_unavailable:NFS 挂载中断。动作:发出 media/transcription.blocked;重新挂载并重新驱动。

设计不变量(不要破坏)

ASR 输出用 parseAsrJson 解析(mlx_whisper 会输出裸 NaN)。

重复筛查采用 collapse-then-screen(screenWithCollapse):连续重复片段折叠为一;折叠比例 >50% ⇒ 解码失败。聚合持久化折叠后的形式。

ASR actor 以 --condition-on-previous-text False --hallucination-silence-threshold 2 运行;说话人分离使用 MPS(可用 TRANSCRIPT_RIG_DIARIZE_DEVICE=cpu 退出)。

waitForEvent 结果会在代码中针对生成的 actorId 校验——开发模式 Inngest 服务器会泄漏匹配表达式之外的外部事件。

已知开发服务器缺口:并发键(transcription-gpu limit 1)未强制执行;在 Inngest 服务器升级前,预计会出现并行 whisper。

代码:packages/system-bus/src/transcription/ 加 packages/system-bus/src/inngest/functions/{media-transcription-pipeline,transcription-asr-chunk,transcription-diarize,transcription-cleanup}.ts。