ffmpeg가 성공으로 끝났는데 자막이 없었던 이유

· 약 2분

쇼츠 영상을 자동으로 굽는 파이프라인에서 겪은 일을 정리합니다. 결론부터 말씀드리면, 이번에는 프로그램이 성공으로 끝났다는 것이 결과물이 맞다는 증거가 되지 못했습니다.

처음 본 것: 렌더링 신호는 모두 정상이었다

이번 렌더링에서 확인한 신호는 세 가지였습니다. ffmpeg는 성공으로 끝났고, 영상 길이도 정상이었고, 로그에도 자막 장수가 찍혔습니다.

이 세 신호만으로는 자막이 빠졌다는 것을 알 수 없었습니다.

실제로 확인한 것: 씬 전체에 자막이 없었다

그런데 완성된 영상의 프레임을 열어 보니 씬 전체에 자막이 없었습니다. 자막 PNG는 정상적으로 그려져 있었고, filter_complex에도 overlay가 걸려 있었습니다. 재료도 있고 합성 지시도 있는데 결과에만 자막이 빠져 있었던 겁니다.

원인을 좁히려고 같은 배경과 같은 PNG를 쓰고 -loop 1 옵션 유무만 바꿔 대조했습니다. 이 대조로 이번 누락의 원인을 특정했습니다.

이 사례에서 특정된 원인은 이렇습니다. -loop 1 없이 PNG를 입력하면 단일 프레임으로 읽힙니다. 자막은 enable 조건으로 꺼졌다가 켜지는데, 켜지는 순간에는 그 입력이 이미 EOF에 도달해 있어서 자막이 통째로 빠졌습니다.

이 설명은 이번 파이프라인의 구성에서 확인한 것입니다. 다른 필터 구성에서도 똑같이 일어나는지는 확인하지 않았습니다.

둘의 차이: 실패가 조용했다

이 버그가 위험했던 이유는 조용했다는 데 있습니다. 성공 종료, 정상 길이, 로그의 자막 장수까지 세 신호가 전부 정상이었습니다. 눈으로 프레임을 열기 전에는 알 수 없었습니다.

이번 사례에서 그 세 신호는 화면에 자막이 있는지를 알려 주지 못했습니다.

그래서 무엇이 달라졌는가: 결과물을 직접 재는 검사기

매번 프레임을 열어 볼 수는 없으니 렌더 후 검사기를 만들었습니다. 완성 파일을 1초 간격으로 샘플링해 자막 영역의 밝은 픽셀 비율을 재고, 연속으로 비어 있으면 실패로 보고합니다.

두 가지를 조정했습니다. 이번 검사기에서는 샘플 하나만 비는 공백을 씬 경계의 페이드로 보고 실패에서 제외했습니다. 판정 임계값은 강조색인 노란색 자막도 걸리도록 낮췄습니다.

검사기 자체도 검증했습니다. 수정 전에 구운 파일, 즉 실제로 자막이 빠진 파일을 넣었고, 검사기는 실제 누락 구간을 잡아냈습니다. 이로써 이 검사기가 이번에 알려진 누락을 놓치지 않는다는 것까지는 확인했습니다.

이 검사기가 보는 것은 자막 영역이 비어 있는지 하나입니다. 자막 내용이 맞는지, 제때 나오는지까지 보증하지는 않습니다. 이번처럼 자막이 통째로 사라지는 종류의 실패를 잡는 장치입니다.

정리

  • ffmpeg에서 정지 이미지를 일정 구간에만 겹치도록 enable을 걸었는데 자막이 안 보인다면, 그 입력에 -loop 1이 붙어 있는지부터 확인해 볼 만합니다. 이번 사례에서는 그것이 원인이었습니다.
  • 이번 사례에서 성공 종료, 정상 길이, 로그는 자막 누락을 드러내지 못했고, 누락은 결과물의 프레임을 직접 열어서야 확인됐습니다.
  • 이번 검사기는 수정 전에 구운 파일에서 실제 누락 구간을 잡아내는지로 검증했습니다. 이미 실패한 파일이 있다면 새 검사기를 그 파일로 먼저 돌려 보는 방법을 쓸 수 있습니다.