3.3 FFprobe로 JSON 분석하기
FFprobe의 show_format, show_streams, show_packets, show_frames 옵션과 JSON 출력 활용법, 프레임 수 검증과 PTS/DTS 읽기, 버전에 따른 필드 변경 주의점을 설명합니다.
#MediaInfo와 FFprobe의 역할 차이
| 구분 | MediaInfo | FFprobe |
|---|---|---|
| 강점 | 방송 포맷 메타데이터, 사람이 읽기 쉬운 항목 | 패킷·프레임 단위 정보, FFmpeg와 같은 해석 |
| 약점 | 프레임 단위 정보 없음 | 방송 고유 항목 일부 부족 |
| 의미 | "파일이 스스로 말하는 것" | "FFmpeg가 실제로 읽어낸 것" |
FFmpeg로 변환할 계획이라면 FFprobe의 해석이 곧 변환 결과의 기준입니다. 그래서 인제스트 분석은 두 도구를 함께 쓰는 것이 안전합니다.
#세 가지 분석 단계
FFprobe는 같은 파일을 세 단계 깊이로 볼 수 있습니다.
| 옵션 | 단위 | 비용 | 용도 |
|---|---|---|---|
-show_format |
파일 | 매우 빠름 | 컨테이너, 길이, 크기, 비트레이트 |
-show_streams |
스트림 | 매우 빠름 | 코덱, 해상도, 프레임레이트, 오디오 구성 |
-show_packets |
패킷 | 파일 읽기 필요 | PTS/DTS, 키프레임 위치, 패킷 크기 |
-show_frames |
프레임 | 디코딩 필요, 느림 | 프레임 유형, 인터레이스 정보 |
#기본: 포맷과 스트림을 JSON으로
ffprobe -v error -show_format -show_streams -of json input.mxf
필요한 항목만 골라서 받을 수도 있습니다.
ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,profile,level,width,height,pix_fmt,field_order,r_frame_rate,avg_frame_rate,time_base,nb_frames,bit_rate,duration \
-of json proxy.mp4
실제 출력은 다음과 같습니다.
{
"streams": [
{
"codec_name": "h264",
"profile": "High",
"width": 640,
"height": 360,
"pix_fmt": "yuv420p",
"level": 30,
"field_order": "progressive",
"r_frame_rate": "30000/1001",
"avg_frame_rate": "30000/1001",
"time_base": "1/30000",
"duration": "5.005000",
"bit_rate": "213848",
"nb_frames": "150"
}
]
}
#필드 읽기
level: 30: H.264 레벨이 정수로 표시됩니다.30은 레벨 3.0,31은 3.1입니다. MediaInfo의High@L3와 같은 정보입니다.field_order:progressive,tt(top field first),bb(bottom field first) 등으로 나옵니다. 앞서 본 MXF는tt였습니다.r_frame_ratevsavg_frame_rate:r_frame_rate는 스트림에서 추정한 기본 프레임레이트,avg_frame_rate는 전체 프레임 수를 길이로 나눈 평균입니다. 둘이 다르면 가변 프레임레이트(VFR) 를 의심합니다.time_base: 타임스탬프의 단위입니다.1/30000이면 PTS 1이 1/30000초입니다.nb_frames: 컨테이너가 기록한 프레임 수입니다. TS나 일부 MXF에서는N/A로 나옵니다.
#프레임 수 검증: -count_frames
컨테이너가 기록한 프레임 수가 실제로 읽을 수 있는 프레임 수와 같은지 확인하는 가장 간단한 방법입니다.
ffprobe -v error -count_frames -select_streams v:0 \
-show_entries stream=nb_frames,nb_read_frames -of default=nw=1 input.mxf
앞 장에서 만든 정상 MXF와, 파일 뒷부분을 잘라 낸 손상 MXF의 결과입니다.
정상 파일 : nb_read_frames=150
잘린 파일 : nb_read_frames=129
잘린 파일은 헤더의 길이 정보는 5.005초로 정상이지만, 실제로 읽을 수 있는 프레임은 129개뿐입니다. 길이 값만 믿으면 이런 파일을 놓칩니다. -count_frames는 파일 전체를 읽기 때문에 시간이 걸리므로, 인제스트 시 "의심 파일"에만 선택적으로 쓰는 것이 좋습니다.
#패킷 읽기: PTS, DTS, 키프레임
ffprobe -v error -select_streams v:0 \
-show_entries packet=pts_time,dts_time,size,flags -of csv=p=0 \
-read_intervals "%+#5" proxy.mp4
0.000000,-0.066733,5573,K__
0.033367,-0.033367,832,___
0.133467,0.000000,1126,___
0.066733,0.033367,327,___
0.100100,0.066733,265,___
열은 PTS, DTS, 크기, 플래그입니다.
- 플래그
K는 키프레임(I) 입니다. 첫 패킷만 키프레임이고 크기(5,573바이트)가 가장 큽니다. 2장의 설명 그대로입니다. - PTS와 DTS가 다릅니다. 세 번째 패킷은 표시 시간(PTS)이 0.1335초인데 디코딩 시간(DTS)은 0.0이어서, B프레임 때문에 저장 순서와 표시 순서가 다릅니다. DTS가 음수로 시작하는 것도 B프레임 재정렬 지연을 반영한 값입니다.
-read_intervals "%+#5"는 "처음부터 5개 패킷만 읽어라"는 뜻입니다. 큰 파일의 앞부분만 빠르게 보고 싶을 때 유용합니다. 시간 구간("10%+5": 10초부터 5초 동안)도 지정할 수 있습니다.
#타임코드 읽기
MOV의 타임코드는 스트림 태그로 읽힙니다.
ffprobe -v error -show_entries stream=index,codec_type:stream_tags=timecode -of compact prores.mov
stream|index=0|codec_type=video|tag:timecode=00:59:58;00
stream|index=1|codec_type=audio
stream|index=2|codec_type=data|tag:timecode=00:59:58;00
비디오 스트림과 data 스트림(tmcd 트랙) 두 곳에 타임코드가 나옵니다. MXF는 포맷 태그(format_tags=timecode)에 나타났습니다. 즉 파일 종류마다 타임코드가 있는 위치가 다릅니다. 분석 코드는 포맷 태그와 스트림 태그를 모두 찾아야 합니다(7편의 분석 도구가 이렇게 처리합니다).
#FFmpeg 버전에 따른 필드 변경
FFprobe의 출력 필드는 버전이 올라가며 바뀝니다. 예전 블로그나 도구에서 가져온 코드가 어느 날 값을 못 읽는 경우가 이 때문입니다.
| 예전 필드 | 현재 | 비고 |
|---|---|---|
pkt_pts_time |
pts_time |
프레임 출력 필드. 구형 코드는 값을 못 찾게 됨 |
pkt_dts_time |
pkt_dts_time |
패킷 기준 DTS (프레임 출력) |
coded_picture_number |
환경에 따라 없음 | 프레임 번호는 직접 세는 편이 안전 |
본 가이드에서 사용한 FFmpeg 빌드(2026년 2월 빌드)에서는 프레임 정보에 pts_time, interlaced_frame, top_field_first, pict_type, key_frame이 있었습니다. 다만 FFmpeg는 개발 과정에서 일부 필드를 폐기(deprecated)하고 다른 형태로 대체하는 일이 있으므로, 분석 코드는 필드가 없을 때를 반드시 처리해야 합니다.
#정리
- MediaInfo는 "파일이 말하는 것", FFprobe는 "FFmpeg가 읽은 것"입니다. 둘을 함께 쓰세요.
- 프레임레이트는 분수로, 길이와 프레임 수는
-count_frames로 교차 검증합니다. - 패킷 정보에서 PTS/DTS와 키프레임 위치를 읽을 수 있고, 타임코드 위치는 포맷마다 다릅니다.
- FFprobe 필드명은 버전에 따라 변하므로 분석 코드는 방어적으로 작성합니다.
#참고 자료
링크는 2026-10-28에 열람이 되는 것을 확인했습니다. 규격과 도구 문서는 개정될 수 있으므로 적용하기 전에 최신 판을 확인하세요.