Potato 2.7.1:转写稿本来就有了
Potato 2.7.1 直接读取 21 种转写和字幕格式,可以从媒体文件旁边的并列文件里加载它们,还附带一个转换器,把一整个 ASR 输出目录变成可以直接标注的数据文件。
几乎没有人是带着一堆裸音频、别的什么都没有来找标注工具的。他们带来的是转写稿。有人把 Whisper 跑在了一整个访谈目录上。有人从一百场会议报告里扒下了字幕。有人接手了一批 TextGrid,来自一个 2019 年就结束的田野调查项目。
然后工具让他们去写一个转换脚本。
Potato 2.7.1 要做的就是把这一步去掉。它直接读取 21 种转写和字幕格式,可以从躺在媒体文件旁边的文件里加载它们,而不要求你把所有内容都粘进一个数据文件里;如果你最后确实想要一个数据文件,它也带了一个转换器。
Potato 2.7.1
进来 21 种格式,出去一个模型
从 6 种涨上来的。完整清单在转写格式页面,粗略说是:九种 ASR 输出(Whisper JSON、WhisperX 及其他带说话人分离的 JSON、whisper.cpp、Whisper TSV、AWS Transcribe、Deepgram、AssemblyAI、Rev.ai、SPoRC),六种字幕格式(SubRip、WebVTT、SubStation Alpha、TTML 和 DFXP、YouTube json3、YouTube srv1/srv2/srv3),三种来自强制对齐领域的格式(NIST CTM、Praat TextGrid、ELAN EAF),再加三种通用形状,留给完全来自别处的数据。
对齐类格式是我们最高兴的一项补充。导出到 EAF 和 TextGrid 本来就有,所以分层标注现在可以双向往返:把已有的对齐拿进来,在 Potato 里改好,再送回 ELAN 或 Praat。
识别是按数据的形状来做的,而不是按文件扩展名,这意味着一个叫 captions.txt 的 WebVTT 文件照样能被解析成 WebVTT,也意味着同一份转写稿无论是内联的还是从磁盘读的,都不用改配置。
只要来源提供,词级时间戳和分段置信度都会被保留。像 CTM、Deepgram、AssemblyAI 这些天然是词级的格式,会按说话人变化加一个停顿阈值分组成话轮。
不管进来的是什么格式,出来的都是这个
并列文件
你的 ASR 工具已经把文件按一个合理的布局写好了:媒体在这儿,转写稿就在它旁边。没有什么好理由逼你把这套结构压平成一坨数据,所以现在你可以直接指过去:
{"id": "int_001", "conversation": {"audio": "media/int_001.mp3",
"transcript": "media/int_001.srt"}}路径相对 task_dir 解析,并和其他所有配置路径一样要过同一套目录穿越校验。如果你的数据里确实存着一行内联转写稿、而它碰巧长得像文件名,用 transcript_is_path: false 可以把这套启发式关掉。
实际的好处是你的转写稿依然是文件。你可以 diff 它们、重新生成它们、把它们交给别人,而不是让一份副本化石般封在某个 JSON 数组里。
给另一种情况准备的转换器
有时候你确实想要一个数据文件。potato transcripts 会 glob 一个目录,按文件名主干把每份转写稿和它的媒体配对,从文件名推出条目 id,然后把结果写出来:
potato transcripts ./whisper_out --media-dir ./audio -o data/interviews.json--dry-run 什么都不写,只告诉你它找到了什么,而当一份转写稿渲染成一整块分不开的东西时,这也是第一个该跑的命令:
Scanned 3 file(s):
interview_01.json Whisper JSON 42 turns 891.4s undiarized
interview_02.json WhisperX JSON 51 turns 1120.8s 2 speaker(s): SPEAKER_00, SPEAKER_01
interview_03.json Whisper JSON 38 turns 754.2s undiarized
3 item(s), 131 turn(s).
某个文件被报成 plain text,几乎总是因为一个 Whisper 的 .txt 混进了 .json 输出里。.txt 里根本没有任何时间信息,不重跑模型就找不回来。我们收到的“为什么我的转写稿看起来不对”的反馈里,大部分都是这一条造成的。
--emit-config 会在数据文件旁边打印一份配套的 config.yaml。
四个方案共用一套词汇
audio_dialogue、speech_transcript、voice_interaction 和 tiered_annotation 过去各自用自己的方式解析转写数据、各自接受不同的格式子集,而没有人说得清为什么。它们现在共用一个归一化器,所以任何一个接受的格式,四个都接受。
已有配置不受影响。每个方案都保留了旧的解析逻辑作为回退,之前能用的每一种转写形状现在还是逐字节能用。
tiered_annotation 还多了一个可选的转写播种功能。把 transcript_field 指向你的转写稿,就会有一层带着预填内容出现,于是标注者是在修正一份已有的对齐,而不是从零开始重新切分语音:
- annotation_type: tiered_annotation
name: tiers
source_field: audio_url
media_type: audio
tiers:
- name: utterance
labels:
- name: speech
color: "#7c3aed"播种出来的区间在标注者真正编辑之前不会被保存,所以没人动过的种子永远不会被误记成人工成果。
Potato 仍然不做的事
它不做转写,也不做说话人分离。ASR 跑在上游。Potato 读的是你的流水线产出的东西。
这一点会被反复问到,因为 Potato 确实会跑一个本地 Whisper 模型,用在 Think-Aloud 模式里,那是用来录标注者一边干活一边说话的。那是一个面向你的标注者的采集功能,不是面向你的语料。两回事,同一个词。
词级置信度在来源提供时会被解析并保留在数据模型里,但目前还没有查看它的界面。
还有一些格式根本没有解析器:SAMI、MicroDVD、SubViewer、Transcriber .trs、EXMARaLDA、CHAT/CHILDES、单独的 RTTM,以及 Montreal Forced Aligner 或 Gentle 的原生输出。这些请先自行转换。我们把这份清单公开出来,是因为一份什么都不排除的“支持格式列表”并不值几个钱。
文档
- 转写格式 —— 每种格式及其识别规则、归一化的话轮模型、并列文件规则、配置键,以及按真实症状编排的排查指南
- 如何标注 Whisper 转写文本 —— 该保留哪个输出文件,以及为什么说话人分离是一个单独的决定
- 如何标注 YouTube 字幕 ——
yt-dlp,以及自动生成的字幕能支持和不能支持什么 - Transcript Format Ingestion —— 一个把六种格式并排展示的可运行示例设计
升级
pip install --upgrade potato-annotation==2.7.1你不需要改任何配置。Potato 以前接受的每一种转写形状,现在还是照样接受。