Skip to content

fix: 接通 youtube-api 分支的转录时限预算时长(预算值不变,纯可见性) - #178

Merged
zj1123581321 merged 1 commit into
mainfrom
card/vta-ytapi-duration-261005
Oct 5, 2026
Merged

zj1123581321 merged 1 commit into
mainfrom
card/vta-ytapi-duration-261005

Conversation

@zj1123581321

Copy link
Copy Markdown
Collaborator

背景

#173 把「准入探测出的时长」接到了通用分支,但 youtube-api 分支(transcription.py:2056 准入 + 2105 转录调用)当时按卡面锁定刻意没接,所以那条路径至今仍是 duration=unknown fallback=sdk_auto,本仓日志看不到它的时长与预算。

当时不敢接的理由是「会改变非 generic 路径的预算行为」。这个理由现在不成立了——主干 SDK pin 已是 492fe191,上游 PR #71 把 SDK 自动预算也改成了 4 倍:

#173 当时 现在
SDK pin b0818dc 492fe191
SDK 自动预算 max(120, duration+60) duration*4+120
不传 media_duration 的实际预算 时长+60 时长×4+120
本仓显式传的预算 时长×4+120 时长×4+120

传与不传算出来的预算值完全相同,本 PR 只换来可见性与解耦,不改变任何任务的预算值。

执行前的前置核实(卡面「不成立就停手」那条)

核实前发现该 worktree 无 .venv,而主仓 .venv 正是本仓历史上的错位版本(858c6b9),
因此先 uv sync 重建本 worktree 自己的环境再核实 pin:

.venv/.../capswriter_asr-0.1.0.dist-info/direct_url.json
  commit_id = 492fe191e3f9568ea178b61970c732c9d37c4e29
pyproject.toml:87 pin = 492fe191      ← 一致

SDK 自动预算公式原文(capswriter_asr/client.py:430-441):

def _auto_budget(duration: float) -> float:
    """...
    93 秒音频的一次真实识别约需 306 秒(~3.3× 实时因子),旧公式
    ``max(120, 时长 + 60)`` 给到的 153 秒会在识别仍在跑时就误杀(issue #69),
    故改为时长 4 倍 + 120 秒。
    """
    return duration * 4 + 120

本仓公式(capswriter_client.py:122-123, 260):

DEADLINE_REALTIME_FACTOR = 4.0
DEADLINE_OVERHEAD_SECONDS = 120.0
deadline = media_duration * DEADLINE_REALTIME_FACTOR + DEADLINE_OVERHEAD_SECONDS
情形 走的公式 结果
传 media_duration=d 本仓 _transcription_deadline d * 4.0 + 120.0
不传(None) SDK _auto_budget d * 4 + 120

改动

全部落在 youtube-api 分支,行 2056–2116,共 +12/-2:

-                            _ensure_audio_track(local_file)
+                            probed_media_duration = _ensure_audio_track(local_file)
…
+                                extra = (
+                                    {} if probed_media_duration is None
+                                    else {"media_duration": probed_media_duration}
+                                )
                                 transcription_result = transcriber.transcribe(
-                                    local_file, temp_output_base
+                                    local_file, temp_output_base, **extra
                                 )

通用分支所在的 2440–2540 区间零 hunk(#173 的成果原样保留)。

新增 tests/unit/test_youtube_api_duration.py(269 行 / 18 用例),走真实入口
process_transcription,复用 test_transcription_audio_admission.py 的 wired fixture 与
替身类,不依赖 /tmp fixture、不依赖 PATH 上的 ffmpeg。

锁定决策

  1. 先核实后实施:SDK 自动预算公式不满足前提就停手上报(已满足)。
  2. None 时不传:保持既有两参调用、kwargs == {},不得无条件传 None
    (既有调用形状有外部 mock 锁着)。
  3. 直接用 _ensure_audio_track 的返回值,不新增第二次探测、不新增缓存字段。
  4. 准入拒绝语义不变:4 条拒绝路径 + 结构畸形分支逐字未动。
  5. 不碰 FunASR 路径(use_speaker_recognition=True):它走 FunASRSpeakerClient,
    不经过 CapsWriter 的 deadline_total。

一处诚实说明:时长口径

SDK _auto_budget 的 d 来自解码后的 samples 数(samples_total / _RAW_SAMPLE_RATE),
本仓的 d 来自 ffprobe 的 format.duration。公式系数与量级相同,但两者不会逐位相等
(转码重采样/截断带来小数级差异)。这是 #173 起就存在的既有口径,本 PR 只是把同一口径
扩展到 youtube-api 分支——换句话说,这轮改动是让两条 CapsWriter 路径收敛到同一口径,
而不是引入第三种。若日后要求严格一致,需单开一卡统一,不宜夹带。

验收证据

  • 全量 make test → 3677 passed / 3 skipped / 0 failed,exit=0(3 个 skip 是
    test_capswriter_samples_total_contract.py 的既有 skip,需真实录音样本,与本 PR 无关)。
  • 窄测 + 关联四套(新文件 / fix: 时长探测在 generic/recorder 路径失效——复用准入探测结果供转录预算使用 #173 / 预算 / 准入):110 passed。
  • 变异反证(主脑独立复核):删掉新传参 → 2 failed, 16 passed
    (test_youtube_api_duration_reaches_transcriber、test_probe_duration_is_the_real_parsed_value);
    恢复后 18 passed,工作树干净。
  • 执行器另做变异 2(无条件传 media_duration=None)→ 该参数化 9 条全红,
    证明「不得无条件传 None」有独立判据锁着,不是靠通读代码。
  • 执行性证明:SingleProbeRunner 对第二次子进程调用当场 AssertionError(不新增探测);
    每个用例先断言 rec.methods == ["fetch_for_transcription"],杜绝「改动落在通用分支、测试假绿」。

本 PR 没做什么

  • 没改预算公式(capswriter_client.py 一字未动)。
  • 没碰通用分支、没碰 FunASR 路径、没新增探测、没改 _ensure_audio_track 本身。
  • 没碰 transcriber/**、downloaders/**、config/**、api/routes/**、CI 配置。
  • 没声称解决 4.9 小时长音频问题——那个根因在上游服务端接收循环(全片 82% 处静默停止,
    见 zlxlabs/CapsWriter-ASR-Server#76),本 PR 完全没碰。

youtube-api 分支的音轨准入早就在跑 ffprobe 并解析出 format.duration,
但返回值被丢弃,Transcriber.transcribe 只拿两参调用,于是该路径恒走
SDK 自动预算,本仓日志里始终是 duration=unknown fallback=sdk_auto。

把 _ensure_audio_track 的返回值接住,传给既有的 media_duration 实参:
不新增探测(仍是准入那一次 ffprobe),不改预算公式,不碰通用分支,
不动 FunASR 路径(它不经过 deadline_total,接时长无意义)。

预算值不变:传参走本仓 duration*4.0+120.0,不传走 SDK 492fe191 的
_auto_budget 同为 duration*4+120,两边数值相同,本卡只换来可见性与
「SDK 再改公式时本仓显式值仍优先」的解耦。

probed_media_duration 为 None 时保持两参调用形状,不无条件传 None。

Agent-Executor: ocgo-bunny-pi
Agent-Model: space-bunny-free
Agent-Effort: high
Dispatch-Id: dlg-20261005-130606-63736f
Task-Id: VideoTranscriptAPI-20261005-06
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

Required Gate v2 — 状态面板

当前状态:pass · 可合并

当前裁决:code_pass / primary_pass

历史可能不完整:1 个制品处理失败:URLError;1 个历史重建预算耗尽

Gate 历史(v1;来源为持久化 gate_terminal 制品)

Run Attempt Head 状态 收件人动作
37318638699 1 e2c4bda pass 可合并

历史行按 run_id + run_attempt 去重并只增不删;删除本评论后可由 gate_terminal 制品重建。

@zj1123581321
zj1123581321 merged commit d968df8 into main Oct 5, 2026
12 checks passed
@zj1123581321
zj1123581321 deleted the card/vta-ytapi-duration-261005 branch October 5, 2026 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant