3.6 자동 QC - 블랙, 프리즈, 무음, 라우드니스 검사
FFmpeg의 blackdetect, freezedetect, silencedetect, ebur128, cropdetect 필터로 영상 품질 검사를 자동화하는 방법과, 결과 해석과 임계값 설정 기준을 설명합니다.
#QC(Quality Control)란
방송사에서 QC는 송출 전에 소재가 기준을 충족하는지 검사하는 일입니다. 전통적으로는 QC 담당자가 영상을 처음부터 끝까지 보며 확인했지만, 파일 기반 환경에서는 자동 검사가 먼저 돌고 사람은 경고가 난 구간만 확인합니다.
자동 QC에서 흔히 검사하는 항목은 다음과 같습니다.
| 분류 | 검사 항목 |
|---|---|
| 구조 | 컨테이너 완결성, 코덱·해상도·프레임레이트 규격 일치, 타임코드 연속성 |
| 영상 | 블랙 프레임, 프리즈(정지) 프레임, 레터박스/필러박스(검은 띠), 블록 노이즈, 색상 범위 |
| 오디오 | 무음 구간, 라우드니스(음량), 피크, 채널 구성, 위상 |
앞 글에서 구조 검사를 다뤘으므로, 이번에는 FFmpeg 필터만으로 구현할 수 있는 영상·오디오 검사를 실습합니다.
#테스트 영상 만들기
검사가 제대로 동작하는지 알려면 정답을 알고 있는 영상이 필요합니다. 아래 명령으로 8초짜리 영상을 만들었습니다.
- 영상: 0~2초 빨간 화면, 2~5초 검은 화면, 5~8초 테스트 패턴
- 오디오: 0~2초 440Hz 톤, 2~5초 무음, 5~8초 880Hz 톤
ffmpeg -y -filter_complex "\
color=c=red:s=640x360:r=25:d=2[a];color=c=black:s=640x360:r=25:d=3[b];testsrc2=s=640x360:r=25:d=3[c];\
[a][b][c]concat=n=3:v=1:a=0[v];\
sine=f=440:d=2[s1];anullsrc=r=48000:cl=mono:d=3[s2];sine=f=880:d=3[s3];\
[s1][s2][s3]concat=n=3:v=0:a=1[a]" \
-map "[v]" -map "[a]" -c:v libx264 -pix_fmt yuv420p -c:a aac qc.mp4
#1) 블랙·프리즈·무음 검출
세 필터를 한 번에 실행하는 명령입니다. 영상은 디코딩만 하고 출력은 버립니다(-f null -).
ffmpeg -hide_banner -i qc.mp4 \
-vf "blackdetect=d=0.5:pix_th=0.10,freezedetect=n=-60dB:d=1" \
-af "silencedetect=n=-50dB:d=0.5" \
-f null - 2>&1 | grep -E "black_|freeze_|silence_"
실행 결과(요약):
black_start:2 black_end:5 black_duration:3
lavfi.freezedetect.freeze_start: 0
lavfi.freezedetect.freeze_duration: 2
lavfi.freezedetect.freeze_end: 2
lavfi.freezedetect.freeze_start: 2
lavfi.freezedetect.freeze_duration: 3
lavfi.freezedetect.freeze_end: 5
silence_start: 2
silence_end: 5.000023 | silence_duration: 3.000023
| 필터 | 결과 | 해석 |
|---|---|---|
blackdetect |
2초~5초 | 만들어 둔 검은 화면 구간을 정확히 검출 |
freezedetect |
0~2초, 2~5초 | 빨간 화면과 검은 화면 모두 "정지"로 검출 |
silencedetect |
2초~5초 | 무음 구간 검출 |
#주요 옵션의 의미
| 옵션 | 의미 | 조정 기준 |
|---|---|---|
blackdetect=d |
검은 화면이 최소 몇 초 이상 지속되어야 보고할지 | 방송 사고 기준(0.5~2초)에 맞춤 |
blackdetect=pix_th |
픽셀을 검다고 볼 밝기 임계값(0~1) | 소재의 블랙 레벨에 맞춤 |
freezedetect=n |
프레임 간 차이를 "같다"고 볼 노이즈 허용치 | 인코딩 노이즈가 많으면 값을 올림 |
freezedetect=d |
정지로 판단할 최소 지속 시간 | 정지 화면이 의도된 구간이 있으면 길게 |
silencedetect=n |
무음으로 볼 음량 임계값(dB) | -50dB 전후에서 시작 |
silencedetect=d |
무음 최소 지속 시간 | 의도된 무음 연출이 있으면 길게 |
#2) 라우드니스 측정
방송 음량 규정은 대부분 LUFS(Loudness Units relative to Full Scale) 기준의 라우드니스로 관리합니다. FFmpeg의 ebur128 필터가 EBU R128 방식의 측정을 제공합니다.
ffmpeg -hide_banner -nostats -i qc.mp4 -af ebur128=peak=true -f null - 2>&1 | sed -n '/Summary/,$p'
Integrated loudness:
I: -21.8 LUFS
Loudness range:
LRA: 10.2 LU
True peak:
Peak: -17.7 dBFS
- I (Integrated): 전체 프로그램의 평균 라우드니스. 방송 기준 값과 비교합니다.
- LRA: 라우드니스 범위(음량 변화 폭).
- True Peak: 실제 파형 피크. 클리핑·왜곡 위험을 판단합니다.
위 테스트는 무음이 포함되어 있고 톤의 크기가 작아 값이 낮게 나왔을 뿐입니다. 어떤 기준(예: 유럽 EBU R128 -23 LUFS, 미국 ATSC A/85 -24 LKFS)을 적용할지는 납품·송출 규격에 따라 다릅니다. 방송사나 플랫폼 규정을 확인해서 설정하세요.
#직접 확인: 구간별 측정값이 움직이는 모습
진폭이 다른 핑크 노이즈 8초 3구간(0.1, 0.5, 1.0)을 이어 붙인 24초 오디오를 ebur128로 측정하고, 로그의 100ms 단위 값을 그래프로 그렸습니다(framelog=info로 순간값이 로그에 출력됩니다).
ffmpeg -hide_banner -nostats -i loud.wav -af ebur128=framelog=info -f null - 2>&1 | grep "M:"

- 각 구간의 Short-term 값은 약 -34.6 → -20.6 → -14.6 LUFS로 수렴했고, 전체 Integrated는 -16.7 LUFS였습니다. 구간별 값을 평균한 것이 아니라 게이팅이 적용된 프로그램 전체 값입니다.
- Momentary는 구간 변화에 빠르게 반응하고, Short-term은 3초 창이라 구간이 바뀐 뒤 약 3초가 지나야 안정됩니다. 처음 3초는 값이 채워지지 않았습니다(그래프에서 바닥에 붙은 부분).
- 그래서 합격 판정은 어느 한 순간의 값이 아니라 Integrated와 LRA로 해야 합니다. 이 샘플은 목표(-23 LUFS)보다 6 LU 이상 큽니다.
#3) 레터박스·필러박스(검은 띠) 검출
4:3 소재를 16:9에 넣거나 반대로 한 경우에 생기는 검은 띠는 cropdetect로 감지할 수 있습니다.
# 테스트: 640x360 영상에 위아래 검은 띠를 붙여 640x480으로 만든 뒤 검사
ffmpeg -hide_banner -ss 5.5 -t 1 -i qc.mp4 -vf "pad=640:480:0:60,cropdetect=24:2:0" -f null - 2>&1 | grep -o "crop=[0-9:]*" | tail -1
crop=640:360:0:60
"640×360 영역을 y=60 위치에서 자르면 검은 띠가 제거된다"는 결과로, 의도한 값을 정확히 찾았습니다. 이 결과는 프록시나 송출 변환 시 화면비 처리에 활용할 수 있습니다.
#4) 파형 모니터와 벡터스코프로 눈으로 확인하기
수치 검사로 못 잡는 문제(밝기 범위 이탈, 색 편향)는 스코프로 확인합니다. FFmpeg의 waveform과 vectorscope 필터로 SMPTE 컬러 바를 분석해 나란히 놓았습니다.
ffmpeg -f lavfi -i smptebars=size=640x360:r=25 -frames:v 1 -filter_complex \
"split=3[a][b][c];[b]waveform=filter=lowpass:scale=digital:graticule=green:flags=numbers+dots,scale=400:360[w];[c]vectorscope=mode=color2:graticule=green:flags=name,scale=360:360[v];[a]scale=640:360[o];[o][w][v]hstack=3" scope.png

