Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#7640 closed defect (invalid)

first part of cut out video only contains audio

Reported by: Hans Henrik Bergan Owned by:
Priority: normal Component: undetermined
Version: git-master Keywords:
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the bug: when cutting out 10.8 seconds starting at 00:11:32 from the video at https://www.youtube.com/watch?v=PojTP32lE_o , the first 2 seconds of the cut only contains the audio (video resumes 2 seconds in) - notably, this doesn't happen if omitting "-c:v copy -c:a copy"

How to reproduce:

youtube-dl 'https://www.youtube.com/watch?v=PojTP32lE_o' -o in.mkv -q 2>/dev/null

ffmpeg -i "in.mkv" -c:v copy -c:a copy  -ss 00:11:32 -t 10.8 -y test.mkv


ffmpeg version N-92820-gd702600350 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 8.2.1 (GCC) 20181201
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
  libavutil      56. 25.100 / 56. 25.100
  libavcodec     58. 42.104 / 58. 42.104
  libavformat    58. 25.100 / 58. 25.100
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 46.101 /  7. 46.101
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Input #0, matroska,webm, from 'in.mkv':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    ENCODER         : Lavf58.3.100
  Duration: 00:20:31.64, start: -0.007000, bitrate: 430 kb/s
    Stream #0:0: Video: h264 (Main), yuv420p(progressive), 640x480 [SAR 1:1 DAR 4:3], 29.97 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
    Metadata:
      HANDLER_NAME    : ISO Media file produced by Google Inc. Created on: 11/13/2018.
      DURATION        : 00:20:31.630000000
    Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
    Metadata:
      DURATION        : 00:20:31.641000000
Output #0, matroska, to 'test.mkv':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    encoder         : Lavf58.25.100
    Stream #0:0: Video: h264 (Main) (H264 / 0x34363248), yuv420p(progressive), 640x480 [SAR 1:1 DAR 4:3], q=2-31, 29.97 fps, 29.97 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      HANDLER_NAME    : ISO Media file produced by Google Inc. Created on: 11/13/2018.
      DURATION        : 00:20:31.630000000
    Stream #0:1(eng): Audio: opus ([255][255][255][255] / 0xFFFFFFFF), 48000 Hz, stereo, fltp (default)
    Metadata:
      DURATION        : 00:20:31.641000000
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame=  264 fps=0.0 q=-1.0 Lsize=     257kB time=00:00:10.78 bitrate= 195.3kbits/s speed=57.7x    
video:92kB audio:159kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 2.594684%

the resulting "test.mkv" is missing the first 2 seconds of video. (but not the first 2 seconds of audio)

and per the instructions at https://ffmpeg.org/bugreports.html :

