LLM 자막 번역 — 줄 밀림과 문장 그룹핑

만든 것2분조회

유튜브 볼 때 번역 자막을 띄워주는 확장은 이미 여럿 있습니다. 그런데 쓰다 보면 결국 유료로 넘어가고 원하는 대로 손보기도 어려워서, 직접 만들어 쓰기로 했습니다. 번역은 AWS Bedrock — 여러 LLM 을 API 하나로 부르는 AWS 서비스 — 의 작은 모델에 맡겼습니다.

자막을 LLM 으로 번역하는 과정에서 세 가지 문제를 만났습니다 — 한 줄 밀림, 속도, 그리고 어순.

배치 번역의 한 줄 밀림

자막 여러 줄을 한 번에 번역시키면 호출 수가 줄어서 좋을 것 같은데, LLM 이 줄 경계를 흐려서 3번 줄 번역이 4번 자리에 들어가는 한 줄 밀림이 생깁니다.

번호를 붙인 JSON 으로 줘도 실기기에서 계속 재현됐습니다. LLM 은 “몇 번째 줄” 을 정확히 지키는 걸 생각보다 못합니다.

결국 줄 단위로 개별 번역하는 쪽으로 갔습니다. 앞뒤 문맥은 같이 주되 번역 결과는 그 한 줄만 받으니, 애초에 밀릴 자리가 없어집니다.

전체 선행 번역 — 느리고 낭비

영상 전체를 미리 번역하면 3시간짜리는 십수 분이 걸리고, 사용자가 보지도 않을 뒷부분까지 번역해서 그만큼 과금됩니다.

그래서 재생 위치를 따라가며 번역합니다. 지금 재생 지점 앞 14줄 창만 번역하고 재생이 진행되면 창도 따라가는데, 앞으로 건너뛰면(시킹) 창도 그쪽으로 옮겨갑니다.

몰입형 번역기가 “즉시” 로 느껴지는 것도 전부 빠르게 번역해서가 아니라, 지금 볼 부분만 미리 번역해두기 때문입니다.

세 조각에 걸친 한 문장 — 조각별 번역 불가

셋 중에 이게 제일 까다로웠는데, 자막은 한 문장을 여러 조각으로 쪼개 놓습니다.

조각 1: "I went to the store"
조각 2: "because I needed"
조각 3: "some milk"

이걸 조각별로 번역하면 한국어와 영어의 어순이 반대라 동사가 갈 곳이 없어 사라지거나, 조각마다 “~습니다” 가 붙습니다. 조각 하나만 보고 자연스러운 한국어를 만드는 건 원리적으로 불가능합니다.

그래서 조각을 문장 단위로 다시 합치는 문장 그룹핑을 넣었습니다.

  • 문장부호로 끝나면 한 문장
  • 침묵이 2.5초 이상이면 끊긴 것으로 봄
  • 아무리 길어도 6조각을 넘지 않게 상한

합쳐진 문장을 통째로 번역하고, 그 문장이 재생되는 동안 같은 한국어 줄을 유지합니다. 영어 자막 줄은 원래 타이밍 그대로 흐르고, 한국어만 문장 단위로 붙어 있습니다.

부수 효과로 호출 수가 약 40% 줄었습니다. 조각마다 부르던 걸 문장마다 부르게 되니 호출 자체가 준 겁니다.

자막의 줄 단위와 문장 단위가 안 맞음

세 문제의 공통점은 “자막의 물리적 단위(줄·조각)” 와 “언어의 논리적 단위 (문장)” 가 안 맞는다는 거였습니다.

  • 밀림은 줄 단위를 지키게 해서 풀고,
  • 속도는 볼 부분만 번역해서 풀고,
  • 어순은 조각을 문장으로 되돌려서 풉니다.

LLM 에게 통짜로 맡기면 편할 것 같지만, 실제로는 입력을 어떻게 잘라서 주느냐가 결과 품질을 대부분 결정했습니다.

  1. 불러오는 중