Hi, A few months ago, my GoPro randomly started creating some corrupt (or partly-corrupt) video files, mixing up frames and causing jaggy playback.To illustrate the case, here is an excerpt I generated with "ffmpeg -c copy" from a corrupt source file : https://drive.google.com/file/d/1GD7YiVS2z8h0r6UdsPPIXFgnh9RukoeR/view?usp=sharing
As you can see, frames are mixed up, but with a repeating pattern. By playing the file frame by frame, I observed that the mangling pattern repeats every 5 frames and that frames should be played in order 1-0-3-4-2 - 6-5-8-9-7 - 11-10-13-14-12 - 16-15-18-19-17 - etc. At first I only had two 5-minute corrupted files, so I resorted to : 1) extract each frame to PNG (with "ffmpeg -i in_bad_frame_order.MP4 frame%06d.png") 2) create a text file with the frames in the right order (Excel fiddling) 3) recreate a MP4 file from the PNG files (with "ffmpeg -r 30 -f concat -i full_list.txt -c:v libx264 -pix_fmt yuv420p out_no_audio.mp4") 4) extract audio from original (with "ffmpeg -i in_bad_frame_order.MP4 -vn -acodec copy audio.aac" 5) reinject audio into the rebuilt file (with "ffmpeg -i out_no_audio.mp4 -i audio.aac -c:v copy -c:a copy out_fixed.mp4") That worked pretty well and I was able to use the rebuilt video no prob, but it took around 24 hours to process 10 minutes of video (it is 4K30) and PNGs are huge. Now I got back from a trip and discovered that I have around 10-15 hours of video that are corrupt :-(. I threw away the GoPro, but I would like to recover the footage without spending 2-3 months with my PC burning CPU 24/7 just to rebuild the files the same way, so I wondered if I could fiddle with the PTS of the frames to make them play in the right order. I thus came up with a formula and tried to apply it using ffmpeg, with the following command (and output) : ffmpeg -i in_bad_frame_order.MP4 -bsf:v setts=pts='if(eq(mod(PTS,5),0),PTS+6,if(eq(mod(PTS,5),1),PTS+4,if(eq(mod(PTS,5),2),PTS+6,if(eq(mod(PTS,5),3),PTS+6,PTS+3))))' -c copy out.mp4 ffmpeg version 7.0.1-full_build-www.gyan.dev Copyright (c) 2000-2024 the FFmpeg developers built with gcc 13.2.0 (Rev5, Built by MSYS2 project) configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libxevd --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxeve --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-dxva2 --enable-d3d11va --enable-d3d12va --enable-ffnvcodec --enable-libvpl --enable-nvdec --enable-nvenc --enable-vaapi --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint libavutil 59. 8.100 / 59. 8.100 libavcodec 61. 3.100 / 61. 3.100 libavformat 61. 1.100 / 61. 1.100 libavdevice 61. 1.100 / 61. 1.100 libavfilter 10. 1.100 / 10. 1.100 libswscale 8. 1.100 / 8. 1.100 libswresample 5. 1.100 / 5. 1.100 libpostproc 58. 1.100 / 58. 1.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'in_bad_frame_order.MP4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2mp41 encoder : Lavf60.16.100 Duration: 00:00:07.03, start: 0.000000, bitrate: 43392 kb/s Stream #0:0[0x1](eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 3840x2160 [SAR 1:1 DAR 16:9], 46444 kb/s, 29.97 fps, 29.97 tbr, 90k tbn (default) Metadata: handler_name : GoPro H.265 vendor_id : [0][0][0][0] encoder : GoPro H.265 encoder timecode : 16:17:19:08 Side data: displaymatrix: rotation of -180.00 degrees Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default) Metadata: handler_name : GoPro AAC vendor_id : [0][0][0][0] Stream #0:2[0x3](eng): Data: none (tmcd / 0x64636D74), 0 kb/s Metadata: handler_name : GoPro H.265 timecode : 16:17:19:08 Stream mapping: Stream #0:0 -> #0:0 (copy) Stream #0:1 -> #0:1 (copy) Output #0, mp4, to 'out.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2mp41 encoder : Lavf61.1.100 Stream #0:0(eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 3840x2160 [SAR 1:1 DAR 16:9], q=2-31, 46444 kb/s, 29.97 fps, 29.97 tbr, 90k tbn (default) Metadata: handler_name : GoPro H.265 vendor_id : [0][0][0][0] encoder : GoPro H.265 encoder timecode : 16:17:19:08 Side data: displaymatrix: rotation of -180.00 degrees Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default) Metadata: handler_name : GoPro AAC vendor_id : [0][0][0][0] Press [q] to stop, [?] for help [out#0/mp4 @ 0000020e07576a80] video:37078KiB audio:162KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 0.022741% size= 37248KiB time=00:00:06.99 bitrate=43607.6kbits/s speed=8.12x No error is thrown, but when playing back, the file looks exactly the same, as if the PTS were left unchanged. However, with a simpler formula, such as doubling the PTS (ffmpeg -i in_bad_frame_order.MP4 -bsf:v setts=pts='PTS*2' -c copy out.mp4), I can see that the video indeed plays twice as slow, so it seems the ffmpeg syntax is correct but the formula somehow gets ignored. Does anybody have an idea what is wrong ? Or can you advise another way to fix the files ? Thanks for your help, Vincent _______________________________________________ ffmpeg-user mailing list ffmpeg-user@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-user To unsubscribe, visit link above, or email ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe".