How to concatenate two MP4 files using FFmpeg?

后端 未结 22 3043
遇见更好的自我
遇见更好的自我 2020-11-22 02:32

I\'m trying to concatenate two mp4 files using ffmpeg. I need this to be an automatic process hence why I chose ffmpeg. I\'m converting the two files into .ts files and th

相关标签:
22条回答
  • 2020-11-22 03:17
    ffmpeg \
      -i input_1.mp4 \
      -i input_2.mp4 \
      -filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]' \
      -map [vid] \
      -c:v libx264 \
      -crf 23 \
      -preset veryfast \
      output.mp4
    
    0 讨论(0)
  • 2020-11-22 03:17

    The concat protocol described here; https://trac.ffmpeg.org/wiki/Concatenate#protocol

    When implemented using named pipes to avoid intermediate files

    Is very fast (read: instant), has no frames dropped, and works well.

    Remember to delete the named pipe files and remember to check if the video is H264 and AAC which you can do with just ffmpeg -i filename.mp4 (check for h264 and aac mentions)

    0 讨论(0)
  • 2020-11-22 03:18

    From the documentation here: https://trac.ffmpeg.org/wiki/Concatenate

    If you have MP4 files, these could be losslessly concatenated by first transcoding them to MPEG-2 transport streams. With H.264 video and AAC audio, the following can be used:

    ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
    ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
    ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
    

    This approach works on all platforms.

    I needed the ability to encapsulate this in a cross platform script, so I used fluent-ffmpeg and came up with the following solution:

    const unlink = path =>
      new Promise((resolve, reject) =>
        fs.unlink(path, err => (err ? reject(err) : resolve()))
      )
    
    const createIntermediate = file =>
      new Promise((resolve, reject) => {
        const out = `${Math.random()
          .toString(13)
          .slice(2)}.ts`
    
        ffmpeg(file)
          .outputOptions('-c', 'copy', '-bsf:v', 'h264_mp4toannexb', '-f', 'mpegts')
          .output(out)
          .on('end', () => resolve(out))
          .on('error', reject)
          .run()
      })
    
    const concat = async (files, output) => {
      const names = await Promise.all(files.map(createIntermediate))
      const namesString = names.join('|')
    
      await new Promise((resolve, reject) =>
        ffmpeg(`concat:${namesString}`)
          .outputOptions('-c', 'copy', '-bsf:a', 'aac_adtstoasc')
          .output(output)
          .on('end', resolve)
          .on('error', reject)
          .run()
      )
    
      names.map(unlink)
    }
    
    concat(['file1.mp4', 'file2.mp4', 'file3.mp4'], 'output.mp4').then(() =>
      console.log('done!')
    )
    
    0 讨论(0)
  • 2020-11-22 03:19

    Here is a script (works for an arbitrary number of specified files (not just all in the working directory), without additional files, also works for .mov; tested on macOS):

    #!/bin/bash
    
    if [ $# -lt 1 ]; then
        echo "Usage: `basename $0` input_1.mp4 input_2.mp4 ... output.mp4"
        exit 0
    fi
    
    ARGS=("$@") # determine all arguments
    output=${ARGS[${#ARGS[@]}-1]} # get the last argument (output file)
    unset ARGS[${#ARGS[@]}-1] # drop it from the array
    (for f in "${ARGS[@]}"; do echo "file '$f'"; done) | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy $output
    
    0 讨论(0)
  • 2020-11-22 03:20

    Detailed documentation on various ways of concatenation in ffmpeg can be found here.

    You can use 'Concat filter' for quick concatenation.

    It performs a re-encode. This option is best when inputs have different video/audio formats.

    For Concatenating 2 files:

    ffmpeg -i input1.mp4 -i input2.webm \
    -filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]" \
    -map "[v]" -map "[a]" output.mp4
    

    For Concatenating 3 files:

    ffmpeg -i input1.mp4 -i input2.webm -i input3.mp4 \
    -filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] [2:v:0] [2:a:0] concat=n=3:v=1:a=1 [v] [a]" \
    -map "[v]" -map "[a]" output.mp4
    

    This works for same as well as multiple input file types.

    0 讨论(0)
  • 2020-11-22 03:21

    Merging all mp4 files from current directory

    I personnaly like not creating external file that I have to delete afterwards, so my solution was following which includes files numbering listing (like file_1_name, file_2_name, file_10_name, file_20_name, file_100_name, ...)

    #!/bin/bash
    filesList=""
    for file in $(ls -1v *.mp4);do #lists even numbered file
        filesList="${filesList}${file}|"
    done
    filesList=${filesList%?} # removes trailing pipe
    ffmpeg -i "concat:$filesList" -c copy $(date +%Y%m%d_%H%M%S)_merged.mp4
    
    0 讨论(0)
提交回复
热议问题