Skip to content

YouTube 자막을 주석하는 방법

yt-dlp로 자막을 내려받아 Potato에서 주석하는 방법. 자동 생성 자막으로 할 수 있는 일과 없는 일, 영상 처리 방법, 직접 만들지 않은 자료를 재배포하기 전에 확인할 것들.

yt-dlp로 자막을 내려받고 Potato를 그 파일로 향하게 하세요. 먼저 알아둘 것은, 자동 생성 자막에는 문장 부호도 화자 표시도 없고 줄바꿈 위치에도 의미가 없어서 무엇을 제대로 주석할 수 있는지가 제한된다는 점입니다. Potato는 yt-dlp가 내놓는 모든 자막 형식을 읽습니다. 전체 목록은 전사 형식에 있습니다.

동영상 플랫폼은 자연스러운 발화의 크고 편리한 공급원입니다. 자막은 그 발화를 텍스트로 만들고, 텍스트는 가볍고 옮기기 쉽고 주석하기도 쉽습니다. 문제는 모든 자막이 같은 종류의 물건이 아니라는 점이고, 같은 것으로 취급하는 지점에서 자막 기반 프로젝트는 대개 어긋나기 시작합니다.

자막은 어떻게 내려받나요?

yt-dlp는 자료를 받든 받지 않든 자막을 가져올 수 있습니다.

bash
# Human-written subtitles, if the uploader provided any
yt-dlp --write-subs --sub-langs en --skip-download <URL>
 
# Auto-generated captions
yt-dlp --write-auto-subs --sub-langs en --sub-format vtt --skip-download <URL>

Potato는 vtt, srt, json3, ttmlsrv1, srv2, srv3 변형을 모두 읽으므로 어떤 --sub-format을 고르든 해석됩니다. 무엇을 남기고 싶은지로 고르세요. json3은 단어 단위 시간을 유지하고, WebVTTSubRip은 사람이 읽고 손으로 고치기 편합니다.

사람이 만든 자막과 자동 생성 자막은 무엇이 다른가요?

텍스트 편집기에서는 비슷해 보이지만, 주석 재료로서는 아주 다르게 움직입니다.

사람이 만든 자막자동 생성 자막
문장 부호있음없거나 믿기 어려움
문장 경계의미 있음임의적
화자가끔, <v Name> 태그로전혀 없음
단어 단위 시간없음있음(json3)
축어성읽기 편하게 압축되는 경우가 많음실제 발화에 더 가까움

어느 쪽이 절대적으로 낫다는 이야기가 아닙니다. 사람이 만든 자막은 읽기 좋지만 가독성을 위해 손질되어 있어서 군말이 빠지고 반복이 줄고 때로는 문장이 통째로 다시 쓰입니다. 자동 생성 자막은 축어에 더 가까워서 사람들이 실제로 어떻게 말하는지를 다룰 때 필요한 쪽이지만, 문장 부호 없는 흐름으로 도착합니다.

자동 생성 자막에는 무엇을 주석할 수 있나요?

자동 생성 자막 위에 문장 단위 주석 설계를 얹지 마세요. 자막 조각의 경계는 문장이 끝난 곳이 아니라 자막 창이 가득 찬 곳에 떨어집니다. 자동 생성 자막의 한 조각은 표시상의 산물이지 언어 단위가 아닙니다. 주석자에게 "문장마다" 평가하라고 하면 각자 조용히 서로 다른 문장 경계를 고르게 되고, 일치도 수치는 원래 재려던 것이 아니라 그 차이를 재게 됩니다.

현실적인 선택지는 두 가지입니다.

  • 자막 조각을 그대로 주석하세요. 각 조각에 해당하는 라벨을 붙이고, 단위가 임의적이지만 일관되다는 점을 받아들이면 됩니다. 주제, 어떤 현상의 유무 등 조각만 보고 판단할 수 있는 것이라면 문제없습니다.
  • 앞단에서 다시 분할하세요. 문장 부호 복원 모델이나 문장 부호를 찍는 음성 인식을 거친 뒤 시간을 다시 맞춥니다. 손은 더 가지만 진짜 단위를 얻습니다.

