I took this over to AI first (Abacus.ai ChatLLM in Agent mode set to Max - Fable 5.1 + GPT-6 Astra) for troubleshooting.
The problem is that I couldn't get smooth playback when re-encoding the source to CPS, and I also had mismatching frame totals, and mismatching frames from input file to output file when they did match.
Source:
It says, "Frame rate: 38.870 FPS". Hybrid is trying to use that, when it should instead be using 60 FPS (i.e., 60,1). It is also generating an incorrect Matroska timecode v2 file with 19,173 frames instead of the input file's actual frame count of 12,434.
According to the AI:
Here is the AI "bug report for the developer":
Regarding the #4 "Suggestion" above, Hybrid output to the "Log" tab "Current frame rate: 59.946 differs from average time code frame rate: 38.87. This will be ignored since 'Check average fps of mkv/mp4 files' is disabled." As much as I tried, I could not find any Check average fps of mkv/mp4 files setting. I'm not sure if that would have any bearing on anything here.
Hybrid_Variable_Framerate_Issue.zip (Size: 946,94 KB / Downloads: 4)
Contents of attachment:
The problem is that I couldn't get smooth playback when re-encoding the source to CPS, and I also had mismatching frame totals, and mismatching frames from input file to output file when they did match.
Source:
General
Count : 365
Count of stream of this kind : 1
Kind of stream : General
Kind of stream : General
Stream identifier : 0
Count of video streams : 1
Count of audio streams : 1
Video formats : HEVC
Video formats (with hints) : HEVC
Codecs Video : HEVC
Audio formats : AAC LC
Audio formats (with hints) : AAC LC
Audio codecs : AAC LC
Total audio channels : 2
Complete name : E:\test_vid\Test_vid_source.mov
Folder name : E:\test_vid
File name extension : Test_vid_source.mov
File name : Test_vid_source
File extension : mov
Format : MPEG-4
Format : MPEG-4
Format/Extensions usually used : braw mov mp4 m4v m4a m4b m4p m4r 3ga 3gpa 3gpp 3gp 3gpp2 3g2 k3g jpm jpx mqv ismv isma ismt f4a f4b f4v
Commercial name : MPEG-4
Format profile : Base Media
Internet media type : video/mp4
Codec ID : isom
Codec ID : isom (isom/iso2/mp41)
Codec ID/Url : http://www.apple.com/quicktime/download/standalone.html
CodecID_Compatible : isom/iso2/mp41
File size : 525499133
File size : 501 MiB
File size : 501 MiB
File size : 501 MiB
File size : 501 MiB
File size : 501.2 MiB
Duration : 320189
Duration : 5 min 20 s
Duration : 5 min 20 s 189 ms
Duration : 5 min 20 s
Duration : 00:05:20.189
Duration : 00:05:18:32
Duration : 00:05:20.189 (00:05:18:32)
Overall bit rate : 13129724
Overall bit rate : 13.1 Mb/s
Frame rate : 38.870
Frame rate : 38.870 FPS
Frame count : 12434
Stream size : 427866
Stream size : 418 KiB (0%)
Stream size : 418 KiB
Stream size : 418 KiB
Stream size : 418 KiB
Stream size : 417.8 KiB
Stream size : 418 KiB (0%)
Proportion of this stream : 0.00081
HeaderSize : 427858
DataSize : 525071275
FooterSize : 0
Is streamable : Yes
Encoded date : 2025-11-29 19:04:23 UTC
Tagged date : 2025-11-29 19:05:42 UTC
File creation date : 2026-10-30 06:11:12.699 UTC
File creation date (local) : 2026-10-30 02:11:12.699
File last modification date : 2026-09-27 12:31:36.730 UTC
File last modification date (local) : 2026-09-27 08:31:36.730
major_brand : Apple QuickTime (.MOV/QT)
minor_version : 0.0.0
compatible_brands : qt
creation_time : 2025-11-29T19:04:23.000000Z
com.apple.quicktime.author : ReplayKitRecording
encoder : Lavf62.6.101
Video
Count : 402
Count of stream of this kind : 1
Kind of stream : Video
Kind of stream : Video
Stream identifier : 0
Stream order : 0
ID : 1
ID : 1
Format : HEVC
Format : HEVC
Format/Info : High Efficiency Video Coding
Format/Url : http://www.itu.int
Commercial name : HEVC
Format profile : Main@L4.1@Main
Internet media type : video/H265
Codec ID : hvc1
Codec ID/Info : High Efficiency Video Coding
Codec ID/Url : http://www.itu.int/
Duration : 319874
Duration : 5 min 19 s
Duration : 5 min 19 s 874 ms
Duration : 5 min 19 s
Duration : 00:05:19.874
Duration : 00:05:18:32
Duration : 00:05:19.874 (00:05:18:32)
Source duration : 319890
Source duration : 5 min 19 s
Source duration : 5 min 19 s 890 ms
Source duration : 5 min 19 s
Source duration : 00:05:19.890
Source duration : 00:05:18:32
Source duration : 00:05:19.890 (00:05:18:32)
Bit rate : 13005222
Bit rate : 13.0 Mb/s
Width : 886
Width : 886 pixels
Height : 1538
Height : 1 538 pixels
Stored_Width : 896
Stored height : 1552
Sampled width : 886
Sampled height : 1538
Pixel aspect ratio : 1.000
Display aspect ratio : 0.576
Display aspect ratio : 9:16
Rotation : 0.000
Frame rate mode : VFR
Frame rate mode : Variable
Frame rate : 38.870
Frame rate : 38.870 FPS
Minimum frame rate : 15.000
Minimum frame rate : 15.000 FPS
Maximum frame rate : 60.000
Maximum frame rate : 60.000 FPS
Frame count : 12434
Source frame count : 12434
Color space : YUV
Chroma subsampling : 4:2:0
Chroma subsampling : 4:2:0
Bit depth : 8
Bit depth : 8 bits
Bits/(Pixel*Frame) : 0.246
Stream size : 520030093
Stream size : 496 MiB (99%)
Stream size : 496 MiB
Stream size : 496 MiB
Stream size : 496 MiB
Stream size : 495.9 MiB
Stream size : 496 MiB (99%)
Proportion of this stream : 0.98959
Source stream size : 520030093
Source stream size : 496 MiB (99%)
Source stream size : 496 MiB
Source stream size : 496 MiB
Source stream size : 496 MiB
Source stream size : 495.9 MiB
Source stream size : 496 MiB (99%)
Source_StreamSize_Proportion : 0.98959
Title : Core Media Video
Writing library : HEVC
Writing library : HEVC
Encoded date : 2025-11-29 19:04:23 UTC
Tagged date : 2025-11-29 19:05:42 UTC
Color description present : Yes
Color description present (source) : Container / Stream
Color range : Full
Color range (source) : Container / Stream
Color primaries : BT.709
Color primaries (source) : Container / Stream
Transfer characteristics : sRGB/sYCC
Transfer characteristics (source) : Container / Stream
Matrix coefficients : BT.709
Matrix coefficients (source) : Container / Stream
Source_Delay : -100
Source_Delay_Source : Container
mdhd_Duration : 319873
Codec configuration box : hvcCIt says, "Frame rate: 38.870 FPS". Hybrid is trying to use that, when it should instead be using 60 FPS (i.e., 60,1). It is also generating an incorrect Matroska timecode v2 file with 19,173 frames instead of the input file's actual frame count of 12,434.
According to the AI:
Quote:Your source isn't really "38.870 fps". It's an iPhone ReplayKit capture on a 60 Hz grid. Each frame stays on screen for 1, 2 or 3 display refreshes, so the video switches between 60, 30 and 20 fps depending on how much is moving. 38.87 is just the average (12,434 frames ÷ 319.8 s). No frame in the file actually lasts 1/38.87 s.
There are three separate problems. One is in how Hybrid calls ffmpeg, not in ffmpeg itself, and the other two are Hybrid logic choices:
- The 19,173-line timecode file. Hybrid runs ffmpeg without -fps_mode passthrough. The mkvtimestamp_v2 muxer is a raw-video output that doesn't declare variable-frame-rate support, so ffmpeg's default auto mode switches to CFR. It then fills a 59.94 fps grid by duplicating 6,739 frames (12,434 + 6,739 = 19,173 timestamps + header). ffmpeg logs this openly: dup=6739, "More than 1000 frames duplicated". That's documented, intended ffmpeg behaviour, not an ffmpeg bug.
- The VFR encode (8,065 frames, 3:27). Hybrid noticed the timecode count didn't match the frame count, then changed the frame count to fit the bad timecodes instead of rejecting them. On top of that, its frameserver pipe uses -fps_mode auto -r 3887/100, which drops frames. Only 8,065 frames got to x264, and they were timed with the first 8,065 entries of the bogus 59.94 grid.
- The CFR encode (choppy, frame numbers off). That one is working as designed, but 38.87 is the wrong target. L-SMASH (fpsnum=3887, fpsden=100) resamples 60/30/20 fps material onto a 38.87 grid. My simulation using your ffprobe timestamps: 2,133 frames dropped and 2,133 duplicated, unevenly spread. That's the judder on pans.
Here is the AI "bug report for the developer":

