Forum Replies Created

  • Jeff Alldridge

    September 9, 2026 at 10:44 pm in reply to: Why has 25fps exported as 23.81?

    Nine years late, Christie, and your DCP went out long ago. So this is really for whoever types that number into Google and lands here next, which is exactly how I turned up.

    Fair warning. This precise question sent me down a rabbit hole that ended with me writing an app. Not a proportionate response to a forum post. But once you see where 23.81 comes from you can’t unsee it.

    23.81 is not a frame rate. Nobody shoots at it, no standard contains it, no camera offers it.

    1000 divided by 42 is 23.8095.

    That’s the whole number. Something in your chain wrote your frame duration as a whole number of milliseconds and landed on 42. Yes, 42.

    So where does 42 come from? A 23.976 frame lasts 41.708 milliseconds. Round that to the nearest whole millisecond and you get 42. Divide back out and the file cheerfully announces 23.81.

    Which answers what you actually asked, and it’s slightly annoying. A 25 fps frame is 40 milliseconds. Exactly forty. Nothing to round, no remainder, nothing to lose. You can’t reach 23.81 from 25 by this route however hard you push, and I did push before typing this.

    So by the time that header got written your file wasn’t 25 anymore. Something conformed it to 23.98 on the way out and the rounding did the rest. Nick was pointing straight at it: export as QuickTime Movie and leave the dropdown on Current Settings. QuickTime Conversion is where a preset quietly conforms you and never mentions it.

    Quick way to see how bad it is. Count the frames in the export and compare against your timeline. Same count means nothing got dropped and this is purely a label. Which is the good news and the bad news, because a label this wrong still costs you: 25 divided by 23.8095 is exactly 1.05, so the whole film is running five percent slow. Your 100 minute cut arrives as 105.

    Fixable without re-rendering, though. Richard’s instinct about Cinema Tools was right even though the software was already a ghost by 2017. Rewrite the header, leave the pictures alone.

    Holy crap. I haven’t thought about Cinema Tools in forever! I was telling a younger editor about edit decisions lists (EDL). I thought I was young. But when you’re old enough to know EDLs… 😑

    And that’s the rabbit hole. I kept meeting files where every frame was present and correct and the header was lying about how fast to play them, and re-encoding a whole feature to correct a number is stupid. So I built something that rewrites the timing and leaves the pictures alone. Full disclosure that I make it, so I’m not neutral here. But it’s a header fix whatever you reach for, and that’s the bit worth knowing.

  • Late to this one, but it’s a good puzzle and I think it’s fixable without re-encoding anything.

    I grabbed the .mp4 you posted on the 12th, the one you flagged as the dodgy upload. That’s actually the useful one, since it’s the file that misbehaves.

    Good news first. The timing is clean. 552 video samples, all exactly the same length, dead constant. So this isn’t ragged timestamps or a variable frame rate, which is where I’d usually start looking.

    The problem is that those 552 samples only decode to 276 pictures. The stream is field coded, so each field got stored as its own sample instead of the pair being packaged as one interlaced frame. The sample table says 50 pictures per second. There are 25.

    That’s the judder. Final Cut believes the container, lays 552 half-pictures on the timeline as though they were whole ones, and you get what you’re seeing. QuickTime, VLC, and Resolve decode the stream and pair the fields themselves, so they never notice the sample table is wrong. And your .mts has no sample table at all. A transport stream is just a stream, and the decoder pairs fields as it goes. That’s why the original imports fine and the rewrap doesn’t.

    It also explains the thing that was nagging you. Progressive footage off the same camera rewraps fine because there’s one picture per sample. Nothing to pair, so nothing to get wrong. This isn’t Final Cut being weird about AVCHD. It reads your AVCHD fine. It’s this particular rewrap.

    And it explains both workarounds. The ProRes transcode read the already-split file, so it just re-encoded the bad interpretation. The H.265 version went back to the original and almost certainly deinterlaced along the way, which is why it looks right and also why it isn’t quite the same footage anymore.

    Now the annoying part. I tried a few stream-copy routes to get those fields paired back up, including a round trip out to a transport stream and back. None of them worked. A copy moves packets one for one, so once they’re split they stay split. One route quietly dropped two frames, which tells you something about how much to trust it. So this particular .mp4 is a write-off. The pairing decision got made when Shutter Encoder wrote it.

    Worth digging around in Shutter Encoder for a setting that controls how it packages interlaced streams, since the run that matters is straight from the .mts. If there isn’t one, I’d keep the .mts and call it done. For what started all this, the rewrap only saves you the transport stream’s packet overhead, a few percent. Thin prize for giving up a format Final Cut already reads.

    If you want to check a file yourself:

    ffprobe -v error -select_streams v:0 -count_frames \
      -show_entries stream=r_frame_rate,nb_read_frames,duration \
      -of default=nw=1 yourfile.mp4

    Divide nb_read_frames by duration. If you get 25 while r_frame_rate says 50, that’s this.

    One warning. Don’t use ffprobe’s field_order to diagnose it. I checked it on a source file, a rewrap, and a full re-encode, and it said “tt” every time. It reads the H.264 headers rather than the container, so it’ll tell you everything’s fine while Final Cut clearly disagrees.

    Full disclosure, I hit this same wall a while back and ended up building a Mac app for it. It doesn’t fix your file either. I ran yours through before posting to check, and it normalizes the timebase but leaves the field pairing alone, so it came out the same shape it went in. Figured I’d tell you what I actually found instead of what I’d have liked to find.

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy