Using ffmpeg to split mkv but get a few seconds video lost (cutting between keyframes without re-encoding?)
I am using ffmpeg (the real one from FFmpeg, not the fake one from Libav) to split some mkv files:
ffmpeg -i input.mkv -ss 00:01:00 -to 00:02:00 -codec copy output.mkv
However, when I open the output.mkv with VLC, the first few seconds has no video, but only audio. And seconds later I can see both video and audio. The interesting part is, when I try different timestamps after -ss parameter, the duration of "audio only" part varies from 1 second to 4 seconds or even more.
I try to use mkvmerge
with --split "timecodes:00:01:00,00:02:00"
, and the output file works fine, with no "audio only" part at the beginning.
I tried different mkv container with different video/audio encoding in them, but the results are same.
I think I am missing some options with ffmpeg. What should I add to ffmpeg command-line to avoid the several seconds of "audio only" part?
Update 1
Here is the complete output:
$ ffmpeg -i 21.mkv -ss 00:00:58 -to 00:02:00 -codec copy clip.mkv ffmpeg version 2.2.2 Copyright (c) 2000-2014 the FFmpeg developers built on May 7 2014 13:08:45 with gcc 4.8.2 (GCC) 20140206 (prerelease) configuration: --prefix=/usr --disable-debug --disable-static --enable-avresample --enable-dxva2 --enable-fontconfig --enable-gnutls --enable-gpl --enable-libass --enable-libbluray --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libv4l2 --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-pic --enable-postproc --enable-runtime-cpudetect --enable-shared --enable-swresample --enable-vdpau --enable-version3 --enable-x11grab libavutil 52. 66.100 / 52. 66.100 libavcodec 55. 52.102 / 55. 52.102 libavformat 55. 33.100 / 55. 33.100 libavdevice 55. 10.100 / 55. 10.100 libavfilter 4. 2.100 / 4. 2.100 libavresample 1. 2. 0 / 1. 2. 0 libswscale 2. 5.102 / 2. 5.102 libswresample 0. 18.100 / 0. 18.100 libpostproc 52. 3.100 / 52. 3.100 Input #0, matroska,webm, from '21.mkv': Metadata: encoder : libebml v1.3.0 + libmatroska v1.4.0 creation_time : 2014-05-07 01:47:41 Duration: 00:42:50.78, start: 0.000000, bitrate: 2833 kb/s Stream #0:0(eng): Video: h264 (High), yuv420p(tv, bt709), 1280x720, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default) Stream #0:1: Audio: ac3, 48000 Hz, 5.1(side), fltp, 384 kb/s (default) Output #0, matroska, to 'clip.mkv': Metadata: encoder : Lavf55.33.100 Stream #0:0(eng): Video: h264 (H264 / 0x34363248), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 23.98 fps, 1k tbn, 1k tbc (default) Stream #0:1: Audio: ac3 ([0] [0][0] / 0x2000), 48000 Hz, 5.1(side), 384 kb/s (default) Stream mapping: Stream #0:0 -> #0:0 (copy) Stream #0:1 -> #0:1 (copy) Press [q] to stop, [?] for help frame= 1414 fps=0.0 q=-1.0 Lsize= 18275kB time=00:01:02.00 bitrate=2414.6kbits/s video:15344kB audio:2906kB subtitle:0 data:0 global headers:0kB muxing overhead 0.134916%
Update 2
There may be something to do with "keyframe" stuff, and letting ffmpeg re-encode the video stream will not lead to the few seconds of blank video. However, since mkvmerge can cut the same file between keyframes without re-encoding, I am wondering if there is a way to make ffmpeg do the same work. For example, somewhat "re-define" the keyframe, et cetra.
Solution 1:
In order to cut in between keyframes (or GOP's, as they are called), you need to re-encode the video. (the same is true for audio, but there the "frames" are much smaller, usually 1024 samples).
In your case, you could change -codec copy
to -acodec copy -vcodec webm
to have ffmpeg re-encode your stream. This will obviously take longer, and you will lose quality (if you do it right, this loss will not be noticeable, but there will be some).