Quote:Hybrid 2026.10.10.1 (64-bit), Windows 10 22H2. VFR source (iPhone ReplayKit HEVC .mov, 12,434 frames, avg 38.87 fps, actual 60 Hz cadence with 1/2/3-refresh frame durations, tbn 19200, ffmpeg-reported tbr 59.94). ffmpeg N-126512-gf7fbb1260e.
Debug logs (variable and constant runs), MediaInfo, ffprobe CSV and the bad/good timecode files are available.
- Timecode extraction produces CFR-padded timecodes.
Call: ffmpeg.exe -y -i "X.mov" -map 0:0 -f mkvtimestamp_v2 "X.txt" (log line 1180).
Because no -fps_mode is given, ffmpeg's auto mode chooses CFR for the mkvtimestamp_v2 (rawvideo-style) muxer and pads to the stream tbr (59.94): ffmpeg reports frame=19173 ... dup=6739 drop=0 and "More than 1000 frames duplicated" (lines 1248/1266). The resulting file is a pure 59.94 grid (16/17 ms deltas only) with 19,173 entries instead of 12,434.
Fix: add -fps_mode passthrough (-vsync 0 / -vsync passthrough for older builds), and preferably -an -sn and -map 0:v:0. Alternatives: ffprobe -show_entries frame=pts_time (sorted) or mkvmerge + mkvextract timestamps_v2.
- Frame count is adjusted to a mismatching timecode count instead of rejecting the timecodes.
Log lines 20451–20453: Adjusting frame count (12434) to time code entry count (19173). then Current frame rate: 59.946 differs from average time code frame rate: 38.87. This will be ignored since 'Check average fps of mkv/mp4 files' is disabled.
A timecode count that differs from the decoder's frame count by 54 % should be treated as an error: warn, then fall back to a different extraction method or CFR. The job carries 19172/38.87 from then on (e.g. line 32289).
- VFR (non-CFR) jobs resample in the frameserver pipe.
Decode call (line 147489): ffmpeg ... -i script.avs -an -sn -pix_fmt yuv420p -fps_mode auto -r 3887/100 -f rawvideo - | x264 ..., with a script using LWLibavVideoSource(...) without fpsnum (12,434 frames 1:1).
-r + -fps_mode auto on rawvideo makes ffmpeg CFR-convert (nominal ~59.94 → 38.87), so only 8,065 of 12,434 frames reach x264. mp4fpsmod then applies the first 8,065 timecodes (video source duration 2:14.551 in MediaInfo; container 3:27.485).
Fix: when timecodes will be applied, the pipe must use -fps_mode passthrough and no -r, so every frameserver frame reaches the encoder 1:1.
- Suggestion: CFR conversion target for VFR sources.
With "CFR Output" checked, Hybrid uses fpsnum=3887,fpsden=100 (the average rate). For sources on a fixed refresh grid (screen recordings, phone captures: 60 Hz base, 19200 tbn), the average is the worst possible target: 2,133 drops + 2,133 dups here, visible judder, and frame indices drift (src 300 → dst ~380, src 3000 → dst ~2703). Using the base rate (60/1, derived from the timestamp GCD / timebase rather than the rounded 59.94 tbr), or at least offering it as an option, gives judder-free CFR output.
Regarding the #4 "Suggestion" above, Hybrid output to the "Log" tab "Current frame rate: 59.946 differs from average time code frame rate: 38.87. This will be ignored since 'Check average fps of mkv/mp4 files' is disabled." As much as I tried, I could not find any Check average fps of mkv/mp4 files setting. I'm not sure if that would have any bearing on anything here.

