7.4 사례 4 - 손상된 파일을 만났을 때
TS 일부 손상과 MP4 데이터 영역 손상을 재현하고, 디코딩 오류 로그, -xerror, 프레임 수 비교로 손상을 판별하는 방법과 한계, 격리·복구·재요청 정책을 정리합니다.
#증상
- 일부 소재가 재생 중 화면이 깨지거나 멈춘다.
- 변환은 성공(종료 코드 0)했는데 결과에 깨진 구간이 있다.
- 파일 크기와 길이는 정상인데 특정 지점에서만 문제가 난다.
#손상의 종류
| 종류 | 예 | 영향 |
|---|---|---|
| 구조 손상 | 헤더/인덱스(MP4의 moov, MXF의 Footer) 소실 |
파일을 아예 못 엶 |
| 데이터 손상 | 중간 일부가 다른 값으로 바뀌거나 0으로 채워짐 | 해당 구간의 화면·소리 깨짐 |
| 잘림 | 뒷부분 소실 | 길이가 짧아지거나 마지막이 재생되지 않음 |
| 미세 손상 | 1비트 반전 | 육안으로 알기 어려움(체크섬으로만 검출, 6장) |
구조 손상과 잘림은 앞 장들(MP4 moov atom not found, MXF Footer/RIP 부재)에서 다뤘습니다. 이 글에서는 데이터 손상을 재현합니다.
#재현 1: TS 중간 5,000바이트를 임의 값으로 덮기
녹화 TS(약 1.5MB, 4초) 한가운데 5,000바이트를 임의 값으로 덮었습니다.
ffmpeg -v warning -i r.ts -f null -
경고 메시지(중복 제거, 요약)는 다음과 같았습니다.
corrupt input packet in stream 0
Packet corrupt (stream = 0, dts = 309600)
corrupt decoded frame
Cannot use next picture in error concealment
그리고 두 가지 사실이 중요합니다.
- 프레임 수는 그대로였습니다. 손상된 파일과 정상 파일 모두
nb_read_frames = 100입니다. 디코더가 오류를 감추면서(concealment) 프레임 수를 채워 넣었기 때문입니다. 프레임 수 비교만으로는 이 유형의 손상을 찾을 수 없습니다. - FFmpeg는 오류를 출력하지만 기본적으로 계속 진행하고 정상 종료합니다(변환 결과에 깨진 프레임이 포함됨).
#-xerror로 중단시키기
ffmpeg -v error -xerror -i r.ts -f null -
corrupt input packet in stream 0
Task finished with error code: -1094995529 (Invalid data found when processing input)
(종료 코드 183)
-xerror 옵션을 주면 오류를 만나는 즉시 중단하고 0이 아닌 종료 코드를 반환합니다. 인제스트 QC에서 "손상이 있으면 실패 처리"해야 할 때 유용합니다.
#재현 2: MP4 데이터 영역의 20,000바이트를 0으로 채우기
프록시 MP4(약 200KB) 한가운데 20,000바이트를 0x00으로 채웠습니다.
h264: Invalid NAL unit size (0 > 357).
h264: missing picture in access unit with size 361
h264: Error splitting the input into NAL units.
aac : channel element 0.0 duplicate
... (수십 건 반복)
읽은 프레임 수: 132 (원본 150)
이번에는 영상 18프레임이 사라졌습니다(150 → 132). 손상이 크면 디코더가 복구하지 못하고 프레임을 버립니다. 이 유형은 프레임 수 비교로 검출됩니다.
| 손상 | 로그 | 프레임 수 |
|---|---|---|
| TS 임의 값 5,000바이트 | 경고 다수 | 같음(은폐) |
| MP4 0 채움 20,000바이트 | 오류 수십 건 | 줄어듦(150 → 132) |
| 1비트 반전 | 없음 | 같음(체크섬만 검출) |
#검출 전략: 여러 겹으로
한 가지 검사로는 모든 손상을 잡을 수 없으므로 층을 쌓아서 점검합니다.
| 층 | 방법 | 잡는 것 | 비용 |
|---|---|---|---|
| 1 | 구조 검사(MXF Footer/RIP, MP4 moov, IsTruncated) |
구조 손상, 잘림 | 낮음 |
| 2 | 프레임 수·길이 비교 | 큰 손상, 잘림 | 중간(-count_frames는 전체 읽기) |
| 3 | 디코딩 검사(ffmpeg -xerror -i f -f null -) |
디코더가 오류로 보는 손상 | 높음(전체 디코딩) |
| 4 | 체크섬 비교 | 모든 바이트 변경(미세 손상 포함) | 중간(전체 읽기) |
| 5 | QC 필터(블랙/프리즈 등, 3장) | 결과 화면의 이상 | 높음 |
- 전송·복사 시점의 체크섬 검증(4)이 가장 확실하고 비용 대비 효과가 좋습니다. 송신 측 체크섬이 있다면 인제스트에서 반드시 비교하세요.
- 체크섬이 없는(외부에서 받은) 파일은 1~3을 조합합니다.
- 디코딩 검사(3)는 비싸므로 의심 파일 또는 샘플링에 적용합니다.
#손상 파일 처리 정책
| 단계 | 처리 |
|---|---|
| 발견 | 소재를 격리 상태로 표시, 일반 사용자에게 숨기거나 경고 표시 |
| 원인 판별 | 전송 오류(재전송 가능)인지, 원본 소스에서 이미 손상인지 구분 |
| 재요청 | 송신처에 재전송 요청, 체크섬 함께 요청 |
| 복구 | 다른 복본(아카이브, 백업)에서 복원(6장 Fixity). 없으면 복구 도구 검토 |
| 부분 활용 | 손상 구간을 제외하고 정상 구간만 사용하는 방안 (구간 정보 기록) |
| 기록 | 어떤 검사에서 어떤 오류가 나왔는지 작업 이력에 보관 |
#점검 순서
- 파일 구조(헤더·인덱스·Footer)를 확인한다.
- 체크섬이 있으면 비교한다.
ffmpeg -v warning으로 디코딩 경고를 수집한다. 많으면-xerror로 실패 처리한다.- 프레임 수와 길이를 기대값과 비교한다.
- 같은 소재의 다른 복본·프록시·원본 카메라 카드가 있는지 찾는다.
- 복구 불가면 손상 범위(타임코드 구간)를 메타데이터로 기록하고 사용 가능 구간을 표시한다.
#정리
- 데이터 손상은 로그, 프레임 수, 체크섬이 각각 다른 유형을 잡아냅니다. 하나로는 부족합니다.
- FFmpeg는 손상을 숨기고 계속 변환하므로
-xerror와 경고 수집이 필요합니다. - 가장 확실한 방어는 전송 시점의 체크섬 검증과 복본에서의 복구입니다.
#참고 자료
링크는 2026-10-28에 열람이 되는 것을 확인했습니다. 규격과 도구 문서는 개정될 수 있으므로 적용하기 전에 최신 판을 확인하세요.