ffmpeg:合并/合并多个mp4视频不起作用,输出只包含第一个视频

时间:2011-03-24 05:06:18

标签: ffmpeg

以下是我用来组合多个视频的命令:

ffmpeg -i 75_540_38HQ2.mp4 -i 76_70_20.mp4 -i 76_173_80.mp4 -i 81_186_35.mp4 -vcodec copy -acodec copy Mux1.mp4

生成的Mux1.mp4不包含所有视频。只有第一个视频(75_540_38HQ2.mp4)。源和结果视频的文件大小在下面(如您所见,生成的视频略大于第一个视频):

$ ls -lh
-rw-r--r-- 1 dbaker dbaker  42M 2011-03-24 11:59 75_540_38HQ2.mp4
-rw-r--r-- 1 dbaker dbaker 236M 2011-03-24 12:09 76_173_80.mp4
-rw-r--r-- 1 dbaker dbaker  26M 2011-03-24 12:05 76_70_20.mp4
-rw-r--r-- 1 dbaker dbaker  54M 2011-03-24 12:15 81_186_35.mp4
-rw-r--r-- 1 dbaker dbaker  44M 2011-03-24 14:48 Mux1.mp4

这是ffmpeg命令的输出。对我而言看起来没问题,显示了多个源输入和单个输出。

FFmpeg version SVN-r26402, Copyright (c) 2000-2011 the FFmpeg developers
  built on Mar 21 2011 18:05:32 with gcc 4.4.5
  configuration: --enable-gpl --enable-version3 --enable-nonfree --enable-postproc --enable-libfaac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxvid --enable-x11grab
  libavutil     50.36. 0 / 50.36. 0
  libavcore      0.16. 1 /  0.16. 1
  libavcodec    52.108. 0 / 52.108. 0
  libavformat   52.93. 0 / 52.93. 0
  libavdevice   52. 2. 3 / 52. 2. 3
  libavfilter    1.74. 0 /  1.74. 0
  libswscale     0.12. 0 /  0.12. 0
  libpostproc   51. 2. 0 / 51. 2. 0
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '75_540_38HQ2.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    creation_time   : 1970-01-01 00:00:00
    encoder         : Lavf52.93.0
  Duration: 00:00:29.99, start: 0.000000, bitrate: 11517 kb/s
    Stream #0.0(eng): Video: h264, yuv420p, 1280x960 [PAR 1:1 DAR 4:3], 11575 kb/s, 29.94 fps, 29.97 tbr, 30k tbn, 59.94 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
    Stream #0.1(eng): Audio: aac, 48000 Hz, stereo, s16, 127 kb/s
    Metadata:
      creation_time   : 1970-01-01 00:00:00
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from '76_70_20.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    creation_time   : 1970-01-01 00:00:00
    encoder         : Lavf52.93.0
  Duration: 00:00:19.98, start: 0.000000, bitrate: 10901 kb/s
    Stream #1.0(eng): Video: h264, yuv420p, 1280x960 [PAR 1:1 DAR 4:3], 10804 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
    Stream #1.1(eng): Audio: aac, 48000 Hz, stereo, s16, 128 kb/s
    Metadata:
      creation_time   : 1970-01-01 00:00:00
Input #2, mov,mp4,m4a,3gp,3g2,mj2, from '76_173_80.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    creation_time   : 1970-01-01 00:00:00
    encoder         : Lavf52.93.0
  Duration: 00:03:09.99, start: 0.000000, bitrate: 10393 kb/s
    Stream #2.0(eng): Video: h264, yuv420p, 1280x960 [PAR 1:1 DAR 4:3], 10321 kb/s, 29.96 fps, 29.97 tbr, 30k tbn, 59.94 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
    Stream #2.1(eng): Audio: aac, 48000 Hz, stereo, s16, 128 kb/s
    Metadata:
      creation_time   : 1970-01-01 00:00:00

Seems stream 0 codec frame rate differs from container frame rate: 119.88 (120000/1001) -> 30000.00 (30000/1)
Input #3, mov,mp4,m4a,3gp,3g2,mj2, from '81_186_35.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    creation_time   : 1970-01-01 00:00:00
    encoder         : Lavf52.93.0
  Duration: 00:00:35.00, start: 0.000000, bitrate: 12700 kb/s
    Stream #3.0(eng): Video: h264, yuv420p, 1280x720 [PAR 1:1 DAR 16:9], 12620 kb/s, 59.91 fps, 30k tbr, 60k tbn, 119.88 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
    Stream #3.1(eng): Audio: aac, 48000 Hz, stereo, s16, 128 kb/s
    Metadata:
      creation_time   : 1970-01-01 00:00:00
Output #0, mp4, to 'Mux1.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    creation_time   : 1970-01-01 00:00:00
    encoder         : Lavf52.93.0
    Stream #0.0(eng): Video: libx264, yuv420p, 1280x960 [PAR 1:1 DAR 4:3], q=2-31, 11575 kb/s, 30k tbn, 29.97 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
    Stream #0.1(eng): Audio: libfaac, 48000 Hz, stereo, 128 kb/s
    Metadata:
      creation_time   : 1970-01-01 00:00:00
Stream mapping:
  Stream #0.0 -> #0.0
  Stream #2.1 -> #0.1
Press [q] to stop encoding
frame=  883 fps=632 q=-1.0 Lsize=   44730kB time=29.40 bitrate=12465.1kbits/s    
video:41678kB audio:2969kB global headers:0kB muxing overhead 0.184548%

我在做一些令人眼花缭乱的蠢事吗?

源视频来自摄像机,是使用ffmpeg -i bigfile.mp4 -ss 20 -t 10 -vcodec copy etc..

拍摄的小片段

谢谢堆! 戴夫


编辑:无法解决,所以我只使用avidemux GUI工具。它似乎附加了MP4就好了。

一定是MP4的问题,或者只是gopro相机的问题。

11 个答案:

答案 0 :(得分:18)

假设您要连接影片,可以使用以下命令:

ffmpeg -f concat -i inputs.txt -vcodec copy -acodec copy Mux1.mp4

在inputs.txt中使用以下文本:

file 75_540_38HQ2.mp4 
file 76_70_20.mp4 
file 76_173_80.mp4
file 81_186_35.mp4

注意:某些发行版(如Ubuntu)在其存储库中没有ffmpeg,而是将ffmpeg定义为avconv的别名。这对avconv不起作用,所以在这种情况下你必须自己编译ffmpeg。您可以通过运行ffmpeg并检查第一个输出行是否以“FFmpeg开发人员”结尾来检查您是否拥有真正的ffmpeg。

答案 1 :(得分:13)

忘了FFmpeg,改用MP4Box,它简单快捷:

    mp4box -add video1.mp4 -cat video2.mp4 -cat video3.mp4 output.mp4

适用于Windows,Linux和OS X: http://www.videohelp.com/tools/mp4box

如果你在Windows上,你可以使用YAMB,它是MP4Box的GUI,效果很好: http://www.videohelp.com/tools/YAMB

2016年6月更新: FFmpeg添加了一个串联过滤器,更多信息在这里: https://stackoverflow.com/a/11175851/218418

答案 2 :(得分:7)

从ffmpeg手册页“示例”部分:

您可以在输出中放置许多相同类型的流:

ffmpeg -i test1.avi -i test2.avi -vcodec copy -acodec copy \ -vcodec copy -acodec copy test12.avi -newvideo -newaudio

除了第一个视频和音频流之外,还有结果    输出文件test12.avi将包含第二个视频和第二个视频    在输入流列表中找到的音频流。

必须在要添加它们的输出文件的名称后面立即指定“-newvideo”,“ - newaudio”和“-newsubtitle”选项。

如果您想要连接它们,FAQ有说明。

我不确定这个问题/答案是否属于SuperUser

答案 3 :(得分:5)

如果所有输入视频具有相同的编解码器,并且您希望输出视频也在同一编解码器中,则简单的concat适用于mp4和mkv文件。 https://trac.ffmpeg.org/wiki/Concatenate
你需要创建一个像

这样的文本文件
# this is a comment
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

然后使用命令

ffmpeg -f concat -i mylist.txt -c copy output.mp4

我使用了同一参考页面中的示例,它运行得很好。唯一的问题是视频未正确捕获。它可能会引入音频视频同步问题,因为它只是将PTS和DTS信息从源视频复制到目标视频。
要获得完整的校对解决方案,您需要逐个数据包地读取视频 然后将所有数据包放在一个视频中,并进行自定义优化,例如丢弃重复的PTS数据包并保持单调的PTS值。