Hybrid_Variable_Framerate_Issue.zip (Size: 946,94 KB / Downloads: 4)
Contents of attachment:
- MediaInfo_Source.txt - MediaInfo output (advanced) for source file.
- MediaInfo_Destination_Variable.txt - MediaInfo output (advanced) for destination file encoded with Hybrid and variable bitrate using Test_vid_source.tc timecode v2 file with incorrect number of frames (19,173); number of frames (8,065) and duration (00:03:27.485) in output file are incorrect.
- MediaInfo_Destination_Constant.txt - MediaInfo output (advanced) for destination file encoded with Hybrid and constant bitrate; number of frames (12,434) and duration (00:05:19.887) are correct in output file, audio is synced, but playback is choppy and video frame captures don't line up between source and destination matching frame numbers (checked using VirtualDub2).
- Test_vid_source.tc - Output from ffmpeg.exe -y -i "Test_vid_source.mov" -map 0:0 -f mkvtimestamp_v2 "Test_vid_source.txt" (this is what Hybrid currently uses); incorrect number of frames (19,173).
- Test_vid_source.csv - Output from ffprobe -v error -select_streams v:0 -show_entries frame=coded_picture_number,pts_time -of csv "Test_vid_source.mov" > "Test_vid_source.csv"; this takes longer to run than Hybrid's FFmpeg command above but is much more accurate, and in this case has the correct number of frames (12,434). You may want to consider using this instead of FFmpeg with -fps_mode passthrough.
- HybridDebugOutput_variable.zip - Hybrid's highest level debug output file for re-encoding the source file with Hybrid and variable bitrate using Test_vid_source.tc timecode v2 file with incorrect number of frames (19,173); number of frames (8,065) and duration (00:03:27.485) in output file are incorrect.
- HybridDebugOutput_constant.zip - Hybrid's highest level debug output file for re-encoding the source file with Hybrid and constant bitrate; number of frames (12,434) and duration (00:05:19.887) are correct in output file, audio is synced, but playback is choppy and video frame captures don't line up between source and destination matching frame numbers.
AI Output Files
- abacus_ai_chat_llm_agent_max.md - Full output from Abacus AI ChatLLM Agent/Max.
- Test_vid_source_correct_v2.tc - "The corrected timecode v2 file built from your ffprobe CSV: 12,434 timestamps in ms, presentation order, starting at 0."
- csv_to_tcv2.py - "Converts any ffprobe pts_time CSV into a v2 timecode file (run: python csv_to_tcv2.py in.csv out.tc)."

