The only Linux command-line tool I've found so-far, that can cut at exact frame (or, with frame accuracy), is melt
(sudo apt-get install melt
).
Say you have an inputvid.mp4
- first check its encoding settings with say ffmpeg
(here, I just say I want to encode it again to -f mp4
, but as the file /dev/null
so the output is discarded; I redirect stderr so I can grep through it - note in the middle, the command prompts, and you should answer y
with ENTER, so the process proceeds and dumps the useful info; this is with ffmpeg 3.3.3 on Ubuntu 14):
ffmpeg -i inputvid.mp4 -f mp4 /dev/null 2>&1 | grep 'Stream\|encoder'
Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709), 640x360 [SAR 1:1 DAR 16:9], 389 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 95 kb/s (default)
y
File '/dev/null' already exists. Overwrite ? [y/N] Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (aac (native) -> aac (native))
encoder : Lavf57.71.100
Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p(progressive), 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
encoder : Lavc57.89.100 libx264
Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 128 kb/s (default)
encoder : Lavc57.89.100 aac
Ok, so we can see ffmpeg
chooses libx264
and aac
encoders for this video; then we can enter this in for melt
:
melt inputvid.mp4 in=7235 out=7349 -consumer avformat:cut.mp4 acodec=aac vcodec=libx264
.... and melt
will cut with the piece between frames 7235 and 7349 into a new file, cut.mp4
. Then to check if cut.mp4
loops correctly, use melt
again to play it back twice - and play it to an SDL window:
melt cut.mp4 cut.mp4 -consumer sdl
... and here is what ffmpeg
sees for this file:
ffmpeg -i cut.mp4 -f mp4 /dev/null 2>&1 | grep 'Stream\|encoder' encoder : Lavf54.20.4
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x360 [SAR 1:1 DAR 16:9], 526 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 182 kb/s (default)
y
File '/dev/null' already exists. Overwrite ? [y/N] Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (aac (native) -> aac (native))
encoder : Lavf57.71.100
Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
encoder : Lavc57.89.100 libx264
Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 48000 Hz, stereo, fltp, 128 kb/s (default)
encoder : Lavc57.89.100 aac
The video encoding settings for cut.mp4
seem to be identical to inputvid.mp4
except video bitrate changed from 389 kb/s to 526 kb/s, and also the audio encoding settings are nearly the same, except the sampling rate changed from 44100 to 48000 Hz; though that can be regulated with:
melt inputvid.mp4 in=7235 out=7349 -consumer avformat:cut.mp4 acodec=aac ar=44100 ab=95k vcodec=libx264 vb=389k
... however, even with this, the final video bitrate for me ends up 337 kb/s. Still, the cuts loop fine (and that includes audio) when played in a loop, so I guess this is indeed frame-accurate...
related- https://superuser.com/questions/1287650/ffmpeg-is-not-even-cutting-this-and-other-mp4s-to-the-nearest-second
– barlop – 2019-04-27T11:12:45.430You'll probably have to reencode before cutting to get it right. You could probably speed things up by first cutting out the surrounding keyframes and only reencode the snippets. – Nifle – 2012-08-07T18:19:31.320
4Which FFmpeg command have you tried, exactly? I believe if you decode the video before (i.e. place the
-ss
parameter after-i
), it should be more accurate. – slhck – 2012-08-07T18:19:33.7971The FFmpeg trick worked! I didn't realize the order mattered so much. Is this the same for any of the other tools? – curmil – 2012-08-07T19:30:48.203