Skip to content

ASR and Video Analysis zh

Hermes Agent edited this page Oct 1, 2026 · 2 revisions

ASR 与视听精读

English | 中文 | 日本語 | 한국어 | Español | Português | Русский

给无字幕的 B 站 / YouTube 视频点 📎,browsa 在页面里拿音频、跑云端 ASR,产出带 [mm:ss] 的转写(或对视频本身做「视听精读」:语音+画面的图文文档)。ASR 供应商目前是火山方舟(Volcengine Ark)。

为什么是「下载 → 上传文件」,不是 URL 直传

URL 直传对两家平台都是死路:B 站 CDN 签名 URL 绑定用户会话 IP(火山服务器 fetch 不到);YouTube 是 PO token + 会话 + cookie 绑定(服务端 fetch 403)。所以必须由浏览器(IP 匹配签名的那个客户端)自己 fetch 字节,再把字节上传到 Files API——这是根因级结论,不是可选路线之一。

管线(八步)

  1. ATTACH_PAGE 返回 {mode:'asr-pending'}(延时落库交接)。
  2. buildAsrPendingCtx 平台分派:B 站重注入 content script 读流;YouTube 调 MAIN world __browsaFetchFreshYouTubeStreams(现签 PO token 的新 /player 请求)。
  3. 选流:最低码率纯音频(反正要转码),但时长 < 真实时长 90% 的流拒绝(截断流真事故);优先 AAC-LC(decodeAudioData 可能拒 HE-AAC)。
  4. DNR 注入下载头(lib/sidepanel/media-headers.js):B 站 Referer;YouTube 还要 Origin 改写 + cookie(googlevideo 403 无头扩展 fetch,实测教训)。
  5. 转码 16kHz 单声道 WAV:B 站 m4s 是纯音频 fMP4 容器,Ark 按内容误判成「视频」→ Invalid video_url → 状态 failed;WAV 是实测唯一稳的。Web Audio 解码 + 手写线性插值重采样(纯函数,Node 可测)。
  6. 上传 Files API(≤512MB multipart):expire_at = 30 天、语义化文件名;browsaArkFileCache 缓存 file_id(键 = base|key指纹|assetId),30 天内同一视频免重传(复用前 GET 探活)。
  7. 轮询文件状态 → /responses 流式转写(input_audio.file_id),提示词强制 [mm:ss] 逐行。
  8. ATTACH_ASR_CONFIRM 落库 + videoSrc 盖章(时间戳胶囊/时间线抽屉的前提)。

截断防御——绝不静默存半截转写(真事故驱动的四层)

  1. /responses 显式 max_output_tokens: 65536(模型默认输出帽会从中间安静截断)。
  2. 解析 SSE 的 incomplete / finish_reason:'length' 信号 → truncated:true。
  3. 完整性门:末时间戳 < 视频时长 90% → 抛错 fail-open 到纯文本 + toast(不落库)。
  4. 洞门:largestTranscriptGapSec 区间并查时间线,最大空洞 > 300s → 拒(实测 81 分钟视频中间丢过 1 小时)。

视听精读(视频本身进模型)

input_video(durl 合一时音频随视频)+ 可选独立 input_audio,max_output_tokens 65536 流式产出图文文档。提示词纪律(真机校准多轮):任何第二个声音出现就标说话人、可识别身份附名、广告压一行、关键帧只截论证依赖的图(软密度提示 + 显式不拍清单;唯一硬顶是客户端 SAFETY_KEYFRAME_CAP 24——防病态输出,不是质量旋钮)。[图N] 标记与页面图片/时间线抽屉共用一套锚定协议。

平台差异速记

  • B 站:/x/player/wbi/v2 字幕轨 + CDN 字幕 JSON 主动拉,与 CC 开关无关。
  • YouTube:timedtext 只对播放器自己的 POT 请求吐内容;直拉 captionTracks.baseUrl 得空体。拦截器只有 CC 开过一次才捕得到。兜底 stage 2c:驱动播放器字幕模块触发一次授权请求(屏幕闪一下字幕是预期),轨道为空的判定按 videoId 负缓存。
  • 无字幕判定看结构化 noTranscript 标志,不是 ## 字幕 文本标记(auto 模式的 Jina 兜底会吞文本标记——真 bug)。

接第二家 ASR 的缝(已预留)

lib/asr-providers.js(元数据注册表,UI 零改动)+ attach-asr.js 的 ASR_ADAPTERS(同签名 {transcribeAudio, analyzeVideo})。难点永远在端点侧的文件上传能力(长音频不可能 base64 内联)。曾完整实现过千问 DashScope 适配器一天后撤(浏览器→OSS 不稳,git 历史在 b55380…de8ee2f);tabCapture 边播边录被否(暂停/跳段=静音,没播过的视频没法转写)。


源头:AGENTS.md「Video ASR subtitles」「YouTube transcript acquisition vs POT」节;attach-asr.js 头注释(完整来龙去脉)。同步于 2026-10-01。

Clone this wiki locally