사람이 만든 자막이라면 이 문제는 거의 사라집니다. 경계를 읽으면서 사람이 놓았기 때문에 대개 절 단위를 존중합니다.

영상은 어떻게 하나요?

자막은 작고 재배포하기 쉽습니다. 영상은 대개 그렇지 않습니다. 선택지는 세 가지입니다.

bash
# Media hosted somewhere your annotators can reach
potato transcripts ./captions --media-url-prefix https://cdn.example.org/video -o data/talks.json
 
# Media downloaded locally as audio only
yt-dlp -f 'ba' -x --audio-format mp3 -o './audio/%(id)s.%(ext)s' <URL>
potato transcripts ./captions --media-dir ./audio -o data/talks.json

세 번째는 자료를 아예 두지 않는 것입니다. 자료 없는 전사도 주석에는 문제가 없고, 주석자는 듣는 대신 읽습니다. 그럴 계획이라면 지침에 그렇게 적으세요. 그러지 않으면 주석자는 재생기가 없는 것을 결함이라고 생각하고 그렇게 보고합니다.

Warning: 직접 만들지 않은 것을 재배포하기 전에 권리를 확인하세요. 자신의 연구를 위해 자막이나 자료를 내려받는 것과, 그 자료를 주석자 집단에 제공하는 것은 다른 문제이며, 플랫폼 약관과 저작권, 소속 기관의 규정이 모두 관련됩니다. 파이프라인을 만든 뒤가 아니라 만들기 전에 정리하세요.

과제는 어떻게 구성하나요?

변환 도구는 이미 정규화된 전사를 담은 데이터 파일을 만듭니다.

bash
potato transcripts ./captions --media-dir ./audio -o data/talks.json
json
{
  "id": "talk_01",
  "conversation": {
    "audio": "audio/talk_01.mp3",
    "turns": [
      {"turn_id": "t0", "speaker": null, "start": 0.0, "end": 4.2,
       "text": "so the thing about caption windows is"}
    ]
  }
}

자동 생성 자막에서 얻는 것은 speaker: null입니다. 그런 차례는 선택기와 함께 Unassigned로 표시되어, 주석자가 들으면서 화자를 지정할 수 있습니다.

회색 빗금 배경의 자동 생성 자막 차례 세 개. 드롭다운 화살표와 함께 Unassigned로 표시되고 각 차례에 질문이 붙어 있다.자동 생성 자막에는 화자 정보가 없어서, 주석자가 고를 때까지 각 조각은 Unassigned로 남습니다

yaml
annotation_task_name: "Talk Annotation"
task_dir: .
data_files:
  - data/talks.json
 
item_properties:
  id_key: id
  text_key: conversation
 
instance_display:
  fields:
    - key: conversation
      type: audio_dialogue
      label: "Captions"
      span_target: true
      display_options:
        show_timestamps: true
        allow_speaker_assignment: auto
 
annotation_schemes:
  - annotation_type: radio
    name: cue_topic
    description: "What is this caption window about?"
    labels: [setup, argument, example, aside]
    turn_level: true
    turn_binding:
      field: conversation

turn_level: true는 질문을 영상 전체가 아니라 각 자막 조각에 붙입니다. 가진 것이 조각뿐일 때는 이것이 옳은 단위입니다. 실행은 다음과 같습니다.

bash
python potato/flask_server.py start config.yaml -p 8000

변환 도구를 아예 쓰지 않고 데이터 파일이 디스크의 자막 파일을 직접 가리키게 할 수도 있습니다. 나머지 흐름은 같으니 Whisper 전사를 주석하는 방법을 보세요.

더 읽을거리