Avoid ffmpeg re encode using complex filter

5,074

Filtering requires re-encoding, but you have another option:

1. Make each segment

What you can do instead is stream copy each segment using -ss and -t or -to with -c copy.

  • Example to skip first 10 seconds and make 20 second output:

    ffmpeg -ss 10 -i input -t 20 -c copy output
    
  • Example to skip first 10 seconds and stop at duration 30 resulting in a 20 second output:

    ffmpeg -i input -ss 10 -to 30 -c copy output
    

2. Concatenate

  1. First, read the concat demuxer documentation.

  2. Then, make a list file:

    $ cat inputs.txt
    file '/path/to/segment00.mp4'
    file '/path/to/segment01.mp4'
    file '/path/to/segment02.mp4'
    file '/path/to/segment03.mp4'
    
  3. Finally, you can concatenate:

    ffmpeg -f concat -i inputs.txt -c copy output
    

Also see

Share:
5,074

Related videos on Youtube

AbrahamSustaita
Author by

AbrahamSustaita

Updated on September 18, 2022

Comments

  • AbrahamSustaita
    AbrahamSustaita almost 2 years

    I have a list of ts files that will be concatenated to being trim later and encode it in mp4.

    All of it is working ok... however the problem I have right now is the file is re-encoded... and that is not what I want, since the ts is already h264 and mp3, so just packing it in mp4 works ok. Actually, this works:

    ffmpeg -i file.ts -c copy file.mp4
    

    But this is not:

    ffmpeg -i videohls-1935m-index.ts -y -filter_complex \
    [0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
    [0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
    [0:v]trim=30:90,setpts=PTS-STARTPTS[v1]; \
    [0:a]atrim=30:90,asetpts=PTS-STARTPTS[a1]; \
    [0:v]trim=100:200,setpts=PTS-STARTPTS[v2]; \
    [0:a]atrim=100:200,asetpts=PTS-STARTPTS[a2]; \
    [0:v]trim=250:350,setpts=PTS-STARTPTS[v3]; \
    [0:a]atrim=250:350,asetpts=PTS-STARTPTS[a3]; \
    [v0][a0][v1][a1][v2][a2][v3][a3]concat=n=4:v=1:a=1[out] \
    -map [out] \
    -c copy \
    videohls-1935m-index.mp4
    

    Obviously it will not "copy" the codecs because the output comes from a virtual exit that is mapped to [out] (or something like that... honestly I don't know exactly how it works, but I know is like that), so it does not have a "codec" per say... so it cannot copy it.

    This means I have 2 problems:

    1. The file is tinier, which is not bad at all, but...
    2. The file is re encoded... so the quality is less also.

    How can I avoid this to keep the quality of the video?

    • SirDarius
      SirDarius over 9 years
      Video filters work on raw uncompressed frames, meaning they need to be decoded prior to being processed by a filter, and subsequently encoded. Using the "copy" codec actually disables filters for this stream, see ffmpeg.org/ffmpeg-all.html#Stream-copy.
    • AbrahamSustaita
      AbrahamSustaita over 9 years
      Thanks a lot for your quick reply... Question: then there is no any way for me to do this faster? I want to keep it simple and fast. So I can do it maybe by first creating the files and then concatenate them. Do you think that will be better than this way?
    • Elisa Cha Cha
      Elisa Cha Cha over 9 years
      Just a reminder that if you have additional ffmpeg cli usage questions they should be asked at Super User instead. Stack Overflow is specifically for programming questions only. It would be best if this question got migrated.
    • AbrahamSustaita
      AbrahamSustaita over 9 years
      How can I migrate it?
  • slhck
    slhck over 9 years
    You could also use the segment muxer to generate the segments.
  • AbrahamSustaita
    AbrahamSustaita over 9 years
    Could you add it as an answer?