Skip to content

音频标注

在 Potato 中切分音频,在交互式波形上标记时间区段,支持播放速度控制、缩放,以及用于转写的逐段问题。

Potato 的音频标注工具让标注者通过基于波形的界面切分音频文件,并给时间区段分配标签。

功能

  • 波形可视化
  • 按时间创建区段
  • 给区段分配标签
  • 可变速的播放控制
  • 缩放与滚动导航
  • 键盘快捷键
  • 服务端波形缓存

基本配置

默认模式要求标注者划出区段并给每一段打标签,所以说话人分离任务只需要写好标签:

yaml
annotation_schemes:
  - name: "speakers"
    description: "Mark when each speaker is talking"
    annotation_type: "audio_annotation"
    labels:
      - name: "Speaker 1"
        color: "#3B82F6"
      - name: "Speaker 2"
        color: "#10B981"

配置选项

字段类型默认值说明
name字符串必填该标注的唯一标识
description字符串必填展示给标注者的说明
annotation_type字符串必填必须是 "audio_annotation"
mode字符串"label"标注模式:"label"、"questions" 或 "both"
labels列表视情况label 或 both 模式下必填
segment_schemes列表视情况questions 或 both 模式下必填
min_segments整数0至少需要的区段数
max_segments整数null允许的最大区段数(null 表示不限)
zoom_enabled布尔值true启用缩放控件
playback_rate_control布尔值false显示播放速度选择器
waveform布尔值true显示波形
spectrogram布尔值false在波形旁显示声谱图
spectrogram_options字典—声谱图的 FFT 大小、频率范围和配色
source_field字符串""当一个条目带有多个音频文件时,本方案所标注的展示字段

方案缺了它所在模式需要的输入,Potato 就拒绝加载,所以 label 和 both 缺 labels 会失败,questions 和 both 缺 segment_schemes 会失败。

标签配置

给每个标签配一个 key_value,标注者不用离开波形就能给区段打标签;在区段一个接一个出现的说话人分离任务里,这一点很要紧:

yaml
labels:
  - name: "speech"
    color: "#3B82F6"
    key_value: "1"
  - name: "music"
    color: "#10B981"
    key_value: "2"
  - name: "silence"
    color: "#64748B"
    key_value: "3"

标注模式

标签模式(默认)

区段拿到类别标签。每个区段回答的都是同一个单选问题时,用这个模式:

yaml
annotation_schemes:
  - name: "emotion"
    description: "Label the emotion in each segment"
    annotation_type: "audio_annotation"
    mode: "label"
    labels:
      - name: "happy"
        color: "#22C55E"
      - name: "sad"
        color: "#3B82F6"
      - name: "angry"
        color: "#EF4444"
      - name: "neutral"
        color: "#64748B"

问题模式

每个区段回答专门的问题。segment_schemes 里的子方案就是普通的标注方案,只是按区段逐个渲染,所以每个子方案都要写齐它自己那种类型需要的字段,比如 likert 量表需要 size、min_label 和 max_label:

yaml
annotation_schemes:
  - name: "transcription"
    description: "Transcribe each segment"
    annotation_type: "audio_annotation"
    mode: "questions"
    segment_schemes:
      - name: "transcript"
        annotation_type: "text"
        description: "Enter the transcription"
      - name: "confidence"
        annotation_type: "likert"
        description: "How confident are you?"
        size: 5
        min_label: "Not confident"
        max_label: "Very confident"

两者兼用模式

把打标签和逐段问卷结合起来。每个区段都要标注者既选标签又填一份表单,所以只在确实两样都要的那一遍标注里用它:

yaml
annotation_schemes:
  - name: "detailed_diarization"
    description: "Label speakers and add notes"
    annotation_type: "audio_annotation"
    mode: "both"
    labels:
      - name: "Speaker A"
        color: "#3B82F6"
      - name: "Speaker B"
        color: "#10B981"
    segment_schemes:
      - name: "notes"
        annotation_type: "text"
        description: "Any notes about this segment?"

全局音频配置

Potato 在服务端计算波形数据并缓存,因为浏览器要自己渲染波形,就得先把整个文件下载下来解码。缓存在配置文件里设置:

yaml
audio_annotation:
  waveform_cache_dir: "waveform_cache/"
  waveform_look_ahead: 5
  waveform_cache_max_size: 1000
  client_fallback_max_duration: 1800
字段默认值说明
waveform_cache_dir—存放缓存波形数据的目录
waveform_look_ahead5预先计算的后续条目数量
waveform_cache_max_size100缓存波形文件的最大数量
client_fallback_max_duration1800没有可用缓存波形时,浏览器愿意渲染的最长文件时长(秒)

标注者翻条目的速度快过服务端预计算时,调高 waveform_look_ahead;研究涉及的文件多过缓存容量时,调高 waveform_cache_max_size。

示例

说话人分离

说话人分离最能体现播放速度的价值:标注者会放慢音频,好把边界卡在说话人切换的位置,又会在某个人连说很久的地方加快播放:

yaml
annotation_schemes:
  - name: "diarization"
    description: "Identify who is speaking at each moment"
    annotation_type: "audio_annotation"
    mode: "label"
    labels:
      - name: "Interviewer"
        color: "#8B5CF6"
        key_value: "1"
      - name: "Guest"
        color: "#EC4899"
        key_value: "2"
      - name: "Overlap"
        color: "#F59E0B"
        key_value: "3"
    zoom_enabled: true
    playback_rate_control: true

声音事件检测

设置 min_segments: 1 可以拦住标注者提交一段什么都没标的录音。只有在每段录音都至少含一个事件时才用它:

yaml
annotation_schemes:
  - name: "sound_events"
    description: "Mark all sound events"
    annotation_type: "audio_annotation"
    labels:
      - name: "speech"
        color: "#3B82F6"
      - name: "music"
        color: "#10B981"
      - name: "applause"
        color: "#F59E0B"
      - name: "laughter"
        color: "#EC4899"
      - name: "silence"
        color: "#64748B"
    min_segments: 1

转写校对

把自由文本字段和一个质量评分配在一起,就记录下了转写为什么没被改动,输出里也就能把干净的区段和听不清的区段区分开:

yaml
annotation_schemes:
  - name: "transcription_review"
    description: "Review and correct the transcription for each segment"
    annotation_type: "audio_annotation"
    mode: "questions"
    segment_schemes:
      - name: "transcript"
        annotation_type: "text"
        description: "Enter or correct the transcription"
      - name: "quality"
        annotation_type: "radio"
        description: "Audio quality"
        labels:
          - "Clear"
          - "Noisy"
          - "Unintelligible"

已经有转写文本了?

上面这些都是从一张空白波形开始的:标注者听音频、划边界、给听到的内容打标签。如果转写文本已经存在,无论来自 Whisper 还是下载的字幕,该走的是另一条路。Potato 能读 21 种转写和字幕格式,把每一轮发言渲染成与音频同步的对话气泡,标注者于是给已有的区段打标签,而不是重新划一遍。

json
{"id": "int_001", "conversation": {"audio": "media/int_001.mp3",
                                   "transcript": "media/int_001.srt"}}

格式清单见转写格式,完整流程见标注 Whisper 转写。两样都需要时,波形切分和转写标注也可以放在同一个任务里跑。

键盘快捷键

按键操作
Space播放/暂停
← / →前后跳 5 秒
[ / ]设置区段起点/终点
Enter创建区段
Del删除区段
+ / -放大/缩小
0适应视图

在 label 和 both 模式下,每个带 key_value 的标签还会占一个自己的按键。

数据格式

输入数据

数据文件里要写上音频文件的路径或 URL:

json
[
  {
    "id": "audio_001",
    "audio_url": "https://example.com/audio/recording1.mp3"
  },
  {
    "id": "audio_002",
    "audio_url": "/data/audio/recording2.wav"
  }
]

把 text_key 指向存放音频路径的字段,因为 Potato 交给标注组件的就是这个字段:

yaml
item_properties:
  id_key: id
  text_key: audio_url

输出格式

json
{
  "id": "audio_001",
  "annotations": {
    "diarization": [
      {
        "start": 0.0,
        "end": 5.5,
        "label": "Interviewer"
      },
      {
        "start": 5.5,
        "end": 12.3,
        "label": "Guest"
      },
      {
        "start": 12.3,
        "end": 14.0,
        "label": "Overlap"
      }
    ]
  }
}

问题模式下,区段里会带上嵌套的回答:

json
{
  "start": 0.0,
  "end": 5.5,
  "transcript": "Hello and welcome to the show.",
  "quality": "Clear"
}

支持的音频格式

  • MP3(推荐)
  • WAV
  • OGG
  • M4A

实践建议

  1. 预先缓存波形 - 数据集较大时使用服务端缓存
  2. 开启播放控制 - 变速有助于精确切分
  3. 使用键盘快捷键 - 比点击快,标注者的视线也能一直留在波形上
  4. 明确边界的定义 - 说清楚什么算区段的起点和终点
  5. 选择合适的模式 - 分类用 "label",细致标注用 "questions"
  6. 限制区段数量 - 用 min_segments 保证覆盖