尝试解决 whisper 识别字幕的痛点,大家帮忙看看还能不能优化一下 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
340746
V2EX    分享创造

尝试解决 whisper 识别字幕的痛点,大家帮忙看看还能不能优化一下

  •  
  •   340746 220 天前 via Android 2400 次点击
    这是一个创建于 220 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用 whisper 时发现识别的时间戳不准,用 whisperx 识别的字幕又太长,设置切段后发现效果更差,尝试用语言理解模型按句意切段后匹配字符级时间戳,结果发现时间戳根本不准,麻了
    只能靠自己来解决问题了,先说一下代码的逻辑:
    1 、用 ffmpeg 提取视频中的音频,切成 20 分钟的段,用 UVR5 分离人声,再拼成完整音频。
    2 、对音频进行 VAD 识别,标出有人声活动的部分,得到 VAD 时间戳,这也是最终字幕的时间戳。
    3 、按照 VAD 结果切段音频,每 30 分钟一组,每组内的音频用 2 秒的静音段隔开,得到新的音频段。并按照上述逻辑计算出一组新的时间戳。 4 、将合成后的新音频送入 whisper 识别,得到带时间戳的识别结果,用计算后的时间戳和识别结果进行匹配,得到字幕。
    5 、匹配后的结果时间戳是错误的,按照对应关系把字幕同步到 VAD 时间戳,得到最终的字幕结果。
    6 、分批把字幕喂给 Gemini 进行翻译,每次喂 100 行熟悉上下文,之后分 10 次获取翻译。
    目前最大的问题是 whisper 识别容易出错,不知道如何设置 hotwords 和 prompt ,翻译逻辑也有问题,识别结果包含很多单独成行的语气词,每次翻译 100 行无法提供足够的上下文,应该考虑用滑动窗口或者过滤掉字符量小的行。
    代码在 github.com/4evergr8/ASMRASR ,欢迎大家批评指正,谢谢

    9 条回复    2025-05-13 00:06:04 +08:00
    xmoiduts
        1
    xmoiduts  
       220 天前
    这不巧了,同样在做两个 side-project ,一个是云 GPU 人声分离 https://github.com/xmoiduts/vocal-extract-transcribe-bot , 一个是 whisper 音频提取字幕 https://github.com/xmoiduts/OpenAI-API-transcriber 。题主您比我走得远,我还没走到发现时间轴不准的阶段,因为我不打轴,全文投成专栏。

    我的方案选型有少量不同:

    之前尝试从 UVR 代码里扒一个专用于提取干声的东西,失败,UVR 的陈年代码耦合太紧了。
    后来我转用了 MSST https://github.com/ZFTurbo/Music-Source-Separation-Training ,同样的模型,推理命令行超级直观。

    切段由于受 whisper api 单文件 25MB 的限制,我做了按 码率 和 时长 双要素判定每片长度的逻辑。相邻两片之间重合 9 秒(随便定的),合并逻辑还没做,目前实际是我手工合并。
    我完全不准备用 whisper 自动断的句,只用单词模式[timestamp_granularity: word],后续接入一个大模型断句。
    - 不建议用 gemini 思考模型断句,会爆 COT ,但 gemini flash 系列不错。
    翻译推荐 claude 系列,但是要注意 claude 3.5 系会偷懒,3.7 系会有些幻觉,要在提示词中加以监工,claude 有足够的反思能力。
    unclemcz
        2
    unclemcz  
       220 天前 via Android
    平时用来识别英文播客字幕,还没碰到 whisper 时间轴不准的问题。
    GobyHsu
        3
    GobyHsu  
       219 天前
    @unclemcz 我之前用 whisper 的感觉是,其要求人声纯净度比较高,多点杂音就识别不出来,而且还容易识别出呵呵呵之类的一堆没必要作为字幕的语气词
    340746
        4
    340746  
    OP
       219 天前
    @GobyHsu #3 确实,动作片的战斗场景的识别结果很糟糕
    340746
        5
    340746  
    OP
       219 天前
    @unclemcz #2 日语的时间轴也不是很偏,最大的问题是句子太长,无法断句
    xmoiduts
        6
    xmoiduts  
       219 天前 via Android
    @340746 gemini 2.0 flash 试试

    10:直播听写粗分句
    作用:对直播文稿粗略分行
    建议模型:gemini 2 flash ( ai studio )理由:8k 输出( ctx 2000 行左右上下文行号开始异常); 不推荐 2.5 pro thinking ,想得太多反而无法完成工作爆 COT

    ```
    你是一个文字处理 ai ,

    将以下听写文稿按照以下标准来断行,不要修改也不要校对文稿内容。
    在每行之前加入行(L for Line)号,例如 `{L1} 正文正文正文` ,请忠实断行并正常分配行号,只输出非空的行。
    原文中的换行仅用于限制原文单行长度,请勿视为带有语义

    模拟 YouTube 字幕的显示效果,遵循以下规则:
    - 每行字符数不超过约{拉丁字母:80 ,中日类:35}个字符。
    - 优先在自然停处进行断句,例如句号、逗号、语气词等。
    - 尽量保持语义完整性,避免在词组中间断句。
    - 短句可以单独成行。
    - 长句可以跨多行,但要在合适的位置断开。
    - 保持视觉上的整洁,避免过长或过短的行。
    - 考虑朗读时的自然停顿和节奏。

    输出到 multiline text block 中
    ```
    {前五行断行结果}

    --process-full-text? -Y
    --line-number-start = L467 # (这个是给 claude 的监工代码,实际没什么用,删了也行)

    {大段未断行正文}
    xmoiduts
        7
    xmoiduts  
       219 天前 via Android
    @GobyHsu 识别出错误的语气词,是不是因为那段时间没有语音,只有静音或 BGM 。whisper 在这种情况下会有幻觉。
    340746
        8
    340746  
    OP
       218 天前
    @xmoiduts #7 应该不太可能,我对音频进行了处理,去掉了背景音乐,只保留人声,每段人声间固定间隔 2 秒
    340746
        9
    340746  
    OP
       218 天前
    @xmoiduts #6 试过对结果分句,whisperx 的字级时间戳也是偏的,字幕根本没法看
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3002 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 410ms UTC 12:36 PVG 20:36 LAX 04:36 JFK 07:36
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86