Drop-frame (DF) and non-drop-frame (NDF) timecode label the same pictures at the same playback rate. The only difference is which labels appear in the sequence. At 29.97, DF never uses the labels ;00 and ;01 in the first second of a minute unless that minute is divisible by ten. At 59.94 it never uses ;00 through ;03 on the same schedule. Skipping those labels keeps the label sequence within a few thousandths of a second of the clock at ten-minute marks. It does not delete frames, change playback speed or convert a frame rate.
Counting conventions used below
Frame index: zero-based position in the clip. Index 0 is the first frame.
Elapsed frames: how many frames have passed. N elapsed frames reach the frame whose index is N.
Duration between two labels: the difference of their frame indices, never the difference of their printed fields.
Seconds: exact values from 30000/1001 and 60000/1001, with any rounding stated.
What changes between DF and NDF, and what does not
| Thing | What it is | Changed by choosing DF? |
|---|---|---|
| Actual video frames | The pictures in the file | No |
| Actual playback rate | 30000/1001 fps (29.97002997…) or 60000/1001 fps (59.94005994…) | No |
| Elapsed seconds | Frame index × 1001 ÷ 30000 (or ÷ 60000) | No |
| Nominal counting base | 30 or 60; sets how high the last field counts | No |
| Timecode label sequence | Which labels are assigned to consecutive frames | Yes, and only this |
“29.97” and “59.94” are rounded displays of those fractions. Calculations in this article use the exact rational rates.
The exact rates and label rules are separate concepts. For playback-rate mismatches, see 29.97 versus true 30 FPS.
Read the fields and the counting base
A label reads HH:MM:SS:FF. The last field is a frame number inside the current nominal second, counted from zero. It is not hundredths of a second. At 29.97 it runs 00–29 because the counting base is 30; at 59.94 it runs 00–59. For example, 00:00:01:12 at 29.97 NDF is frame index 42, which starts at 1.4014 s, not 1.12 s.
Punctuation is a common clue, not proof. Many editors write DF with a semicolon before the frame field and NDF with colons. SMPTE’s text notation, as summarized by EDLmax, also lets the separator signal interlace field information (period, colon, comma, semicolon). FFmpeg’s timecode option accepts a semicolon or a period for drop frame. A tool can display either style regardless of the file, so confirm the convention with the boundary tests below. Likewise, a frame-rate estimate such as the one from the video FPS checker tells you how quickly frames arrive. It does not tell you whether the labels skip.
Follow the first-minute boundary at 29.97
Table 1 lists six consecutive frames of a clip at 30000/1001 fps, starting at index 0. Each row is one actual picture. The DF and NDF columns label that same picture.
Table 1. 29.97 first-minute boundary (illustrative numbering, computed)
| Zero-based frame index | DF label | NDF label | Frame start time (s) |
|---|---|---|---|
| 1,797 | 00:00:59;27 | 00:00:59:27 | 59.959900 |
| 1,798 | 00:00:59;28 | 00:00:59:28 | 59.993267 |
| 1,799 | 00:00:59;29 | 00:00:59:29 | 60.026633 |
| 1,800 | 00:01:00;02 | 00:01:00:00 | 60.060000 |
| 1,801 | 00:01:00;03 | 00:01:00:01 | 60.093367 |
| 1,802 | 00:01:00;04 | 00:01:00:02 | 60.126733 |
The step from ;29 to ;02 looks like a gap, but the index advances by one (1,799 to 1,800), so exactly one frame interval of 1001/30000 s (33.367 ms) passes. Subtracting the printed fields by hand gives 3 frames; subtracting indices gives 1. Use indices whenever a duration crosses a minute boundary.
Why skip anything? After 1,800 frames, 60.06 s have really elapsed, but an NDF counter has counted them as a nominal 60 s (00:01:00:00). DF jumps to ;02, a nominal 60.0667 s, which is 6.7 ms from the true 60.06 s instead of 60 ms away. SMPTE’s ST 12-1 defines the rule; EDLmax quotes its drop-frame section as saying the first two frame numbers (00 and 01) shall be omitted from the count at the start of each minute except tenth minutes.
As a result, 00:01:00;00 and 00:01:00;01 do not label any frame under 29.97 DF. 00:01:00;02 is the first label of that minute.
Understand the tenth-minute exception
Ten minutes at 30000/1001 fps contain 600 × 30000 ÷ 1001 = 17,982.018 frames. A 30-per-second label count would run to 18,000 labels in that time, so about 18 labels must be skipped. Skipping two in every minute would remove 20, which overshoots. Skipping two in nine of every ten minutes removes exactly 18, leaving 17,982 labels against 17,982.018 frames. The tenth minute is exempt, and the leftover 0.018 frame is about 0.6 ms per ten minutes.
Table 2. 29.97 tenth-minute boundary
| Zero-based frame index | DF label | NDF label | Frame start time (s) |
|---|---|---|---|
| 17,979 | 00:09:59;27 | 00:09:59:09 | 599.899300 |
| 17,980 | 00:09:59;28 | 00:09:59:10 | 599.932667 |
| 17,981 | 00:09:59;29 | 00:09:59:11 | 599.966033 |
| 17,982 | 00:10:00;00 | 00:09:59:12 | 599.999400 |
| 17,983 | 00:10:00;01 | 00:09:59:13 | 600.032767 |
| 17,984 | 00:10:00;02 | 00:09:59:14 | 600.066133 |
Here nothing is skipped, so 00:10:00;00 and 00:10:00;01 are valid labels. The NDF column shows how far the counter has fallen behind: it is 12 labels short of 00:10:00:00 after 17,982 frames.
Off-by-one guard. 17,982 is both the number of elapsed frames at this point and the index of the frame labeled 00:10:00;00. A clip containing exactly 17,982 frames has indices 0 to 17,981. Its last frame is 00:09:59;29, and its duration is 17,982 × 1001 ÷ 30000 = 599.9994 s. A last-frame label is not a clip’s full duration.
Compare the 59.94 convention
At 60000/1001 fps the nominal base is 60 and DF skips four labels, ;00 to ;03, at the same minute boundaries. Software and vendor interfaces that count to 59 at this rate document this: GStreamer supports drop frame only at 30000/1001 and 60000/1001 (and its source comments skip two at 30000/1001 and four at 60000/1001), FFmpeg’s libavutil permits drop frame only with those two rates, and Apple documents a 59.94 drop type whose frame numbers are adjusted to match elapsed clock time. This article describes the 0–59 label convention that such tools display. It does not claim how any particular file stores its timecode.
Table 3. 59.94 first-minute boundary
| Zero-based frame index | DF label | NDF label | Frame start time (s) |
|---|---|---|---|
| 3,597 | 00:00:59;57 | 00:00:59:57 | 60.009950 |
| 3,598 | 00:00:59;58 | 00:00:59:58 | 60.026633 |
| 3,599 | 00:00:59;59 | 00:00:59:59 | 60.043317 |
| 3,600 | 00:01:00;04 | 00:01:00:00 | 60.060000 |
| 3,601 | 00:01:00;05 | 00:01:00:01 | 60.076683 |
| 3,602 | 00:01:00;06 | 00:01:00:02 | 60.093367 |
The skipped-label range at this boundary is 00:01:00;00 through 00:01:00;03.
Table 4. 59.94 tenth-minute boundary
| Zero-based frame index | DF label | NDF label | Frame start time (s) |
|---|---|---|---|
| 35,961 | 00:09:59;57 | 00:09:59:21 | 599.949350 |
| 35,962 | 00:09:59;58 | 00:09:59:22 | 599.966033 |
| 35,963 | 00:09:59;59 | 00:09:59:23 | 599.982717 |
| 35,964 | 00:10:00;00 | 00:09:59:24 | 599.999400 |
| 35,965 | 00:10:00;01 | 00:09:59:25 | 600.016083 |
| 35,966 | 00:10:00;02 | 00:09:59:26 | 600.032767 |
Compact comparison
| 29.97 NDF | 29.97 DF | 59.94 NDF | 59.94 DF | |
|---|---|---|---|---|
| Actual rate | 30000/1001 | same | 60000/1001 | same |
| Last field runs | 00–29 | 00–29 | 00–59 | 00–59 |
| Labels skipped | none | ;00, ;01 | none | ;00 to ;03 |
| Skipped when | never | first second of each minute not divisible by 10 | never | same schedule |
| Labels per 10 minutes | 18,000 | 17,982 | 36,000 | 35,964 |
| Labels per hour | 108,000 | 107,892 | 216,000 | 215,784 |
| Real time at label 01:00:00 | 3,603.6 s | 3,599.9964 s | 3,603.6 s | 3,599.9964 s |
Convert frame counts into labels and real seconds
Table 5. Checked controls (counts are elapsed frames from 00:00:00 unless stated)
| Quantity | 29.97 (30000/1001) | 59.94 (60000/1001) |
|---|---|---|
| Elapsed frames | 17,982 | 35,964 |
| DF label of frame index equal to that count | 00:10:00;00 | 00:10:00;00 |
| NDF label of the same frame | 00:09:59:12 | 00:09:59:24 |
| Exact elapsed time | 2,999,997/5,000 s = 599.9994 s | 2,999,997/5,000 s = 599.9994 s |
| Last frame within those elapsed frames (index) | 17,981: DF 00:09:59;29 | 35,963: DF 00:09:59;59 |
| One hour of NDF labels (01:00:00:00) | 108,000 frames = 3,603.6 s | 216,000 frames = 3,603.6 s |
| One hour of DF labels (01:00:00;00) | 107,892 frames = 3,599.9964 s | 215,784 frames = 3,599.9964 s |
An NDF label of 01:00:00:00 therefore describes 3.6 s more than an hour. Run the clock for exactly 3,600 s and the frame being shown is index 107,892 at 29.97: 00:59:56:12 in NDF and 01:00:00;00 in DF. DF is not perfect: labels read as nominal seconds are 0.6 ms off at each ten-minute mark, 3.6 ms off at one hour, and between those marks a frame’s true start can sit roughly 64 ms below to 60 ms above its nominal label time during the first hour (about two frames at 29.97). Over an unwrapped elapsed count, NDF’s offset accumulates; a displayed clock may roll over. For the intervals here: 0.06 s after one minute, 0.6 s after ten, 3.6 s after one hour.
A calculation you can reproduce: 00:12:34;15 at 29.97 DF
Nominal label count at base 30: (12 × 60 + 34) × 30 + 15 = 22,635.
Minutes 1 to 12 each begin with a skip except minute 10, which makes 11 skips of 2 labels: 22.
Frame index = 22,635 − 22 = 22,613 (zero-based).
Start time = 22,613 × 1001 ÷ 30,000 = 22,635,613 ÷ 30,000 = 754.520433 s.
Read the same text as NDF and you get index 22,635, which is 22 frames (0.734 s) later. Mixing the two conventions at minute 12 shifts a cue by 22 frames. At 59.94 the same label gives 754 × 60 + 15 = 45,255, minus 11 × 4 = 44, so index 45,211 at 754.270183 s.
The mismatch grows by two frames per minute at 29.97 (four at 59.94), pausing at each tenth minute. You can use the Extract Video Frames timecode calculator to check the frame count and timecode for your own label.
A duration between two labels follows the same rule. From 00:03:21;10 (index 6,034) to 00:12:34;15 (index 22,613) is 16,579 elapsed frames, or 553.185967 s. Subtracting the printed fields would not give that.
Diagnose invalid labels and mismatched settings
A label is invalid when:
The frame field reaches the counting base, such as ;30 at 29.97 or ;60 at 59.94.
Minutes or seconds are 60 or higher.
Under DF, seconds are 00, the minute is not divisible by ten, and the frame field is below the skip count: under 2 at 29.97, under 4 at 59.94.
| Label | Convention | Valid? | Why |
|---|---|---|---|
| 00:01:00;00, 00:01:00;01 | 29.97 DF | No | Skipped at a non-tenth minute |
| 00:01:00;02 | 29.97 DF | Yes | First label of the minute |
| 00:10:00;00, 00:10:00;01 | 29.97 DF | Yes | Tenth minute, nothing skipped |
| 00:02:00;01 | 29.97 DF | No | Skipped at minute 2 |
| 00:01:00;00 to ;03 | 59.94 DF | No | Four labels skipped |
| 00:01:00;04 | 59.94 DF | Yes | First label of the minute |
| 00:01:00:00 | 29.97 NDF | Yes | NDF skips nothing, so the same text is fine here |
| 00:00:59;30 | 29.97 | No | Frame field exceeds the base |
Symptoms from mismatched settings are recognizable by size:
| Symptom | Likely cause | Check |
|---|---|---|
| Label jumps by 2 (or 4) at a minute boundary | Normal DF skip, nothing lost | Compare frame indices across the jump |
| Cues land 2 frames off after minute 1, 22 frames off after minute 12 | DF text treated as NDF or the reverse | Convert via frame index, not by swapping punctuation |
| Drift reaching about 3.6 s per labeled hour | DF/NDF mix, or 1000/1001 rate confused with its integer rate | Verify the exact rate and the convention |
| Constant offset of exactly one hour | Start reference of 01:00:00:00 | Subtract the actual start label |
| One frame too long or short | Inclusive endpoint counting | See the position-or-duration check below |
Switching DF/NDF does not repair a frame-rate or audio-sync problem. It changes the numbers printed beside the same frames, and Adobe states that changing the display format does not alter the frame rate of clips or sequences. Closed Caption Creator draws the useful line between relabeling (the picture times stay put) and conforming to a different rate (every time must be recalculated). If cues drift, look for a rate or start mismatch rather than a display toggle.
Choose the convention your workflow requires
A written delivery requirement. If a spec, broadcaster or client names DF or NDF, follow it. That is a requirement.
The convention of the material you were given. Match the EDL, caption file or project you are working from.
Your project default. With neither of the above, choose one and record it. This is a preference, and sources disagree on which is better. For NTSC work, Adobe’s sequence reference recommends drop-frame timecode because it displays duration accurately, while others favor NDF for frame counting. B&H lists system specification, distribution media and editor preference as the deciding factors.
No single convention is universally required. Caption formats illustrate this: per Closed Caption Creator, SCC signals DF with a semicolon, while SRT and WebVTT store real time and have no DF or NDF at all. Converting between them still needs the exact rate and convention.
Checklist when someone sends you a timecode
Actual rate: exact value (for example 30000/1001), not just “30.”
Counting convention: DF or NDF, confirmed with a boundary test, not punctuation alone.
Start reference: does 00:00:00 mean the first frame, or does the source begin at 01:00:00:00 or a time-of-day value?
Position or duration: a label is a position; a duration is a difference of indices. Adobe’s timecode help notes that In and Out points identical in timecode give a one-frame duration, so confirm whether the end frame is included.
Frequently asked questions
Does drop frame delete frames or change speed? No. Pictures and playback rate are untouched; only labels differ.
Is DF identical to wall-clock time? No. It stays within about 0.6 ms per ten minutes at the ten-minute marks and a few tens of milliseconds in between.
Is there drop frame at 23.976? The common 29.97/59.94 rules described here do not supply a 23.976 DF convention. The referenced tools limit their supported DF modes to particular multiples of 30000/1001 (GStreamer’s code states that 24000/1001 is not a drop-frame rate, and Medialooks and Epic’s Unreal docs say the same). The 1000/1001 offset still exists there; it is just not corrected by skipping labels.
Can I turn a DF label into NDF by swapping the semicolon? No. Convert through the frame index: 00:01:00;02 DF and 00:01:00:00 NDF are the same frame.
How were these examples checked? They were computed in exact rational arithmetic in Python (a literal label enumeration compared with a closed-form conversion across full hours), and the boundary labels were compared with FFmpeg’s drop-frame counter rendered as a synthetic text overlay. That overlay illustrates the numbering rule only. It does not show that any media file carries valid embedded timecode metadata.
Keep the clocks separate
A constant fractional rate can have regular frame intervals. DF/NDF chooses how those frames are labeled, not when their pictures appear. At film rates, compare 23.976 and true 24 FPS before interpreting a timecode as a stopwatch duration.
Boundary labels, skipped-label rejection and frame-count conversions were checked against the calculator functions and independent exact-rational arithmetic. Diagrams show zero-based label models, not embedded media metadata.
Examples and calculations are scoped to their stated settings. Source links support the instructions; an illustration is not a screenshot of an application test.