YouTube Shorts 자동화

자막 싱크 — edge-tts VTT 전환

기존 subtitle-worker는 오디오 전체 길이를 텍스트 글자 수로 나눠서 각 자막의 시작/종료 시간을 계산하는 방식이었다.

구현이 단순하다는 장점이 있지만, 실제 발화 속도는 단어마다 다르다. 긴 문장에서 자막이 점점 밀리는 문제가 생길 수밖에 없었다.

edge-tts에는 --write-subtitles 옵션이 있다. 이걸 쓰면 단어 단위 타이밍이 담긴 VTT 파일을 뽑을 수 있다. EdgeTTSAdapter.ts에서 이 옵션을 활성화하고, 생성된 VTT 파일을 S3에 업로드한 뒤 subtitleVttS3Key를 SQS 메시지에 실어 subtitle-worker로 넘기도록 했다.

subtitle-worker(processor.ts) 쪽에서는 parseVttEntries → buildSrtFromVtt 경로를 추가했다. VTT 키가 있으면 실측 타임스탬프 기반 SRT를 생성하고, 없으면 기존 글자 수 비례 방식으로 폴백한다.

// processor.ts 핵심 분기
if (subtitleVttS3Key) {
  const vttContent = await downloadFromS3(subtitleVttS3Key);
  const entries = parseVttEntries(vttContent);
  return buildSrtFromVtt(entries, subtitleLines);
}
// fallback: 문자 수 비례 방식
return buildSrtByCharRatio(audioduration, subtitleLines);

추가로 splitEntry 함수에서 마지막 청크가 8자 미만이면 앞 청크에 병합하도록 수정했다. 한 단어짜리 자막이 혼자 떠 있는 경우가 없어져서 가독성이 눈에 띄게 좋아졌다.

두 워커 모두 package.json에 zod 의존성이 추가됐는데, VTT 파싱 결과 검증용이다.