ffmpeg: ffmpeg version 6.1.1-3ubuntu5 Copyright (c) 2000-2023 the FFmpeg developers excerpt: start 60 s, duration 10 s; frames compared as 160x90 gray md5 of decoded pictures source 24 fps: 240 frames, all hashes distinct: True 24->24: out frames 240, unmapped 0, source frames kept 240 of 240, dropped 0 (0.00%), repeated output frames 0 (0.00%), longest hold 1, distinct hold lengths [1], first 12 holds 1,1,1,1,1,1,1,1,1,1,1,1 24->30: out frames 300, unmapped 0, source frames kept 240 of 240, dropped 0 (0.00%), repeated output frames 60 (20.00%), longest hold 2, distinct hold lengths [1, 2], first 12 holds 1,2,1,1,1,2,1,1,1,2,1,1 24->60: out frames 600, unmapped 0, source frames kept 240 of 240, dropped 0 (0.00%), repeated output frames 360 (60.00%), longest hold 3, distinct hold lengths [2, 3], first 12 holds 3,2,3,2,3,2,3,2,3,2,3,2 source 30 fps: 300 frames, all hashes distinct: True 30->24: out frames 240, unmapped 0, source frames kept 240 of 300, dropped 60 (20.00%), repeated output frames 0 (0.00%), longest hold 1, distinct hold lengths [0, 1], first 12 holds 1,1,0,1,1,1,1,0,1,1,1,1 30->30: out frames 300, unmapped 0, source frames kept 300 of 300, dropped 0 (0.00%), repeated output frames 0 (0.00%), longest hold 1, distinct hold lengths [1], first 12 holds 1,1,1,1,1,1,1,1,1,1,1,1 30->60: out frames 600, unmapped 0, source frames kept 300 of 300, dropped 0 (0.00%), repeated output frames 300 (50.00%), longest hold 2, distinct hold lengths [2], first 12 holds 2,2,2,2,2,2,2,2,2,2,2,2 source 60 fps: 600 frames, all hashes distinct: True 60->24: out frames 240, unmapped 0, source frames kept 240 of 600, dropped 360 (60.00%), repeated output frames 0 (0.00%), longest hold 1, distinct hold lengths [0, 1], first 12 holds 0,1,0,1,0,0,1,0,1,0,0,1 60->30: out frames 300, unmapped 0, source frames kept 300 of 600, dropped 300 (50.00%), repeated output frames 0 (0.00%), longest hold 1, distinct hold lengths [0, 1], first 12 holds 1,0,1,0,1,0,1,0,1,0,1,0 60->60: out frames 600, unmapped 0, source frames kept 600 of 600, dropped 0 (0.00%), repeated output frames 0 (0.00%), longest hold 1, distinct hold lengths [1], first 12 holds 1,1,1,1,1,1,1,1,1,1,1,1 #### extra checks (test-extra.sh) == ffprobe of a 10 s excerpt of the 24 fps source (control: expect 24/1) r_frame_rate=24/1 avg_frame_rate=24/1 nb_frames=240 == convert to 30 fps with the fps filter, then ffprobe (expect 30/1 and 300 frames) r_frame_rate=30/1 avg_frame_rate=30/1 nb_frames=300 == YouTube 1080p SDR bitrate ratio, high frame rate 12 Mbps over standard 8 Mbps ratio 1.50, increase 50% == hold 3 against hold 2 (24 to 60 pattern) 3/2 = 1.50, so 50% longer #### source files (sha256 of the zips downloaded from download.blender.org) 109e3ede8790bd633f374ca311d9cc61dce8d7f98f5b0797ca98199c9fbceedf src/BigBuckBunny_320x180.mp4.zip e320fef389ec749117d0c1583945039266a40f25483881c2ff0d33207e62b362 src/bbb_sunflower_1080p_30fps_normal.mp4.zip 68c456673409f8df09b80d0afe29ecb38ef110551fa8a93c83e54a96ebdaec78 src/bbb_sunflower_1080p_60fps_normal.mp4.zip #### live-action footage (editor addition, October 27, 2026; script test-live.py; sources: Wikimedia Commons CC0 titmouse clip, CC BY 3.0 Sony FS700 salad clip) source titmouse.webm at 30/1 fps, excerpt start 5 s, 10 s: 300 frames, all hashes distinct: True -> source: out frames 300, unmapped 0, source frames kept 300 of 300, dropped 0 (0.00%), repeated output frames 0 (0.00%), distinct hold lengths [1], first 12 holds 1,1,1,1,1,1,1,1,1,1,1,1 -> 24: out frames 240, unmapped 0, source frames kept 240 of 300, dropped 60 (20.00%), repeated output frames 0 (0.00%), distinct hold lengths [0, 1], first 12 holds 1,1,0,1,1,1,1,0,1,1,1,1 -> 30: out frames 300, unmapped 0, source frames kept 300 of 300, dropped 0 (0.00%), repeated output frames 0 (0.00%), distinct hold lengths [1], first 12 holds 1,1,1,1,1,1,1,1,1,1,1,1 -> 60: out frames 600, unmapped 0, source frames kept 300 of 300, dropped 0 (0.00%), repeated output frames 300 (50.00%), distinct hold lengths [2], first 12 holds 2,2,2,2,2,2,2,2,2,2,2,2 source salad.webm at 24000/1001 fps, excerpt start 10 s, 10 s: 240 frames, all hashes distinct: True -> source: out frames 240, unmapped 0, source frames kept 240 of 240, dropped 0 (0.00%), repeated output frames 0 (0.00%), distinct hold lengths [1], first 12 holds 1,1,1,1,1,1,1,1,1,1,1,1 -> 24: out frames 240, unmapped 0, source frames kept 240 of 240, dropped 0 (0.00%), repeated output frames 0 (0.00%), distinct hold lengths [1], first 12 holds 1,1,1,1,1,1,1,1,1,1,1,1 -> 30: out frames 301, unmapped 0, source frames kept 240 of 240, dropped 0 (0.00%), repeated output frames 61 (20.27%), distinct hold lengths [1, 2], first 12 holds 2,1,1,1,2,1,1,1,2,1,1,1 -> 60: out frames 600, unmapped 0, source frames kept 240 of 240, dropped 0 (0.00%), repeated output frames 360 (60.00%), distinct hold lengths [2, 3], first 12 holds 2,3,2,3,2,3,2,3,2,3,2,3