1인 회사 시스템 build

정밀하다는 옵션이 실제로는 590ms 더 틀렸다

whisper의 DTW 정밀 타임스탬프를 자막 싱크 정답지로 쓰려다 실패한 기록. 왜 정답지는 도구의 정밀 모드가 아니라 원본 오디오여야 하는지 실측으로 정리합니다.


정밀한 값을 정답지로 앉히려다

제가 만든 영상 렌더 파이프라인에는 자막 싱크를 자동으로 맞추는 단계가 있습니다. 음성을 whisper로 옮기고, 나온 타임스탬프로 자막 조각의 시작·끝을 정하는 구조입니다. 그런데 자동으로 붙은 싱크가 맞는지 아닌지를 판단할 기준, 즉 ‘정답지’가 필요했습니다. 눈으로 프레임을 세는 건 한계가 있으니까요.

그때 눈에 들어온 게 whisper의 -dtw 옵션이었습니다. DTW(Dynamic Time Warping)로 각 토큰의 발화 시각을 정렬해 더 정밀한 타임스탬프를 뽑아 준다는 기능입니다. 문서만 보면 이보다 나은 정답지가 없어 보였습니다. “정밀 모드가 있으니 이걸 기준으로 삼고, 기존 휴리스틱 싱크가 여기서 얼마나 벗어나는지 재면 되겠다”고 생각했습니다.

결론부터 적으면, 이 판단은 두 군데에서 틀렸습니다. 하나는 옵션이 제가 기대한 곳에 아예 개입하지 않았다는 것이고, 다른 하나는 개입하는 값을 따로 꺼내 봤더니 오히려 더 틀렸다는 것입니다.

첫 번째 착각 — 켜도 1ms도 안 변했다

가장 먼저 확인한 건 단순했습니다. -dtw를 켠 결과와 끈 결과를 놓고, 자막 분할 경계가 얼마나 달라지는지 비교했습니다. 정밀 모드가 정말 경계를 바꾼다면 최소한 몇 밀리초는 움직여야 하니까요.

경계는 49곳이었습니다. 그리고 49곳 전부, 차이가 0.00초였습니다. 켜든 끄든 1ms도 달라지지 않았습니다.

원인을 뜯어 보고 나서야 이해했습니다. -dtw로 계산한 값은 t_dtw라는 별도 필드에만 들어갑니다. 그런데 자막을 조각내는 -ml 분할 로직이 실제로 읽는 값은 t0t1입니다. DTW는 자기 필드에 조용히 앉아 있을 뿐, 분할이 참조하는 자리에는 손을 대지 않았던 겁니다. 정밀한 값을 계산하긴 했지만, 그 값이 흘러가는 경로와 제가 쓰려던 경로가 애초에 만나지 않았습니다.

여기서 곁가지로 하나 더 배웠습니다. -ml은 글자 수가 아니라 바이트 수 기준이라는 점입니다. UTF-8에서 한글 한 글자는 3바이트라, -ml을 문자 수로 알고 값을 잡으면 한글 자막은 예상의 3분의 1 지점에서 잘려 나갑니다. 같은 옵션 값이라도 언어마다 체감 분할 위치가 전혀 달라지는 이유였습니다.

두 번째 착각 — 정밀한데 더 늦었다

첫 번째가 “정답지가 개입조차 안 했다”였다면, 두 번째는 더 뼈아팠습니다. t_dtw 필드에서 값을 직접 꺼내, 이번엔 진짜 정답지와 대조했습니다.

진짜 정답지는 원본 오디오였습니다. 파형에서 실제 발화가 시작되는 시각을 직접 읽었더니 0.742초였습니다. 이걸 기준으로 두 값을 나란히 놓았습니다.

  • 기존 휴리스틱 t0: 정답 대비 -0.04초
  • DTW 값: 정답 대비 +0.34초 (늦음)

