accurate cutting of video (+ audio) with ffmpeg

10

7

I want my website to allow users to accurately create their own clips from a source video I provide.

I have a source video file that I first want to convert to something suitable for a website:

Input #0, matroska,webm, from 'source.mkv': 
Duration: 00:28:18.57, start: 0.000000, bitrate: 10183 kb/s 
Stream #0:0: Video: h264 (Constrained Baseline), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 48 tbc (default)
Stream #0:1: Audio: mp3, 44100 Hz, stereo, s16, 128 kb/s (default)

I use ffmpeg to convert it like so:

ffmpeg -i source.mkv -c:v libx264 -c:a aac -strict experimental -vf scale="960:-1" source.mp4

Watching this video back it is good enough quality and small enough file size for my needs, and loads/plays on my website.

I have a webpage that lets users select a start and endpoint on this video - and create a clip. Here's an example of the ffmpeg command that I use for that:

-ss 577.920 -i source.mp4 -t 011.980 -codec:v copy -codec:a copy -vf scale="960:-1" clip1.mp4

The problem is the clip is not always time-accurate enough. Usually the audio is accurate enough but the video stops half a second early or something.

Is there any way to make this accurate and in-sync to say, 0.2 of a second?

EDIT: Adding -force_key_frames 00:00:00.2 didn't help.

EDIT: I changed the clipping to use -c:v libx264 -c:a aac -strict experimental instead of -codec:v copy -codec:a copy with good (ish) results.

The file can play externally without issue - but when I load it into my html5 video element and play it - the last part of the video (audio is fine) freezes. The last part that freezes is less than a second long.

Should I try it with another video encoder? What is the best alternative for libx264? Bearing in mind I will probably want this to be on a public website.

But hang on doesn't the fact that it plays accurately without issue with a player like MPC or Windows Media Player suggest that it is a problem with either Google Chrome or the HTML video element? Or am I using an unsupported encoding or something?

Pete Oakey

Posted 2012-11-03T19:56:30.830

Reputation: 194

This might have to do with the timing of key frames. In any case, this should be moved to SuperUser.com. – Brad – 2012-11-03T19:58:47.867

Hi, ffmpeg can't cut the video at any point, it only can cut on keyframes; for this reason audio is almost precise, while video isn't. – None – 2012-11-03T19:59:53.657

Can I move it myself? I will try adding key frames to the source file with -force_key_frames 00:00:00.2 – Pete Oakey – 2012-11-03T20:11:27.453

Answers

9

The behavior of -ss changes depending if it used as an input or output option, and is often slower but can be more accurate when used as an output option. See the answer to ffmpeg converts video from specified time period slowly for more details and examples.

To change output quality for source.mp4 use the -crf option with a value between 18-28 (23 is default). See the CRF section of the FFmpeg and x264 Encoding Guide for examples.

Your trimming command can be simplified:

ffmpeg -ss 577.92 -i source.mp4 -ss 0 -t 11.98 -c copy -map 0 clip1.mp4

I replaced -codec:v copy -codec:a copy with -c copy -map 0. This will copy all streams instead of just the first video and audio streams--although the input only has two streams due to your previous command. Since you can not scale without re-encoding, therefore being mutually exclusive with -codec:v copy, and since your input is already scaled to the set size I removed the filter options.

If it is still not accurate enough then try:

ffmpeg -i source.mp4 -ss 577.92 -t 11.98 -c copy -map 0 clip1.mp4

It will be slower, but probably more accurate. See the links in the answer in the first link I provided for a description of the differences of these two examples.

Lastly, you should run source.mp4 through qt-faststart (located in the tools directory in ffmpeg source), or use the -movflags faststart option. This will relocate some data to the beginning of the file so it can begin playback before it is completely downloaded.

llogan

Posted 2012-11-03T19:56:30.830

Reputation: 31 929

2Using -ss as output option instead of input option fixed my problem: the first video frame was around 1s in the output video, with only audio before that (also confirmed by ffprobe -show_frames). Moving -ss after -i made it output audio and video frames starting at frame 0. – CodeManX – 2018-05-03T09:13:15.323

+1 for the tips but I tried ffmpeg -i source.mp4 -ss 577.92 -t 011.980 -c copy -map 0 clip1.mp4 but the first part (almost a second) and last part (maybe quarter of a second) of the video is missed, audio is fine though. – Pete Oakey – 2012-11-03T22:13:48.987

@PeteOakey Have you tried cutting without bitstream copy, but actual re-encoding? – slhck – 2012-11-07T08:06:12.857

Tried it without bitstream copy - results appended to my question. – Pete Oakey – 2012-11-08T21:15:00.297