我有一个正在尝试编译的视频项目。以下是概述:
- 我有很多 5 分钟培训课程的视频 - 主要视频。
- 简介视频将是一段标准的 5 秒视频,其中包含视频标题和作者。它将与主视频串联在一起。
- 尾随视频基本上是一段库存视频,将连接到主视频并包含所有法律信息等。
- 简介视频将平滑地淡入主视频,并且当您到达主视频结束时,它也会很好地淡入尾随视频。
- 该产品是一部全新视频,集简介、主要视频和预告片于一体!
这个概念其实很简单。事实上,我找到了一个已经解决了这个问题的人的例子,并且做我想要做的事。
该解决方案是一个 Bash 脚本,它采用包含标题、作者等的配置文件,并生成简介、结尾,并将它们连接起来创建最终视频。
我使用的是 Ubuntu 12.04 Server。我一直试图将其作为示例,但由于不兼容错误而无法运行。我甚至尝试使用.MP4
容器或来转换它.MKV
。我遇到了一个又一个错误或不兼容问题。我甚至ffmpeg
使用 2013 年 10 月 25 日的版本更改了二进制文件http://ffmpeg.gusari.org/static/64bit/我喜欢这个,因为我不必担心重建二进制文件。几乎成功了,但我又遇到了一些无法解决的错误。
我知道部分问题在于视频制作、编解码器、格式对我来说是一个全新的领域,所以我正在尝试探索这个新领域。
也许这里的专家有类似的东西,我可以使用它们作为使用 MP4 或 h.264 格式的指南。或者从 URL 中获取上述解决方案,并使其与最新版本的 ffmpeg 配合使用。
我将在下面包含脚本及其参数文件和输出(由于限制而缩写)。基本上,就脚本目前的情况而言,运行时我收到错误[matroska,webm @ 0x27bbee0] Read error
。此错误是从第一个 ffmpeg 命令的“reasembleVideo”例程返回的。
以下是参数文件:
#!/bin/bash
INPUTFILE="ssh_main.mp4"
LOGO="logo.png"
LOGOLENGTH="1"
SPEAKER="Jason"
TITLE="Basic SSH Video"
DATE="October 28, 2013"
SCENESTART="00:00:01"
SCENEDURATION="00:00:09"
OUTPUTFILE="ssh_basic_1"
}
以下是我正在运行的脚本。${OUTPUTFILE}
正在使用的是一个我在 screen-o-matic 中以 MP4 格式创建的 2 分钟小视频。
PasteBin 上的脚本(对于超级用户来说帖子太长了)
答案1
在生产环境中,当有许多视频需要合并时,为了使流程自动化,您可以将其分成四个部分。假设您一开始有 100 个主要培训视频。这些视频被命名为 main001.mov、main002.mov 等等,直到 main100.mov。
- 通过 imagemagick/graphicsmagick/gimp/photoshop/whatever 以 png 或其他格式创建 100 张标题卡。
- 在 ffmpeg 中将这些文件转换为 mov 文件。我使用准备好的无声立体声文件进行演示,而不是从空设备引入,但这样也可以。这将创建一个淡入淡出的 5 秒标题:
#!/bin/bash for i in *.png; do ffmpeg -y -loop 1 -f image2 -i $i -i silence.wav -t 00:00:05 -s 1920x1080 -aspect 16:9 -acodec pcm_s24le -b:a 128k -vcodec qtrle -b:v 1024k -filter_complex 'fade=in:0:10, fade=out:110:10' -f mov ${i%%.png}.mov done
这将从提供的 png 文件中创建(100)个 mov 标题。
- 将结束卡创建为 png 并像以前一样转换为 mov,现在您可以说:
ffmpeg -y -loop 1 -f image2 -i endcard.png -i silence.wav -t 00:00:05 -s 1920x1080 -aspect 16:9 -acodec pcm_s24le -b:a 128k -vcodec qtrle -b:v 1024k -filter_complex 'fade=in:0:10, fade=out:110:10' -f mov endcard.mov
- 连接三组文件,前两组各有 100 个文件,分别是 title 和 main,第三组只包含一个共同的结束文件。为此,你将这三组文件的文件名放在三个数组中,然后循环遍历数组的索引以将它们连接起来,如下所示:
#!/bin/bash # define the movie array movie=("main001.mov" "main002.mov" .....and so on till ... "main100.mov") #define titles array title=("title001.mov" "title002.mov" .....and so on till ... "title100.mov") #define end card array endcard=("endcard.mov") # Use for loop # get total subscripts in an array total=${#movie[*]} for (( i=0; i<=$(( $total -1 )); i++ )) do ffmpeg -i ${title[i]} -i ${movie[i]} -i ${endcard[0]} -y -filter_complex '[0:0] setsar=1/1[sarfix];[sarfix] [1:0] [2:0] concat=n=3:v=1:a=0 [v]' -map '[v]' -pass 1 -strict -2 -an -vcodec libx264 -pix_fmt yuv420p -aspect 16:9 -threads 4 -b:v 1024k -flags +loop -cmp chroma -partitions +parti4x4+partp8x8+partb8x8 -subq 1 -trellis 0 -refs 1 -bf 3 -b_strategy 2 -coder 1 -me_range 16 -g 250 -keyint_min 75 -sc_threshold 40 -i_qfactor 0.71 -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 ${movie[i]%%.mov}.mp4 ffmpeg -i ${title[i]} -i ${movie[i]} -i ${endcard[0]} -y -filter_complex '[0:0] setsar=1/1[sarfix];[sarfix] [0:1] [1:0] [1:1] [2:0] [2:1] concat=n=3:v=1:a=1[v] [a]' -map '[v]' -map '[a]' -strict -2 -acodec aac -b:a 128k -pass 2 -vcodec libx264 -pix_fmt yuv420p -aspect 16:9 -threads 4 -b:v 1024k -flags +loop -cmp chroma -partitions +parti4x4+partp8x8+partb8x8 -mixed-refs 1 -subq 6 -trellis 1 -refs 5 -bf 3 -b_strategy 2 -coder 1 -me_range 16 -g 250 -keyint_min 75 -sc_threshold 40 -i_qfactor 0.71 -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 ${movie[i]%%.mov}.mp4 done
第 1 轮不考虑音频。结束卡数组的索引是静态的 0,因为只有一个。当然,您可以直接在此处传递文件的名称,而不是使用数组。如果标题电影甚至结束卡电影导致问题,则可能需要 Sarfix。我没有显示结束卡电影的 sarfix 选项 - 这将需要在 [2:0] 映射后设置 setsar=1/1[sarfix];[sarfix]。另请注意,大小和比特率可能不适用于您。
通过这种方式,您可以自动连接大量主文件与标题和结束卡。
答案2
您有 2 个 ${OUTPUTFILE}.mkv 吗?一个用于主输入,一个用于最终输出?将最后一个明确更改为 ${FINALOUTPUT}.mkv 之类的内容。您在 mkv 格式上使用 concat 协议。您应该使用 concat 解复用器,或将整个中间文件更改为 mpeg 或 .ts 格式。另外:
将速率 - r 29.97 放在 -i "${OUTPUTFILE}-frames"/frame%d.png 之后。
因此,不要这样:
./ffmpeg -threads 4 -r 29.97 -f image2 -i "${OUTPUTFILE}-frames"/frame%d.png \ -i "${OUTPUTFILE}.mkv" -c:a copy \ -map 0:0 -map 1:0 -f MP4 -y "${OUTPUTFILE}.mkv"
使用:
./ffmpeg -threads 4 -f image2 -i "${OUTPUTFILE}-frames"/frame%d.png -r 29.97 \ -i "${OUTPUTFILE}.mkv" -c:a copy \ -map 0:0 -map 1:0 -f MP4 -y "${OUTPUTFILE}.mkv"
在连接阶段,尝试不使用速率:
./ffmpeg -threads 4 \ -i concat:"${OUTPUTFILE}-intro.mkv"\|"${OUTPUTFILE}.mkv"\|"${OUTPUTFILE}-exit.mkv" \ -y "${FINALOUTPUT}.mkv"
如果这不起作用,则必须使用其他 concat 选项,例如 concate demuxer:
ffmpeg -f concat -i mylist.txt -c copy output
其中 mylist.txt 包含三个生成的文件的列表。
请参阅这。
还存在其他问题,其中一个流默认为 yuv444p,而另一个流明确为 yuv420p。这应该明确说明 -pix_fmt yuv420p:
ffmpeg -loop 1 -i "${OUTPUTFILE}-intro.png" -q:v 1 -r 29.97 -t ${LOGOLENGTH} -y -f MP4 "${OUTPUTFILE}-logo1.mkv"
以及下一阶段:
ffmpeg -i "${OUTPUTFILE}-logo1.mkv" -i "silence.mkv" \ -c:v copy -c:a copy -map 0:0 -map 1:0 -threads 4 \ -y -f MP4 "${OUTPUTFILE}-intro.mkv"