在解决我的ffmpeg命令行时需要帮助

时间:2019-04-03 09:25:59

标签: ffmpeg

我创建了一个小的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

整天都在工作,但我仍然无法正常工作。

有人可以指导我哪一部分错了吗?

2 个答案:

答案 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)。

但是,这个特定示例是有争议的,因为...

只需使用流说明符

不需要VIDEOMAPAUDIOMAP

代替:

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检查您的脚本

shellcheck.net将帮助您清理脚本并防止出现问题:它有许多有关脚本的建议。