答案 4 :(得分:4)

您必须将它们转换为易于连接的MPEG格式。下面是我使用的脚本,并为我的GoPro视频调用“ffcat”。它基本上运行了几个“ffmpeg -i”命令,这些命令产生可连接的MPEG,它通过管道输出到ffmpeg命令,然后将它们转换为H.264 mp4文件。

它还会将视频大小调整为720p,但您可能不希望这样。

“h264options”是我最近在互联网上h264.code-shop.com

找到的标志

希望这有帮助, 里德


cmd="( "

h264options="-vcodec libx264 -b 512k -flags +loop+mv4 -cmp 256 \
 -partitions +parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 \
 -me_method hex -subq 7 -trellis 1 -refs 5 -bf 3 \
 -flags2 +bpyramid+wpred+mixed_refs+dct8x8 -coder 1 -me_range 16 \
   -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10\
 -qmax 51 -qdiff 4"

outfile="out-`date +%F-%H%M.%S`.mp4"

for i; do
    cmd="${cmd}ffmpeg -i $i -ab 256000 -vb 10000000 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -f mpeg -; "
done
cmd="${cmd} ) | ffmpeg -y -i - -threads 8 ${h264options} -vb 10000000 -acodec libfaac -ar 44100 -ab 128k -s 1280x720 ${outfile}"
echo "${cmd}"
eval ${cmd}

答案 5 :(得分:3)

我一直非常成功地使用这个脚本。结果很完美,因为它使用的是原始视频。

http://trac.ffmpeg.org/wiki/How%20to%20concatenate%20%28join,%20merge%29%20media%20files

确保编辑EXTRA OPTIONS字符串。

#!/bin/bash

################################################################################
#
# Script name: MultiMedia Concat Script (mmcat)
# Author: burek (burek021@gmail.com)
# License: GNU/GPL, see http://www.gnu.org/copyleft/gpl.html
# Date: 2012-07-14
#
# This script concatenates (joins, merges) several audio/video inputs into one
# final output (just like as if all the inputs were played in a playlist, one
# after another).
#
# All input files must have at least one audio and at least one video stream.
# If not, you can easily add audio silence, using FFmpeg. Just search the
# internet for "ffmpeg add silence".
#
# The script makes use of FFmpeg tool (www.ffmpeg.org) and is free for use under
# the GPL license. The inspiration for this script came from this FAQ item:
# http://ffmpeg.org/faq.html#How-can-I-join-video-files_003f
#
# If you find any bugs, please send me an e-mail so I can fix it.
#
################################################################################
#
# General syntax: mmcat <input1> <input2> <input3> ... <output>
#
# For example: mmcat file1.flv file2.flv output.flv
# would create "output.flv" out of "file1.flv" and "file2.flv".
#
################################################################################

# change this to what you need !!!
EXTRA_OPTIONS='-vcodec libx264 -crf 23 -preset medium -acodec aac -strict experimental -ac 2 -ar 44100 -ab 128k'

################################################################################
#
# NO NEED TO TOUCH ANYTHING AFTER THIS LINE!
#
################################################################################

# the version of the script
VERSION=1.3

# location of temp folder
TMP=/tmp

################################################################################

echo "MultiMedia Concat Script v$VERSION (mmcat) - A script to concatenate multiple multimedia files."
echo "Based on FFmpeg - www.ffmpeg.org"
echo "Don't forget to edit this script and change EXTRA_OPTIONS"
echo ""

################################################################################
# syntax check (has to have at least 3 params: infile1, infile2, outfile
################################################################################
if [ -z $3 ]; then
    echo "Syntax: $0 <input1> <input2> <input3> ... <output>"
    exit 1
fi

