1.4 타임코드와 드롭 프레임
영상의 주소인 SMPTE 타임코드의 구조, 드롭 프레임이 필요한 이유와 계산법, 프레임 번호와의 변환 방법을 예제 코드로 설명합니다.
#타임코드란
타임코드(Timecode)는 영상의 프레임마다 붙는 고유한 주소입니다. 시:분:초:프레임 형식으로 표기하고, 일반적으로 SMPTE 12M 규격을 따릅니다.
01:23:45:12 → 1시간 23분 45초 12프레임
방송 현장에서는 "5분 20초 지점부터 30초 구간"이 아니라 "00:05:20:00부터 00:05:50:00까지"처럼 프레임 단위로 구간을 지정합니다. EDL, 큐시트, 자막, 광고 삽입 위치, MAM의 마커와 서브클립이 모두 타임코드를 기준으로 움직입니다.
#프레임레이트별 표기
| 프레임레이트 | 프레임 필드 범위 | 비고 |
|---|---|---|
| 24, 25 | 00 ~ 23 / 00 ~ 24 | 정확히 정수 |
| 30 | 00 ~ 29 | NDF 또는 시청 편의상 정수 처리 |
| 29.97 | 00 ~ 29 | NDF(Non-Drop) 와 DF(Drop Frame) 두 종류 |
| 59.94 | 00 ~ 59 | 마찬가지로 NDF/DF |
#드롭 프레임이 필요한 이유
29.97fps 영상의 1초는 30프레임이 아니라 약 29.97프레임입니다. 그런데 타임코드는 "1초 = 30프레임"으로 계산해서 숫자를 올리면, 타임코드 시계가 실제 시간보다 느려집니다.
1시간 분량 영상 = 약 107,892 프레임 (29.97 × 3600)
타임코드가 세는 프레임 수 = 108,000 프레임 (30 × 3600)
차이 = 108 프레임 ≈ 3.6초
실제 시계로 1시간이 지났을 때 타임코드는 00:59:56:12를 가리킵니다(107,892프레임 ÷ 30). 반대로 타임코드가 01:00:00:00이 되려면 실제로는 약 3603.6초가 걸립니다. 즉 타임코드 시계가 실제 시계보다 1시간에 3.6초 느리게 갑니다. 방송 시간표는 초 단위로 맞아야 하므로 이 차이를 없애기 위해 드롭 프레임(Drop Frame, DF) 방식을 사용합니다.
#드롭 프레임의 규칙
드롭 프레임은 영상 프레임을 실제로 버리는 것이 아닙니다. 타임코드 숫자를 건너뛰는 방식입니다.
- 매 분이 시작될 때 프레임 번호
00,01을 건너뜁니다. (예:00:00:59:29다음은00:01:00:02) - 단, 10분 단위(0, 10, 20, 30, 40, 50분) 에는 건너뛰지 않습니다.
이렇게 하면 1시간에 2 × (60 − 6) = 108개의 숫자를 건너뛰어, 앞에서 계산한 108프레임 차이가 정확히 보정됩니다.
표기에서도 구분합니다. NDF는 01:00:00:00처럼 콜론만 쓰고, DF는 마지막 구분자를 세미콜론(또는 점)으로 써서 01:00:00;00으로 적습니다.
#직접 확인: 1분 경계의 6프레임
FFmpeg의 drawtext 필터는 timecode 옵션으로 타임코드를 화면에 새길 수 있습니다. 구분자가 :이면 논드롭 프레임, ;이면 드롭 프레임으로 계산합니다. 29.97fps(30000/1001)에서 00:00:59의 27번 프레임부터 연속된 6프레임을 새겨 비교했습니다.
ffmpeg -f lavfi -i "color=c=0x23272e:s=300x110:r=30000/1001" \
-vf "drawtext=fontfile=consola.ttf:timecode='00\:00\:59\;27':timecode_rate=30000/1001:fontsize=40:fontcolor=white:x=(w-tw)/2:y=(h-th)/2" \
-frames:v 6 df_%d.png

