使用 FFMPEG 以最少的重新编码添加覆盖
Posted
技术标签:
【中文标题】使用 FFMPEG 以最少的重新编码添加覆盖【英文标题】:Adding an Overlay Using FFMPEG With Minimal Re-Encoding 【发布时间】:2016-03-14 20:03:50 【问题描述】:FFMPEG 对于剪切视频的一部分非常有用,无需重新编码视频。
我知道也可以使用 FFMPEG 在视频的特定部分(例如从 10 秒到 20 秒)中添加叠加图像。
我的问题是:如果我对图像进行这种叠加,整个视频会因此被重新编码吗?还是只对相关的持续时间进行编码?
还有什么选项可以使重新编码最小化吗? 目的当然是保持与原始视频一样的视频质量.. (我根本不要求重新编码,但我不明白这怎么可能......)
谢谢
【问题讨论】:
过滤时整个视频会被重新编码。 哦.. 甚至没有我可以设置的参数来改进它?好的,我明白了。。谢谢。顺便说一句,如果你在下面的答案中写了这个,我可以点击接受。.. 您可能能够在不重新编码的情况下进行拆分,将叠加层添加到相关段,然后将所有内容连接回来。取决于您的关键帧在哪里,您可能无法准确地剪切 10 到 20 秒之间的标记。试试video.stackexchange.com 这是一个有趣(而且肯定会奏效)的想法。关于“根据关键帧所在的位置,您可能无法准确地剪切 10 到 20 秒之间的标记。” - 有没有办法让我给 FFMPEG 一个视频文件,并让它为我列出所有时间点,这些时间点是一个新的“数据包”(或者那些称为第二个片段)?这样我就可以尝试在一个结束另一个开始时准确地计划切割.. 是的,您可以使用同一包中的ffprobe
来显示数据包并搜索关键帧时间戳ffprobe -show_packets -select_streams v <input>
。另请参阅 ffmpeg Seeking wiki,它会有所帮助。
【参考方案1】:
另一种方法是使用播放器:
ffplay -f lavfi "movie=main.mkv[bg];movie=logo.png[fg];[bg][fg]overlay=W-w-10:H-h-10:enable=between'(t,10,20)'[out0];amovie=main.mkv[out1]"
无需编码。没有质量损失。即时满足。
【讨论】:
如果我理解正确,因为您正在执行ffplay
,这意味着覆盖仅显示在屏幕上,但不会以某种方式嵌入到文件中。我也想要文件中的更改..(只是希望可以通过最少的重新编码)
@spaceman 正确。问题中并不清楚您是否需要将其永久包含在视频中,但也许这种方法可能对其他有一些奇怪用例的用户有用。【参考方案2】:
如果您在视频的一部分上叠加图像,整个视频将被重新编码。您可以避免重新编码整个内容的一种方法是剪掉您希望覆盖的部分并仅重新编码该部分(请参阅-t duration
开关和documentation 中的-ss position
开关
您需要在整个过程中保持当前的编码参数。这在拆分时很容易做到,因为您可以将 copy 参数用于编解码器开关,例如 -c:a copy -c:v copy
概念化(注意这些不是完整的命令):
第 1 部分:电影开头(您不希望覆盖的前 10 秒)(通过 ffmpeg -i SourceFileName -t 10 -c:a copy -c:v copy SourceFileNameP1.mkv
获得,其中 SourceFileName 是您要处理的视频。
Part2:要叠加的10到20秒之间的电影部分(通过ffmpeg -i SourceFileName -ss 10 -t 10 -c:a copy -c:v copy SourceFileNameP2
获得)
Part3:影片结尾(通过`ffmpeg -ss 20 -c:a copy -c:v copy获得)
额外提示:您可以通过将 `-ss 参数移到输出文件之前来获得更慢但更精确的切割。这将从输出中丢弃帧,而不是在创建输出之前尝试寻找输入上的正确位置。
如果不知道源文件的编码细节,可以通过ffprobe SourceFileName
或者我最喜欢的mediainfo SourceFileName
获取
我建议至少将 Matroska 容器用于中间输出,因为它具有灵活性和低开销。
这是一个脚本,您可以使用(在基于 Debian 的系统上)获取匹配的必要参数。
#!/bin/bash
#mknfo.sh
#Written by Elder Geek for the Stack Exchange network
# 1/1/2018
####################################################################################################
#bash script to create an nfo file which includes information to help joining video clips #
####################################################################################################
# This function will create an nfo file including the tech specs for a specified media file #
####################################################################################################
function shortinfo
echo $@
mediainfo --Inform="General;Duration=%Duration/String2%\nFile size=%FileSize/String1%\nBit Rate=%OverallBitRate/String% " "$@"
echo -n "Video: "
mediainfo --Inform="Video;FrameRate=%FrameRate/String% BitRate=%BitRate/String% Resolution=%Width%x%Height% Codec=%CodecID%" "$@";
echo -n "Audio: "
mediainfo --Inform="Audio;Mode=%BitRate_Mode/String% BitRate=%BitRate/String% Format=%Format%" "$@";
echo "-----------------------------------------------------------------------------"
####################################################################################################
# This function will check for the existence of mediainfo and attempt installation if not found #
####################################################################################################
function getmi
echo "mediainfo is required and not found. Attempt install Y/N"
read -n 1 solve
if [ $solve==Yy ]
then sudo apt-get -y install mediainfo
else echo "Cannot continue"
exit 1
fi
####################################################################################################
# Main program #
####################################################################################################
if [ $# -ne 1 ]
then
echo Error
echo "$0" requires a single filename argument. Example: "$0" Videofile
exit 2
fi
exist=$(which mediainfo)
if [ "$exist" == "" ];
then getmi
fi
target=$(pwd)"/"$1".nfo"
if [ -e $target ]
then
echo Error: "$1.nfo" already exists
exit 3
fi
echo "Creating $target"
shortinfo "$1" > "$target"
exit 0
Now you'll want to re-encode the overlay section (Part2) of the video to exactly match the parameters (same audio and video codecs and same bitrate and sample rate as the original of Part1 and Part3 to allow for joining.
完成后,您可以将所有部分连接在一起。
mkvmerge -o joined.mkv Part1 + Part2Reencoded + Part3
请注意,重新编码总是会导致一些质量损失,因此片段之间的连接可能会显示出明显的缺陷。这可能会或可能不会因覆盖同时出现和消失的代码而引起的分心。
这可能会根据材料的长度显着减少重新编码的时间,并且具有仅重新编码必须重新编码的内容的额外好处。
here 介绍了如何覆盖重新编码的片段,您可以调整接受的答案以匹配您的材料。
【讨论】:
以上是关于使用 FFMPEG 以最少的重新编码添加覆盖的主要内容,如果未能解决你的问题,请参考以下文章