我创建了一个小的bash脚本来编码1080p视频,该视频将在左下方添加水印,并且我需要在顶部和底部添加黑色填充
我尝试了几种方法,但还是没有运气,我尝试了-vf,是的,但是不能同时使用padding和watermark,建议使用filter_complex
如果我直接使用此代码而不使用bash脚本,那么它将起作用
time ffmpeg -hide_banner -i transformers.mp4 -i transformers.ass -loop 1 -i watermark.png -loop 1 -i logo.png -map 0:0 -map 0:1 -filter_complex "[0:0]scale=(iw*sar)*min(1920/(iw*sar)\,800/ih):ih*min(1920/(iw*sar)\,800/ih), pad=1920:800:(1920-iw*min(1920/iw\,800/ih))/2:(800-ih*min(1920/iw\,800/ih))/2;ass=transformers.ass[FID1];[FID1][2:v]overlay=10:${WATERMARKPOSITION}:repeatlast=0:enable='between(t,300,600)'[FID3];[3:v]fade=in:st=1200:d=1.6:alpha=1,fade=out:st=107998:d=1.6:alpha=1[FID6];[FID3][FID6]overlay=10:5:repeatlast=0:enable='between(t,1200,187922)'" -c:v libx264 -minrate 1800k -maxrate 1800k -bufsize 3600k -profile:v high -c:a aac -b:a 128k -profile:a aac_main -movflags faststart -strict -2 -f mp4 -y "transformers.mp4"
但是当我将其包含在bash脚本中时,出现此错误,
[libx264 @ 0x2a063e0] height not divisible by 2 (300x39)
Output #0, mp4, to '/movie/Paddy/output/Transformers.Age.of.Extinction.2014.1080p.BluRay.H264.AAC-RARBG.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
comment : Transformers.Age.of.Extinction.2014.1080p.BluRay.H264.AAC-RARBG
encoder : Lavf57.71.100
title : Transformers Age of Extinction 2014 1080p BluRay H264 AAC-RARBG - Visit us @ Juraganfilm.COM
Stream #0:0: Video: h264 (libx264), yuv420p, 1920x800 [SAR 1:1 DAR 12:5], q=-1--1, max. 2300 kb/s, 23.98 fps, 23.98 tbn, 23.98 tbc
Metadata:
encoder : Lavc56.60.100 libx264
Stream #0:1: Video: h264, none, q=2-31, 128 kb/s, SAR 1:1 DAR 0:0, 25 fps
Metadata:
encoder : Lavc56.60.100 libx264
Stream #0:2(eng): Audio: aac, 0 channels, 128 kb/s (default)
Metadata:
creation_time : 2017-12-19 07:58:39
handler_name : SoundHandler
encoder : Lavc56.60.100 aac
Stream mapping:
Stream #0:0 (h264) -> scale (graph 0)
Stream #0:0 (h264) -> overlay:overlay (graph 0)
Stream #2:0 (png) -> ass (graph 0)
Stream #3:0 (png) -> fade (graph 0)
pad (graph 0) -> Stream #0:0 (libx264)
overlay (graph 0) -> Stream #0:1 (libx264)
Stream #0:1 -> #0:2 (aac (native) -> aac (native))
Error while opening encoder for output stream #0:1 - maybe incorrect parameters such as bit_rate, rate, width or height
下面是我一直在处理的脚本
output="/movie/output"
FILESDIR=`find $PWD -type f -regex ".*\.\(mp4\|mkv\|avi\)" | sed 's@.*/@@' | sort -n`
for video in $FILESDIR
do
MOVIETITLE=${video%.*}
INFOVID=${MOVIETITLE//./ }
BITRATE="${HEIGHT}"
WIDTH=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 ${video} 2>&1 | sed -e 's|\[.*||g' | sed ':a;N;$!ba;s/\n//g' | sed -e 's|x.*||g')
HEIGHT=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 ${video} | sed -e 's/.*x//')
WATERMARKPOSITION=$(expr $HEIGHT - 50)
VIDEOMAP=$(ffmpeg -i $video 2>&1 | grep "Stream #" | grep Video | sed -e "s|.*\#||g" | sed -e "s|: Video.*||g" | sed -e "s|(.*||g")
AUDIOMAP=$(ffmpeg -i $video 2>&1 | grep "Stream #" | grep Audio | sed -e "s|.*\#||g" | sed -e "s|: Audio.*||g" | sed -e "s|(.*||g")
MAXRATE=$(expr $BITRATE + 500)
BUFFSIZE=$(expr $MAXRATE \* 2)
time ffmpeg -hide_banner -i $video -i $MOVIETITLE.ass -loop 1 -i $WATERMARK -loop 1 -i $LOGO -map ${VIDEOMAP} -map ${AUDIOMAP} -filter_complex "[${VIDEOMAP}]scale=(iw*sar)*min(${WIDTH}/(iw*sar)\,${HEIGHT}/ih):ih*min(${WIDTH}/(iw*sar)\,${HEIGHT}/ih), pad=${WIDTH}:${HEIGHT}:(${WIDTH}-iw*min(${WIDTH}/iw\,${HEIGHT}/ih))/2:(${HEIGHT}-ih*min(${WIDTH}/iw\,${HEIGHT}/ih))/2;ass=$MOVIETITLE.ass[FID1];[FID1][2:v]overlay=10:${WATERMARKPOSITION}:repeatlast=0:enable='between(t,300,600)'[FID3];[3:v]fade=in:st=1200:d=1.6:alpha=1,fade=out:st=107998:d=1.6:alpha=1[FID6];[FID3][FID6]overlay=10:5:repeatlast=0:enable='between(t,1200,187922)'" -c:v libx264 -minrate ${BITRATE}k -maxrate ${MAXRATE}k -bufsize ${BUFFSIZE}k -profile:v high -c:a aac -b:a 128k -profile:a aac_main -movflags faststart -strict -2 -f mp4 -y "${output}/$MOVIETITLE.mp4"
done
整天都在工作,但我仍然无法正常工作。
有人可以指导我哪一部分错了吗?
答案 0 :(得分:0)
1)删除映射。未标记的filter_complex输出将自动映射,因此-map 0:0
将映射未处理的视频流。没有任何地图。一个音频流将是picked up,并且在您的输入中只有一个。
2)在您的键盘后面有一个分号,使其成为未标记的filter_complex输出,可以直接发送到输出
pad (graph 0) -> Stream #0:0 (libx264)
因此,ass过滤器没有输入,并且最终使用watermark.png进行输入。叠加层和其他滤镜将应用于此流。而且它的大小不能被2整除。
overlay (graph 0) -> Stream #0:1 (libx264)
分号应该是逗号。
3)屁股过滤器正在直接读取字幕文件。不需要将其作为常规输入。
time ffmpeg -hide_banner -i transformers.mp4 -loop 1 -i watermark.png -loop 1 -i logo.png -filter_complex "[0:0]scale=(iw*sar)*min(1920/(iw*sar)\,800/ih):ih*min(1920/(iw*sar)\,800/ih), pad=1920:800:(1920-iw*min(1920/iw\,800/ih))/2:(800-ih*min(1920/iw\,800/ih))/2, ass=transformers.ass[FID1];[FID1][2:v]overlay=10:${WATERMARKPOSITION}:repeatlast=0:enable='between(t,300,600)'[FID3];[3:v]fade=in:st=1200:d=1.6:alpha=1,fade=out:st=107998:d=1.6:alpha=1[FID6];[FID3][FID6]overlay=10:5:repeatlast=0:enable='between(t,1200,187922)'" -c:v libx264 -minrate 1800k -maxrate 1800k -bufsize 3600k -profile:v high -c:a aac -b:a 128k -profile:a aac_main -movflags faststart -strict -2 -f mp4 -y "transformers.mp4"
此外,您淡出和最后覆盖的数字看起来有误。 st=107998
代表107888 秒,即30 小时。 between(t,1200,187922)
答案 1 :(得分:0)
关于您的脚本:
ffprobe
命令这将消除四个sed
实例。
更改:
WIDTH=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 ${video} 2>&1 | sed -e 's|\[.*||g' | sed ':a;N;$!ba;s/\n//g' | sed -e 's|x.*||g')
HEIGHT=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 ${video} | sed -e 's/.*x//')
收件人:
WIDTH=$(ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=p=0 ${video})
HEIGHT=$(ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=p=0 ${video})
ffprobe
而不是ffmpeg
来解析信息 ffmpeg
的stderr输出并不意味着要被机器解析。请改用ffprobe
。这就是它的目的。
所以代替:
VIDEOMAP=$(ffmpeg -i $video 2>&1 | grep "Stream #" | grep Video | sed -e "s|.*\#||g" | sed -e "s|: Video.*||g" | sed -e "s|(.*||g")
这很脆弱,如果输入的视频流不止一个,它将返回多个结果。
相反,您可以这样做:
VIDEOMAP=$(ffprobe -v error -select_streams v:0 -show_entries stream=index -of csv=p=0 $video)
对于音频,只需更改stream specifier中的-select_streams
(将v
更改为a
)。
但是,这个特定示例是有争议的,因为...
不需要VIDEOMAP
和AUDIOMAP
。
代替:
VIDEOMAP=$(ffmpeg -i $video 2>&1 | grep "Stream #" | grep Video | sed -e "s|.*\#||g" | sed -e "s|: Video.*||g" | sed -e "s|(.*||g")
AUDIOMAP=$(ffmpeg -i $video 2>&1 | grep "Stream #" | grep Audio | sed -e "s|.*\#||g" | sed -e "s|: Audio.*||g" | sed -e "s|(.*||g")
在您的-filter_complex
中使用:
0:v:0
引用第一个视频流0:a:0
引用第一个音频流ffmpeg
不需要-strict -2
的崇拜货物。 FFmpeg AAC编码器被认为是实验性时,以前需要这样做。多年没有进行试验,但是用户一直在从旧的,烂的示例中添加它,并复制和粘贴死记硬背的用法。
请勿使用-profile:v high
。除非您需要限制较小的配置文件(“主要”或“基准”)以与较旧或受限的设备/播放器兼容,否则只需让编码器选择配置文件即可。
除非您的输出文件名不明确(例如,缺少扩展名),否则您不需要-f mp4
。
shellcheck.net将帮助您清理脚本并防止出现问题:它有许多有关脚本的建议。