精准转写:利用 Whisper 处理音视频转文字不完全指南
前阵子女朋友去读研,授课是全英的,加之又有很多专业名词,有时就会出现理解能力跟不上讲课速度的情况。
因此借助课堂回放/录音复习也变成了一项每周必做的工作,但是完全回看一个三小时长的课程显然是不现实的,所以,音视频转文字就成了必选项。
我是飞书妙记的会员,所以遇到了这个需求,我马上想到先用妙记试试。
然而,尝试转录的结果表明,妙记在专业课程上的转录准确度相当差,无法满足通过文字转录来提高复习速度的需求。
其他商用服务(如通义听悟、讯飞听见、Notta 等)的转录效果和飞书妙记差不太多,大体原因有三点:
基于问题 2 和 3 ,我放弃了继续寻找其他商业 ASR 服务的想法。
因为平时业务里我自己基于 OpenAI 发布的 Whisper API 写了不少工作流,所以我又试了试 Whisper(Large-v2)的转录效果。——非常惊艳,甚至连符号的写法(theta_i^t)它都转写了出来。
这里简要介绍一下 Whisper,Whisper 是 OpenAI(没错,还是 chatGPT 背后的公司)在 2022 年 9 月开源的音频转文本的模型,它的转写精确度非常高。
但想使用 Whisper 进行转写也并非易事。它有两种实现方式:云端 Or 本地。
云端转写的优势在于不会受到本地机器性能的限制,且速度相对较快。但它存在两个问题:
本地转写的话倒是没有上述两个问题,但本地转写的麻烦之处在于:
且不论是云端转还是本地转,上述方案只是实现了音频转文字的过程,但却少了一个直观的用户界面,帮助我们快速通过文字理解音频内容。
一个理想的转文字结果页面可以借鉴妙记的设计:
Potplayer 的字幕浏览器倒是能变相实现这个效果,但它文本一长就被截断了,也就是勉强能用的程度。
后来某天逛小众软件的时候发现了 Memo AI 的内测,它的功能刚好能满足我的需求。
这可真是刚想瞌睡就有人送枕头。有了 Memo 之后,下面就可以介绍我们整个转录工作的流程了。
音视频文件主要有两种来源:学校提供的课程视频回放、手机/录音笔的录音结果。
某些课程在 Canvas LMS 平台上提供了视频回放的功能,但却没有视频下载的选项。
不过网站视频的下载也并不困难,视频是基于 m3u8 的,并且没有加密。只需要获取到 m3u8 地址,随后使用 m3u8下载器就能把视频下载到本机。
至于提取视频url的工具,我推荐使用 xifangczy/cat-catch: 猫抓 chrome资源嗅探扩展。通过使用「猫抓」,可解决大约 80% 的网页视频下载问题。
m3u8 下载器则推荐 N_m3u8DL-CLI,一键搞定。
没有提供视频回放的课程只能通过自己录音来解决。设备不外乎两种:手机或者录音笔。
至于具体选什么设备,这里得根据自己的情况来确定。
通常,手机的远距离收音效果比较一般。在课堂这样的场合,如果不能坐在前排,老师的声音往往会被其他噪音掩盖。
录音笔的效果通常会比手机更好,一般 100-200 元的价格就可以满足需求。
如果是部分留学&专业课程场景,不建议为了实时语音转文字功能而选择某些录音笔,可能会有三个比较大的问题:
有时, 录音效果可能比较尴尬。这可能是由于手机的收音能力较弱,或者是录音位置与声源之间的距离过大。这种情况下,我们可能会遇到以下问题:
因此,在进行转录前,最好先对音频进行一些处理,这可以有效提升 Whisper 转录的效果。我主要做三个操作:人声增强、降噪、响度均衡。
具体的软件在 Windows 上我使用 Pr,在 Mac 上我使用 Final Cut Pro。
下载的课程回放视频通常都包含 20 至 30 分钟的课间休息时间,我通常会选择把这部分片段从视频里切掉。这么做有两个目的:
手动删除空白时间段内容是一种很糙的解决方案,更优雅的方案是结合声音活动检测(VAD, Voice Activity Detection)来做转写,自动忽略掉空白时间段。(开发者说 Memo 的后续版本会接入 VAD)
至于切视频,可以使用 Pr/FCP 等剪辑软件,但这种方式需要重新编码处理后的视频,比较耗时间。愿意折腾一下的话此处建议使用 ffmpeg 通过复制流的方式来做,通常 3 小时的视频文件切掉空白只需几秒钟。
核心的命令为两个:
从视频里提取特定时间段
$$ffmpeg -i "{OriFileLoc}" -ss {RangeTimeStart} -to {RangeTimeEnd} -c:v copy -c:a copy "{OriFileParDir}\temp\temp_video_{temp_video_index}{OriFileExtension}"
利用 concat 衔接多个视频(格式一致)
$$ffmpeg -y -hide_banner -vsync 0 -safe 0 -f concat -i "{OriFileParDir}\temp\fileList.txt" -c copy "{OriFileParDir}\RmBlank_{OriFileName}{OriFileExtension}"
你可以把本地文件地址丢给 chatGPT 让他直接给你生成最终的命令,抑或使用 QuickCut: Your most handy video processing software 或者我编写的 Quicker 动作。
与传统的 ASR 模型不同,Whisper 在某些情况下可以借助 Prompt 提升音频转文字的准确度。
虽然同属于 OpenAI,但 Whisper 和 chatGPT 的 Prompt 差别非常大。
如果 Whisper 的 Prompt 是 "请尽力保持每句话的完整 并给每句话都添加标点符号",你会发现这句 Prompt 没有任何作用,Whisper 的转录结果里可能还是会出现大量中断的句子,或者转录结果无标点。
这是因为 Whisper 是在尝试学习 Prompt 里的「风格(style)」,而非具体的指令。
那什么是 Prompt 的「风格」?
根据 Whisper 的 cookbook、 Whisper prompt 的 issues 和我的实际体验,Prompt 的风格可以表现在下面几个方面:
风格 1:Prompt 里是否包含标点符号。
Whisper 的转录结果有时会缺乏标点符号,这个时候你可以使用带标点符号的 Prompt 的来引导 Whisper 添加标点。
Prompt 1 是有意义的,Prompt 2 是无意义的。
不过 Whisper 也不是能每一次都学会 Prompt 的风格添加标点符号。实测在 Whisper-large v2 模型下,通常英文内容使用 prompt 可以为结果添加标点,中文内容则要看运气。
风格2:一些容易拼写错误的人名、产品名、公司名
这里比较好理解,不同的词汇可能会有同一个发音。你可以在 Prompt 里指定你希望的拼写格式。
比如一段对话里提到了张三和李四,而「张三」的音同「章三」、「樟叁」...
那 Prompt 里就可以包含 「张三,李四。」
风格3:是否包含一些填充词(filler words)
这里直接引用官方的说法来解释,翻译成中文会有点怪异。
The model may also leave out common filler words in the audio. If you want to keep the filler words in your transcript, you can use a prompt that contains them: "Umm, let me think like, hmm... Okay, here's what I'm, like, thinking."
风格4:简体中文和繁体中文
因为中文有两种,有的时候 Whisper 会把音频以繁体中文的形式转录。此时用简体中文来陈述 Prompt 大概率可以解决此问题。
一般建议 Whisper 的 Prompt 语言和转录的音频语言一致。即英文音频用英语 Prompt,中文音频用简中/繁中 Prompt。
风格5:通过对话风格的 Prompt 变相实现转录结果区分说话人
这个技巧来自于 prompt vs prefix in DecodingOptions ,有的时候会有效果。
单纯的 Whisper 模型并不能在转录结果里区分出说话人,想要区分说话人,一般会配合 Pyannote 来做。但在某些场景下,我们可以通过 Prompt 来变相实现区分说话人——每一句的转录结果都属于单个说话人,不会出现某一句的转录结果属于多个说话人的情况。
方法就是用一个对话式的 Prompt:
播客这种场景可以试试。
Whisper Prompt 的其他 Tips
因为我主要转录的是课程内容,所以我的 Whisper Prompt 通常会使用这节课的关键词列表。如果课程有讲义 pdf 文件,我会直接把它丢给 Claude,然后:
summarize the file, response me with format like :"keyword1, keyword2, keyword3,keyword4.."
如果课程没有讲义,我会手动输入几个关键词,或者直接从课本里随便挑一段话作为 prompt。
Whisper 转写需要指定模型。模型越大,转写越精准,转写速度越慢。
Memo 在 Windows 和 Mac 上都实现了 GPU 加速。
Windows
Windows 电脑如果是独显机器大部分应该没什么问题,部分显卡的测试转录速度如下:
RTX4090 显卡在 Large 模型下转录 1.2 小时音频时间为 7 分钟
RTX3080Ti 显卡在 Large 模型下转录 1.2 小时音频时间为 8 分钟
RTX3080Ti 显卡在 Large 模型下转录 0.4 小时日漫时间为 2 分钟
RTX3060 laptop 显卡在 Large 模型下转录 1.2 小时音频时间为 20 分钟
RTX3060 在 Large 模型下转录 1.2 小时音频时间为 12 分钟
6600XT 显卡在 Large 模型下转录 1.2 小时音频时间为 11 分钟
5700XT 显卡在 Large 模型下转录 1.2 小时音频时间为 15 分钟
如果你的电脑只有核显,那可能会遇到显存不足的问题。
但这里如果是 AMD 的核显,你可以尝试在 Bios 里调整显存大小。(高风险行为,谨慎操作)
游戏爆显存?显示器黑屏花屏?BIOS 没有调整选项?AMD 核显显存大小调整教程(UniversalAMDFormBrowser AMD 台式及笔记本改核显显存教程,核显还只有 512M?
我手里的笔记本是 R7-6800H,32G 内存,出厂分配 4G 作为 GPU 显存。在 Large 模型下,开启 GPU 加速后显存会占满,转录时长:音频时长大概等于 1:2 。
我尝试把显存开到 8G,跑 Whisper 时大概会占用 6G 显存,但速度相较于 4G 显存无提升。所以如果调整 Bios 的显存大小,通常调整到 4G 就足够使用了。
Mac
Intel 的机器我手上没有,主要分享一下 M 系列的机器速度。
M 系列的 GPU 加速倍数近似和 GPU 核心数成正比:
Mac GPU 核心数对比可参考 Mac processor comparison: M1 & M2 vs Intel | Macworld。
使用 Whisper GPU 加速时,除了消耗 GPU,同时也会消耗大量内存。我用 Large 模型时 Memo 占用 6.4 G 内存。
如果是在为视频创建简易的字幕文件,那到这里基本可以收工了。但如果是在为需要快速阅读全文的课程或会议等场景进行操作,那么此处可以对转写结果做一些优化,主要解决两个问题:
开发者说这两个功能未来的版本都会实现,但在没实现之前只能靠我们自己来处理了。我写了一段 Python 的脚本将原始的字幕转换成段落模式的字幕:Adjust_SubTitle: 调节 Whisper 转录生成的 srt 文件,避免一句话被分成两行,避免一句话过短。
你可以导出原始转录的 srt 文件,然后修改 AdjustSrt.py 里的 srt 文件路径,运行脚本后会自动在原始路径下生成段落模式的 srt 的字幕。最后只需重新创建 Memo 任务,同时指定需导入的音频和字幕文件即可。
因为段落模式的实现逻辑是基于原始转录结果里的标点符号,所以运行脚本的前置条件是 Whisper 生成的字幕里有标点。
除此之外,基于标点符号的段落模式只能用于只有一个说话人的情况。否则可能会导致一句话里出现了多个说话人,容易造成误解。
虽然 Whisper 结合上下文的能力很强,转写准确度非常高。但 Whisper 也有两个比较麻烦的问题:
所谓「幻觉」是指 Whisper 转录的文本和音频不相关,而是在不断重复之前的转录结果。
我体验下来目前主要是两种情况会造成幻觉:
1 比较好处理,Memo 之后会引入 VAD 自动过滤空白内容。
同时根据 Ignore repeated prompt by heimoshuiyu · Pull Request #1253 · openai/whisper 这个 issue,设定 --condition_on_previous_text False
,也就是不让 Whisper 用前文的转写结果转录后面的音频,也能降低空白引起幻觉的概率,但代价是丧失了 Whisper 在上下文理解上的优势。(开发者说后续会开放此参数。)
但 2 目前还没找到比较好的解决方案,只能是再尝试对音频调整降噪、人声增强的强度试试..
从天梯榜上看,Whisper 的英语转录效果名列前茅,而对于中文的转录效果在中等水平。
上文提到过,如果是英文音频,那合适的 Prompt 大概率可以给转写结果添加标点,但中文音频则有概率无法添加标点。此时就比较尴尬了,我也没有找到比较好的解决方案,如果有朋友知道怎么解决,欢迎评论区里分享。
我曾经尝试利用 gpt 3.5 来给生成的文本添加标点符号,但由于 gpt 也存在幻觉,它经常直接将文本合并,然后时间戳和文本就对不上了。。如果用 4 的话成本则有点高。
希望这篇分享对你有所帮助,以上。