交互式连接视频文件


9

如何以交互方式将多个MP4视频文件串联(合并)为一个文件?

有很多程序从命令行对两个文件执行此操作。例如:

  • ffmpeg
  • avconv
  • MP4盒

但是我们经常需要一种解决方案来交互地执行此操作。


1
您能描述互动的意思吗?
slm

@slm我的意思是一个程序,要求用户先输入输入文件,然后再创建输出文件。然后进行串联。
Slyx

我从未见过直接执行此操作的程序,就像您精心制作的那样,它是一个收集信息然后组装命令行的shell脚本。您是否正在寻找所拥有的改进?
slm

@slm我发布了这篇文章,因为它经常需要像我这样的多媒体用户。所以我希望它可以帮助其他人。当然,任何改进都值得欢迎!
Slyx

1
@gold我将编辑放入队列中。ffmpeg确实绝不是死亡或过时:最后一次git提交是master15分钟前,我每天都使用它。
Anko 2014年

Answers:


8

我最近没有尝试过这种方法,但是不明白为什么它仍然无法使用。我相信cat .mp4,如果您只想将它​​们串联起来,就可以将它们归档在一起。

1.使用猫

$ cat file1.mp4 file2.mp4 > file3.mp4
$ ffmpeg -i file3.mp4 -qscale:v 2 output.avi

我一直ffmpeg都在使用,它也可以连接文件。

2.使用ffmpeg

  1. 列出要串联的文件

    $ cat inputs.txt 
    file sample_mpeg4.mp4
    file sample_mpeg4.mp4
    
  2. 连接

    $ ffmpeg -f concat -i inputs.txt -c copy out.mp4
    
    $ ll |grep -E "sample|out"
    -rw-rw-r--. 1 saml saml 491860 Feb 19 23:36 out.mp4
    -rw-r--r--. 1 saml saml 245779 Feb 19 23:32 sample_mpeg4.mp4
    

    FFmpeg Wiki中介绍了其他方法:如何串联(合并,合并)媒体文件

    注意: Ubuntu似乎不支持该concat格式。您必须使用concat协议。此外,它还有按流编解码器选项。因此,使用concat协议的结果如下:

    $ ffmpeg -i input1.mp4 -vcodec copy -acodec copy \
         -vbsf h264_mp4toannexb -f mpegts intermediate1.ts
    
    $ ffmpeg -i input2.mp4 -vcodec copy -acodec copy \
         -vbsf h264_mp4toannexb -f mpegts intermediate2.ts
    
    $ ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" \
         -vcodec copy -acodec copy -absf aac_adtstoasc output.mp4
    

    Ubuntu ffmpeg选项在此处记录


有趣!我不知道catMP4文件够用了!解决方案虽然不是交互式的!
Slyx

@Slyx-是的,这就是为什么我问您互动的意思。让我看看你对此有何评论,并看看我能对此做些什么。检查是否cat可以。我上次使用它的时候是用.mpg文件定义的。与那些人一起工作。
slm

2
我证实了。使用cat不是有效的解决方案。通过生成cat两个文件生成的文件仅显示第一个输入文件的内容!
Slyx

@Slyx-cat可以工作,但是时间戳不正确,因此,当您尝试播放时,视频播放器会因时间戳从00跳到结尾再回到00而感到困惑。如果您要对此视频进行转码,将在该过程中得到解决。也有一些方法可以重新生成时间戳。
slm

我也是那个意思。那里有两个内容,但是媒体播放器只检测到第一个。
Slyx

4

我使用MP4Box作为工作库。
我建议该脚本一个接一个地读取所有文件,验证每个文件(天气是一个普通文件),并要求用户输入要创建的文件名。

#!/bin/bash
printf "###  Concatenate Media files ###\n"
fInputCount=0
# Reading input files
IFS=''
while (true)
do
    let currentNumber=$fInputCount+1 
    printf "File n°%s (\"ok\" to finish): " $currentNumber
    read inputFile
    [ "$inputFile" == "ok" ] && break
    [ ! -e "$inputFile" ] || [ ! -f "$inputFile" ] && printf "\"%s\" : Invalid filename. Skipped !\n" "$inputFile" && continue
    ((fInputCount++))
    inputFileList[$fInputCount]=$inputFile
    printf "\"%s\" : Added to queue !\n" "$inputFile"
done
[ "$fInputCount" == "0" ] || [ "$fInputCount" == "1" ] && echo "No enough input data. BYE ! " && exit
# Listing the input file list 
for ((i=1;i<=$fInputCount;i++))
do
    printf "%2d : %s\n" $i ${inputFileList[$i]}
done
# Reading the output filename
while (true)
do
    printf "Output file without extention (\"none\" to dismiss) : "
    read outputRead
    [ "$outputRead" == "none" ] && echo "Dismissed. BYE ! " && exit
    [ "$outputRead" == "" ] && echo "Try again ! " && continue
    [ -e "$outputRead" ] && echo "\"$outputRead\" exists. Try again !" && continue
    outputFile=$outputRead.mp4
    echo "Output to \"$outputFile\". Go !" && break
done
# Creating a random temporary filename
tmpOutFile="/tmp/concatMedia"`date +"%s%N"| sha1sum | awk '{print $1}'`".mp4"
# Joining the two first input files
MP4Box -cat "${inputFileList[1]}" -cat "${inputFileList[2]}" $tmpOutFile
# Adding all other files
for ((i=3;i<=$fInputCount;i++))
do
    tmpIntermediateFile=$tmpOutFile
    tmpOutFile="/tmp/concatMedia"`date +"%s%N"| sha1sum | awk '{print $1}'`".mp4"
    MP4Box -cat $tmpIntermediateFile -cat "${inputFileList[$i]}" $tmpOutFile
    rm $tmpIntermediateFile
done
mv $tmpOutFile "$outputFile"
# Finished
echo "\"$outputFile\" Saved !"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.