정밀하다던 쪽이 340ms 늦게 찍혔고, 별 기대 없던 휴리스틱이 40ms 안쪽으로 붙어 있었습니다. 한 토큰만 그런가 싶어 전체를 돌렸더니 방향이 일정했습니다. 227개 토큰 중 226개에서 DTW가 더 늦었고, 늦은 양의 중앙값은 590ms였습니다. 예외는 단 하나뿐이었습니다.

정밀하다는 말과 정답에 가깝다는 말이 같지 않다는 걸 숫자로 마주한 순간이었습니다. DTW는 자기 방식으로 일관되게 정렬을 하지만, 그 일관된 결과가 실제 소리가 난 시점보다 체계적으로 뒤에 있었습니다. 정밀한 오답은 정밀하기 때문에 오히려 의심받지 않습니다.

정답지는 평판이 아니라 원본이어야 한다

돌아보면 제 실수는 기술적이라기보다 태도의 문제였습니다. “DTW = 정밀”이라는 평판을 그대로 정답지 자격으로 승격시킨 겁니다. 검증하려는 대상(자막 싱크)과 검증 기준(같은 도구가 뽑은 다른 필드)이 사실상 같은 출처였고, 출처가 같으면 그 안의 오차는 서로를 가려 줄 뿐 드러나지 않습니다. 원본 오디오라는 바깥 기준을 들이대기 전까지, 저는 590ms를 통째로 못 보고 있었습니다.

그래서 지금은 정답지를 고를 때 딱 한 가지만 봅니다. 이 기준이 검증 대상과 다른 출처인가. 도구가 “정밀”이라고 이름 붙인 모드는 그 도구 안의 추정치일 뿐, 도구 바깥의 사실이 아닙니다. 자막이라면 원본 파형, 데이터라면 원 로그처럼, 검증하려는 파이프라인이 손대지 않은 원본이어야 정답지 자격이 있습니다.

정밀 모드에 붙은 이름은 마케팅이자 그 도구의 자기 평가입니다. 590ms는 그 평가를 원본과 대조하지 않았다면 영영 몰랐을 숫자였습니다. 도구가 스스로 정밀하다고 말할 때, 그 말을 정답지로 앉히지 말고 원본을 꺼내 재 보는 습관 하나가 이번 기록에서 남은 전부입니다.

자주 묻는 질문

whisper의 -dtw 옵션을 켜면 자막 분할 경계가 더 정확해지나요?

제 실측에서는 아니었습니다. -dtw로 계산한 값은 t_dtw라는 별도 필드에만 들어가고, -ml 분할이 실제로 참조하는 t0/t1에는 반영되지 않았습니다. 그래서 분할 경계 49곳을 비교했을 때 옵션을 켜든 끄든 전부 0.00초, 1ms도 달라지지 않았습니다.

DTW 타임스탬프가 휴리스틱보다 정밀하다는데 왜 더 틀렸나요?

정밀하다는 것과 정답에 가깝다는 것은 다른 문제입니다. 실제 발화 시작 시각을 원본 오디오로 재보니, 휴리스틱 값이 오히려 정답에 가깝고 DTW 값은 전반적으로 늦게 찍혔습니다. 제 데이터에서는 227토큰 중 226개에서 DTW가 더 늦었고 중앙값이 590ms 차이였습니다.

whisper의 -ml(최대 길이) 옵션은 글자 수 기준인가요?

문자 수가 아니라 바이트 수 기준입니다. UTF-8에서 한글 한 글자는 3바이트라, -ml 값을 글자 수로 착각하면 한글 자막은 예상의 3분의 1 길이에서 잘립니다. 언어별로 체감 분할 위치가 크게 달라지는 이유입니다.

도구가 제공하는 정밀 모드를 정답지로 삼아도 되나요?

권하지 않습니다. 정밀 모드는 어디까지나 그 도구 내부의 추정치이고, 검증 대상과 검증 기준이 같은 출처면 오차를 발견할 수 없습니다. 정답지는 원본 오디오나 원 데이터처럼 도구 바깥의 사실이어야 합니다.

#whisper#자막#타임스탬프#1인 개발#검증