Skip to content
Announcements2 min read

Potato 2.7.1:转写稿本来就有了

Potato 2.7.1 直接读取 21 种转写和字幕格式,可以从媒体文件旁边的并列文件里加载它们,还附带一个转换器,把一整个 ASR 输出目录变成可以直接标注的数据文件。

Potato Team

几乎没有人是带着一堆裸音频、别的什么都没有来找标注工具的。他们带来的是转写稿。有人把 Whisper 跑在了一整个访谈目录上。有人从一百场会议报告里扒下了字幕。有人接手了一批 TextGrid,来自一个 2019 年就结束的田野调查项目。

然后工具让他们去写一个转换脚本。

Potato 2.7.1 要做的就是把这一步去掉。它直接读取 21 种转写和字幕格式,可以从躺在媒体文件旁边的文件里加载它们,而不要求你把所有内容都粘进一个数据文件里;如果你最后确实想要一个数据文件,它也带了一个转换器。

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 工具已经把文件按一个合理的布局写好了:媒体在这儿,转写稿就在它旁边。没有什么好理由逼你把这套结构压平成一坨数据,所以现在你可以直接指过去:

json
{"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,然后把结果写出来:

bash
potato transcripts ./whisper_out --media-dir ./audio -o data/interviews.json

--dry-run 什么都不写,只告诉你它找到了什么,而当一份转写稿渲染成一整块分不开的东西时,这也是第一个该跑的命令:

text
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_dialoguespeech_transcriptvoice_interactiontiered_annotation 过去各自用自己的方式解析转写数据、各自接受不同的格式子集,而没有人说得清为什么。它们现在共用一个归一化器,所以任何一个接受的格式,四个都接受。

已有配置不受影响。每个方案都保留了旧的解析逻辑作为回退,之前能用的每一种转写形状现在还是逐字节能用。

tiered_annotation 还多了一个可选的转写播种功能。把 transcript_field 指向你的转写稿,就会有一层带着预填内容出现,于是标注者是在修正一份已有的对齐,而不是从零开始重新切分语音:

yaml
  - 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 的原生输出。这些请先自行转换。我们把这份清单公开出来,是因为一份什么都不排除的“支持格式列表”并不值几个钱。

文档

升级

bash
pip install --upgrade potato-annotation==2.7.1

你不需要改任何配置。Potato 以前接受的每一种转写形状,现在还是照样接受。