################################################################################
# get all the command line parameters, except for the last one, which is output
################################################################################
# $first  - first parameter
# $last   - last parameter (output file)
# $inputs - all the inputs, except the first input, because 1st input is
#           handled separately
################################################################################
first=${@:1:1}
last=${@:$#:1}
len=$(($#-2))
inputs=${@:2:$len}

# remove all previous tmp fifos (if exist)
rm -f $TMP/mcs_*

################################################################################
# decode first input differently, because the video header does not have to be
# kept for each video input, only the header from the first video is needed
################################################################################
mkfifo $TMP/mcs_a1 $TMP/mcs_v1

ffmpeg -y -i $first -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a1 2>/dev/null </dev/null &
ffmpeg -y -i $first -an -f yuv4mpegpipe -vcodec rawvideo $TMP/mcs_v1 2>/dev/null </dev/null &

# if you need to log the output of decoding processes (usually not necessary)
# then replace the "2>/dev/null" in 2 lines above with your log file names, like this:
#ffmpeg -y -i $first -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a1 2>$TMP/log.a.1 </dev/null &
#ffmpeg -y -i $first -an -f yuv4mpegpipe -vcodec rawvideo $TMP/mcs_v1 2>$TMP/log.v.1 </dev/null &

################################################################################
# decode all the other inputs, remove first line of video (header) with tail
# $all_a and $all_v are lists of all a/v fifos, to be used by "cat" later on
################################################################################
all_a=$TMP/mcs_a1
all_v=$TMP/mcs_v1
i=2
for f in $inputs
do
    mkfifo $TMP/mcs_a$i $TMP/mcs_v$i

    ffmpeg -y -i $f -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a$i 2>/dev/null </dev/null &
    { ffmpeg -y -i $f -an -f yuv4mpegpipe -vcodec rawvideo - 2>/dev/null </dev/null | tail -n +2 > $TMP/mcs_v$i ; } &

    # if you need to log the output of decoding processes (usually not necessary)
    # then replace the "2>/dev/null" in 2 lines above with your log file names, like this:
    #ffmpeg -y -i $f -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a$i 2>$TMP/log.a.$i </dev/null &
    #{ ffmpeg -y -i $f -an -f yuv4mpegpipe -vcodec rawvideo - 2>$TMP/log.v.$i </dev/null | tail -n +2 > $TMP/mcs_v$i ; } &

    all_a="$all_a $TMP/mcs_a$i"
    all_v="$all_v $TMP/mcs_v$i"
    let i++
done

################################################################################
# concatenate all raw audio/video inputs into one audio/video
################################################################################
mkfifo $TMP/mcs_a_all
mkfifo $TMP/mcs_v_all
cat $all_a > $TMP/mcs_a_all &
cat $all_v > $TMP/mcs_v_all &

################################################################################
# finally, encode the raw concatenated audio/video into something useful
################################################################################
ffmpeg -f u16le -acodec pcm_s16le -ac 2 -ar 44100 -i $TMP/mcs_a_all \
       -f yuv4mpegpipe -vcodec rawvideo -i $TMP/mcs_v_all \
    $EXTRA_OPTIONS \
    $last

################################################################################
# remove all fifos
################################################################################
rm -f $TMP/mcs_*

答案 6 :(得分:3)

Concat demuxer

concat demuxer被添加到ffmpeg 1.1中。如果你的ffmpeg版本是旧的,从这里获取最新的静态二进制文件: http://www.ffmpeg.org/download.html

说明

创建一个文件mylist.txt,其中包含您希望以下列形式连接的所有文件(忽略以破折号开头的行):

# this is a comment
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

请注意,这些可以是相对路径或绝对路径。然后,您可以使用以下代码对文件进行编码:

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

可以使用bash for循环或使用printf生成此列表文件。以下任一项都会生成一个列表文件,其中包含工作目录中的每个* .wav:

for f in ./*.wav; do echo "file '$f'" >> mylist.txt; done
printf "file '%s'\n" ./*.wav > mylist.txt

来源:ffmpeg wiki

答案 7 :(得分:1)

最初的问题更多是关于在一个输出文件中混合多个视频流,并让应用程序选择要解码的视频流。正如上面评论中提到的,您可以使用 FFmpeg 提供的 -map 选项来完成。

以下是从单独的输入文件中混合 3 个视频流的快速示例命令:

ffmpeg  -i video_A.mp4  -i video_B.mp4 -i video_C.mp4 -c copy \
   -map 0:0 -map 1:0 -map 2:0 -map 2:1  output_mux_video.mp4
  • 每个 -map 选项都以特定的值格式 <INPUT_INDEX>:<STREAM_INDEX> 开头
  • <INPUT_INDEX> 上面是-i <INPUT_FILE_NAME>
  • 的顺序 上面的
  • <STREAM_INDEX> 是在每个 <INPUT_FILE_NAME> 中找到的流的顺序,它也可以是特殊字符,例如 a(所有音频流)或 v(所有视频流)流),有关更高级的用法,请查看 FFmpeg -map 。在此示例中,假设视频流位于索引 0,音频流位于索引 1
  • -c copy 表示 stream copy,因此 FFmpeg 将复制每个输入视频流以进行复用/解复用,而不是对每个视频流重新编码。

命令执行会输出这样的消息:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from "/path/to/video_A.mp4"
 ..... <OMITTED_NOT_IMPORTANT> ..... 
  Duration: 00:04:54.08, start: 0.000000, bitrate: 146 kb/s
    Stream #0.0(und): Video: h264 (Main), yuv420p, 256x140 [PAR 1:1 DAR 64:35], 10 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc
    Stream #0.1(und): Audio: aac, 44100 Hz, stereo, fltp, 127 kb/s

Input #1, mov,mp4,m4a,3gp,3g2,mj2, from "/path/to/video_B.mp4"
 ..... <OMITTED_NOT_IMPORTANT> ..... 
  Duration: 00:05:35.01, start: 0.000000, bitrate: 363 kb/s
    Stream #1.0(und): Video: h264 (Main), yuv420p, 426x240 [PAR 1:1 DAR 71:40], 229 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc
    Stream #1.1(eng): Audio: aac, 44100 Hz, stereo, fltp, 127 kb/s

Input #2, mov,mp4,m4a,3gp,3g2,mj2, from "/path/to/video_C.mp4"
 ..... <OMITTED_NOT_IMPORTANT> ..... 
Duration: 00:05:35.01, start: 0.000000, bitrate: 363 kb/s
    Stream #2.0(und): Video: h264 (Main), yuv420p, 426x240 [PAR 1:1 DAR 71:40], 229 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc
    Stream #2.1(eng): Audio: aac, 44100 Hz, stereo, fltp, 127 kb/s

Output #0, mp4, to '/path/to/output_mux_video.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
 ..... <OMITTED_NOT_IMPORTANT> ..... 
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #1:0 -> #0:1 (copy)
  Stream #2:0 -> #0:2 (copy)
  Stream #2:1 -> #0:3 (copy)
Press ctrl-c to stop encoding
frame= 8818 fps=  0 q=-1.0 Lq=-1.0 size=   15342kB time=293.87 bitrate= 427.7kbits/s    
video:9783kB audio:5235kB global headers:0kB muxing overhead 2.160838%

通过检查上面的 Stream mapping 部分,您将知道映射是否符合您的预期。

对于那些遇到类似问题的人,这个答案可以节省您的时间。

答案 8 :(得分:0)

MP4Box可以在不破坏音频的情况下工作。我做了以下工作以获得良好的结果:

  1. 从gpac网站下载最新的Linux deb版本: http://gpac.wp.mines-telecom.fr/downloads/gpac-nightly-builds/

  2. 使用-force-cat选项

  3. 示例命令行:

    MP4Box -force-cat -add in1.mp4 -cat in2.mp4 -cat in3.mp4 ... out.mp4
    

    一些小评论:

    1. 上述方法很重要,因为与Linux Mint 13一起发布的MP4Box的最新版本存在错误,并且导致音频损坏。

    2. -force-cat很重要,因为视频格式标签在没有它的情况下从AVC更改为avc3。

答案 9 :(得分:0)

您可以避免显式创建列表文件,而只需一行即可完成整个操作

ffmpeg -f concat -safe 0 -i <(for f in ./*.mp4; do echo "file '$PWD/$f'"; done) -c copy output.mp4

请参阅ffmpeg wiki

答案 10 :(得分:0)

here所示,您有几种选择:

1。 concat协议:

ffmpeg -i "concat:input1.ts|input2.ts|input3.ts" -c copy output.ts

2。 concat过滤器:

我不完全了解这一点,您可能需要查看所有图表和过滤器图表,但是它可以让您处理多种格式和不同的编解码器属性

    ffmpeg -i input1.mp4 -i input2.webm -i input3.mov \
-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[outv][outa]" \
-map "[outv]" -map "[outa]" output.mkv

3。 concat多路分配器:

首先,您需要生成某种列表文件,例如。 “ mylist.txt”

    # this is a comment
    file '/path/to/file1.wav'
    file '/path/to/file2.wav'
    file '/path/to/file3.wav'

第二,您需要运行命令以使用列表

ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.wav