通过在主视频中添加简介和尾随视频来自动生成视频

通过在主视频中添加简介和尾随视频来自动生成视频

我有一个正在尝试编译的视频项目。以下是概述:

  1. 我有很多 5 分钟培训课程的视频 - 主要视频。
  2. 简介视频将是一段标准的 5 秒视频,其中包含视频标题和作者。它将与主视频串联在一起。
  3. 尾随视频基本上是一段库存视频,将连接到主视频并包含所有法律信息等。
  4. 简介视频将平滑地淡入主视频,并且当您到达主视频结束时,它也会很好地淡入尾随视频。
  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"

相关内容