DropFrameTimecode · Article
← Guide
Field guide

Why your reader says 30 when you're really running 29.97 ND

You set your generator to 29.97 non-drop, send LTC down the line, and the reader on the other end — or the lighting console, or the field recorder — proudly shows 30. Did you do something wrong? No. Your reader did. Here's what's actually happening.

LTC carries the time, not the rate

Linear Timecode packs each frame into an 80-bit word: hours, minutes, seconds, frames, a few user bits, a sync word, and a small handful of flags. One of those flags is the drop-frame bit. What's not in there? The frame rate. There is no field in LTC that says "this is 29.97" or "this is 30." The stream just counts frames.

That means 29.97 non-drop and 30 are bit-for-bit identical in the data. Same numbers, same flags. The only physical difference is timing: a 29.97 stream plays about 0.1% slower, so its frames land fractionally farther apart in real time. The bits are the same; the clock underneath is not.

So what's the drop-frame flag for?

Drop-frame exists because 29.97 fps drifts against the wall clock (~3.6 seconds per hour). Drop-frame renumbering skips two frame numbers each minute (except every tenth) to keep timecode tracking real time. The flag tells a reader "these numbers are drop-frame counted."

Crucially, that flag distinguishes 29.97 drop (and 59.94 drop) — the numbering pattern is visibly different. It does nothing for 29.97 non-drop vs 30. Both are non-drop, both carry the flag off, both count 0–29 every second. Identical.

Why readers get it wrong

Because the rate isn't in the data, the only way to know it is to measure — count how far apart frames actually arrive in real seconds and work out the rate (29.97 frames per real second, vs exactly 30). Plenty of hardware readers don't bother. They assume a rate, or round to the nearest "nice" number, and a true 29.97 non-drop signal gets labelled 30. It's not lying maliciously — it just never measured.

Does it actually matter?

Sometimes it's cosmetic: if everyone downstream simply programs to whatever number hits their desk, the label doesn't change the work. But it bites when a device assumes a rate that doesn't match what you're feeding it. Send 29.97 to something running 30 (or vice versa) and you accumulate that 0.1% — roughly 3.6 seconds per hour, about 1.8 frames per minute. Over long-form playback, a show, or a multicam day, that's the difference between "in sync" and "why is everything slipping."

What to do about it

Two things. First, generate at the exact rate you mean, from a tool that renders it faithfully — pick your rate and drop/non-drop and get a verified file, nothing uploaded. Second, don't fully trust a reader that rounds. If a box can't tell you it measured 29.97 versus assumed it, treat its frame-rate label as a guess.

The short version: LTC carries the time, not the rate. 29.97 non-drop and 30 look identical on the wire — the difference is 0.1% of clock that only a measurement can reveal. Know your rate, set it on purpose, and verify it from the source.
Generate verified SMPTE LTC / BWF — free, in your browser → Pick the rate and drop/non-drop; nothing uploaded.