드롭 프레임에서는 59;29 다음 프레임이 01:00;00이 아니라 01:00;02입니다. 사라진 것은 영상 프레임이 아니라 타임코드 숫자 두 개(;00, ;01)뿐이고, 화면은 끊김 없이 이어집니다. 이렇게 매 분마다 숫자를 건너뛰어(10분 단위는 제외) 29.97fps에서 생기는 누적 오차를 실제 시계에 맞춥니다.
#타임코드와 프레임 번호 변환
MAM이나 편집 도구를 만들다 보면 타임코드를 프레임 번호로 바꾸고 다시 되돌리는 작업이 필수입니다. 아래는 29.97fps 드롭 프레임 기준의 파이썬 예제입니다.
def tc_to_frames_df(h, m, s, f):
"""29.97 DF 타임코드 -> 절대 프레임 번호"""
total_minutes = h * 60 + m
dropped = 2 * (total_minutes - total_minutes // 10)
return ((h * 3600 + m * 60 + s) * 30 + f) - dropped
def frames_to_tc_df(frame):
"""절대 프레임 번호 -> 29.97 DF 타임코드 문자열"""
frames_per_10min = 17982 # 10분 = 600초 * 30 - 18
frames_per_min = 1798 # 1분 = 60 * 30 - 2 (10분 배수 제외)
d, m = divmod(frame, frames_per_10min)
if m < 2:
frame += 18 * d
else:
frame += 18 * d + 2 * ((m - 2) // frames_per_min)
f = frame % 30
s = (frame // 30) % 60
mm = (frame // 1800) % 60
h = frame // 108000
return f"{h:02d}:{mm:02d}:{s:02d};{f:02d}"
print(frames_to_tc_df(1800)) # 00:01:00;02
print(tc_to_frames_df(0, 1, 0, 2)) # 1800
00:01:00;02가 프레임 번호 1800과 같다는 점이 핵심입니다. 건너뛴 00, 01 두 숫자는 실제 프레임이 없습니다.
#실무에서 주의할 점
- 파일에 NDF/DF 정보가 있는지 확인합니다. MXF는 시작 타임코드와 DF 여부를 메타데이터에 가지고 있고, MOV는 타임코드 트랙(
tmcd)에 저장합니다. MediaInfo에서Time code of first frame,Time code, striped와 같은 항목으로 볼 수 있습니다. - 시작 타임코드가 00:00:00:00이 아닌 경우가 많습니다. 방송 소재는 보통
01:00:00:00부터 시작하는 것이 관례입니다(앞쪽 바와 톤, 카운트다운 때문). 프록시를 만들 때 시작 타임코드를 함께 옮기지 않으면 원본과 프록시의 구간이 어긋납니다. - 프레임 정확도(Frame Accuracy)를 점검합니다. 인터레이스 영상이나 B프레임이 있는 코덱은 탐색 후 정확히 그 프레임을 보여주는지 확인해야 합니다. 프록시와 원본의 프레임 수가 같은지도 검증 항목입니다.
- 웹 플레이어는 초 단위입니다. HTML5
<video>의currentTime은 초(실수) 단위라서, 프레임 단위 이동이 필요한 UI는프레임 번호 / 프레임레이트를 직접 계산해야 합니다. 이때 29.97를30000/1001로 정확히 다루는 습관이 중요합니다.
#정리
- 타임코드는 프레임 단위 주소이며, 29.97fps에서는 NDF와 DF가 있습니다.
- DF는 프레임을 버리지 않고 숫자만 건너뛰어 실제 시간과 맞춥니다.
- 시작 타임코드와 DF 여부는 변환·검수 때 반드시 보존하고 확인해야 합니다.
#참고 자료
링크는 2026-10-28에 열람이 되는 것을 확인했습니다. 규격과 도구 문서는 개정될 수 있으므로 적용하기 전에 최신 판을 확인하세요.