$ ffmpeg -v 9 -loglevel 99 -i in.mkv
ffmpeg version N-92820-gd702600350 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 8.2.1 (GCC) 20181201
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
  libavutil      56. 25.100 / 56. 25.100
  libavcodec     58. 42.104 / 58. 42.104
  libavformat    58. 25.100 / 58. 25.100
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 46.101 /  7. 46.101
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Splitting the commandline.
Reading option '-v' ... matched as option 'v' (set logging level) with argument '9'.
Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument '99'.
Reading option '-i' ... matched as input url with argument 'in.mkv'.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument 9.
Successfully parsed a group of options.
Parsing a group of options: input url in.mkv.
Successfully parsed a group of options.
Opening an input file: in.mkv.
[NULL @ 00000000004d0e40] Opening 'in.mkv' for reading
[file @ 00000000004d1740] Setting default whitelist 'file,crypto'
Probing matroska,webm score:100 size:2048
[matroska,webm @ 00000000004d0e40] Format matroska,webm probed with size=2048 and score=100
st:0 removing common factor 1000000 from timebase
st:1 removing common factor 1000000 from timebase
[matroska,webm @ 00000000004d0e40] Before avformat_find_stream_info() pos: 1047 bytes read:32768 seeks:0 nb_streams:2
[h264 @ 00000000004d6e00] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 00000000004d6e00] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 00000000004d6e00] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 00000000004d6e00] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 00000000004d6e00] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 00000000004d6e00] Format yuv420p chosen by get_format().
[h264 @ 00000000004d6e00] Reinit context to 640x480, pix_fmt: yuv420p
[h264 @ 00000000004d6e00] no picture
[matroska,webm @ 00000000004d0e40] All info found
[matroska,webm @ 00000000004d0e40] stream 0: start_time: 0.000 duration: -9223372036854776.000
[matroska,webm @ 00000000004d0e40] stream 1: start_time: -0.007 duration: -9223372036854776.000
[matroska,webm @ 00000000004d0e40] format: start_time: -0.007 duration: 1231.641 bitrate=430 kb/s
[matroska,webm @ 00000000004d0e40] After avformat_find_stream_info() pos: 15422 bytes read:32768 seeks:0 frames:5
Input #0, matroska,webm, from 'in.mkv':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    ENCODER         : Lavf58.3.100
  Duration: 00:20:31.64, start: -0.007000, bitrate: 430 kb/s
    Stream #0:0, 3, 1/1000: Video: h264 (Main), 1 reference frame, yuv420p(progressive, left), 640x480 [SAR 1:1 DAR 4:3], 0/1, 29.97 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
    Metadata:
      HANDLER_NAME    : ISO Media file produced by Google Inc. Created on: 11/13/2018.
      DURATION        : 00:20:31.630000000
    Stream #0:1(eng), 2, 1/1000: Audio: opus, 48000 Hz, stereo, fltp, delay 312 (default)
    Metadata:
      DURATION        : 00:20:31.641000000
Successfully opened the file.
At least one output file must be specified
[AVIOContext @ 00000000004daa00] Statistics: 32768 bytes read, 0 seeks

Change History (3)

in reply to:  description comment:1 by erikbs, 6 years ago

This happens if you copy a video stream and the first frame in the output video is not a keyframe. Keyframes are the only frames that actually contain a complete picture – the ones in-between are just stored as diffs, since that is more efficient when there are relatively few changes between frames. If you cut a video and the first frame is not a keyframe, then you will have nothing to calculate the intermediate frames from, which is why the video is usually rendered black / random colours until the next keyframe (usually a couple of seconds later).

Replying to hanshenrik:

this doesn't happen if omitting "-c:v copy -c:a copy"

It is because if you do not specify copy, the stream will be re-encoded and in the process ffmpeg will have access to the entire data stream. A new keyframe will be written as the first frame in the output stream. With copy, ffmpeg will just raw copy the stream from the specified timecode, even if you need earlier parts of the stream to play it correctly (in this case the keyframe used to calculate the first few frames).

There is no way to cut the video between keyframes without either experiencing this or re-encoding the stream. Thus you have two options:

  1. Re-encode the video (you can still do -c:a copy, the audio can usually be cut at any time)
  2. Cut the video a little earlier or later, so that a keyframe is the first one. I do not know how that is done efficiently with ffmpeg (i.e. without trial and error), but it is easy to do it with the GUI tool Avidemux, which has buttons for skipping to the next/prev keyframe (just remember to set the correct container format, it seems to default to AVI). End points need not be keyframes.

If you want to avoid re-encoding the entire clip, you can also combine the solutions: re-encode the first two seconds from your desired cutting point until the first keyframe and cut the video losslessly from the first keyframe, then concatenate the two clips.

comment:2 by Carl Eugen Hoyos, 6 years ago

Resolution: invalid
Status: newclosed

comment:3 by Hans Henrik Bergan, 6 years ago

i see, thank you for the explanation,

edit: see ticket #7644

still, could a stderr warning be implemented for using "-c:v copy" + "-ss non-key-frame" ?
that may save people debugging time + prevent stuff like this from being added to the tracker in the future (for example, it would have prevented this ticket from being created)

Last edited 6 years ago by Hans Henrik Bergan (previous) (diff)
Note: See TracTickets for help on using tickets.