- 파형 모니터: 가로는 화면의 좌우 위치, 세로는 밝기입니다. 8비트 방송 영상의 정상 범위(리미티드 레인지)는 16~235이므로 이 범위를 벗어나는 신호가 있는지 봅니다. 컬러 바의 각 막대가 서로 다른 높이의 가로선으로 나타납니다.
- 벡터스코프: 색상은 각도, 채도는 중심에서의 거리입니다. 컬러 바의 점이 R, Mg, B, Cy, G, Yl 표시 안에 들어오면 색이 정상입니다. 점이 한쪽으로 쏠려 있으면 색 편향(화이트 밸런스, 변환 오류) 을 의심합니다.
- 자동화할 때는
signalstats필터로 프레임별 밝기 최소·최대(YMIN,YMAX)를 수치로 뽑아 범위를 벗어난 프레임 수를 세는 방식이 더 실용적입니다. 스코프 이미지는 문제가 보고된 소재를 사람이 확인하는 도구로 씁니다.
#자동 QC 파이프라인 구성
실제 시스템에서는 이런 검사를 인제스트 직후의 작업 단계 하나로 구성합니다.
인제스트 완료
↓
① 구조 검사: Footer/RIP, IsTruncated, 프레임 수 (MXF)
↓
② 규격 검사: 코덱, 해상도, 프레임레이트, 주사 방식이 규격과 일치하는가
↓
③ 영상·오디오 검사: blackdetect / freezedetect / silencedetect / ebur128
↓
④ 결과를 구간(시작·끝 타임코드) + 종류 + 심각도로 DB에 저장
↓
⑤ 사람이 경고 구간만 프록시로 확인 후 승인/반려
④에서 결과를 타임코드 구간으로 저장하는 것이 중요합니다. FFmpeg 출력은 초 단위이므로, 소재의 시작 타임코드와 프레임레이트를 이용해 타임코드로 바꿔서 저장해야 MAM의 마커로 바로 쓸 수 있습니다(1장 타임코드 편 참고).
#성능 고려
- 영상 필터는 모든 프레임을 디코딩해야 하므로 UHD나 롱 GOP에서는 시간이 오래 걸립니다. 프록시(저해상도)에서 검사하면 훨씬 빠르지만, 원본에서만 보이는 문제(블록 노이즈, 미세한 색상 문제)는 놓칩니다. 용도에 따라 원본/프록시 검사를 나누세요.
- 필터를 한 번의 실행에 묶으면(위 예시처럼) 파일을 한 번만 읽고 디코딩합니다. 검사마다 따로 실행하면 같은 파일을 여러 번 디코딩해 낭비입니다.
- 여러 파일을 동시에 처리할 때는 CPU 코어 수를 기준으로 동시 작업 개수를 제한하세요.
#정리
- 자동 QC는 "오류 판정"이 아니라 사람이 확인할 구간을 좁혀 주는 도구입니다.
- FFmpeg 필터(
blackdetect,freezedetect,silencedetect,ebur128,cropdetect)만으로도 기본 QC 파이프라인을 만들 수 있습니다. - 임계값은 소재 유형과 납품 규격에 맞게 조정하고, 결과는 타임코드 구간으로 저장해 MAM 마커와 연결합니다.
#참고 자료
링크는 2026-10-28에 열람이 되는 것을 확인했습니다. 규격과 도구 문서는 개정될 수 있으므로 적용하기 전에 최신 판을 확인하세요.