ffmpeg/avconv:使用相同的编解码器和参数作为输入进行转码
Posted
技术标签:
【中文标题】ffmpeg/avconv:使用相同的编解码器和参数作为输入进行转码【英文标题】:ffmpeg/avconv: transcode using same codec and params as input 【发布时间】:2016-03-30 06:30:03 【问题描述】:有没有办法告诉 ffmpeg 和/或 avconv 使用与输入编码的编解码器相同的编解码器进行输出,但进行转码?
我正在寻找类似的东西:
ffmpeg -i input.mp4 -vcodec same_as_input output.mp4
请注意,我不是在寻找 -vcodec copy
,因为这会复制流而不进行转码。我希望它进行转码,但使用与输入文件编码相同的编解码器。
另外,如果可能的话,我希望每个可能的参数都相同,即:使用相同的比特率、帧大小等,从一个给定的输入文件中获取每个可能参数的值,而不是使用任何其他默认值。
上面的例子可能看起来很愚蠢,因为它过于简单(结果与复制相同),但想象一下我添加了一些处理,例如开始时间和长度,甚至更复杂的东西,例如添加叠加图像,但我想确保它使用与输入文件相同的编码器(可能还有相同的参数)进行编码。
【问题讨论】:
ffprobe 返回有关视频文件的信息,包括编解码器。您可以让程序或脚本解析其输出以检测原始编解码器并有条件地使用相同的编解码器进行转码。 见票#5081: A wish for ffmpeg to be able to reference input properties。你怎么知道比特率和其他选项不是次优的?你怎么知道制作文件的人知道他们在做什么或者正在使用一个健全的编码器实现? @LordNeckbeard 您可能出于多种原因想要重现输入属性,无论它们是最佳还是好的。一个用例:我有一个视频文件在某些软件中触发了问题,我想提供示例文件,但它太长或包含私人内容,因此我无法按原样共享它,因此我需要制作一个具有相同属性的修改版本(因为我不知道哪个是产生问题的相关版本) 和另一个用例:您想对视频文件进行一些简单的修改(例如修剪)并且您知道它的属性“足够好”(因为质量看起来不错并且文件不是很大),因此您知道,通过保持相同的属性,即使不是最优的,它也会很好,并且您不必为所有事物找出最佳参数。 @cantelope 如果您可以共享一个示例脚本(它可以是单行吗?)用于对单个文件进行转码,例如,使用与输入相同的编解码器和比特率,我会接受作为答案:) 【参考方案1】:这似乎有效
file="input.mp4"
ffmpeg -re -y -i "$file" -c:v `ffprobe $file |& grep 'Video:' | awk -v N=4 'print $N'` -b:v `ffprobe $file |& grep 'Video:' | awk -v N=15 'print $N'`k -f flv output.mp4
这里的关键是这部分,它从输入文件中抓取视频编解码器。您会注意到这在语句中出现了两次,第二次是获取比特率。
`ffprobe $file |& grep 'Video:' | awk -v N=4 'print $N'`
【讨论】:
您在正确的轨道上,但如果输入包含多个视频流,这将中断。您的ffprobe
比特率示例为我返回DAR
,因为输出顺序可能会有所不同。您可以消除grep
和awk
:ffprobe -loglevel error -select_streams v:0 -show_entries stream=codec_name,bitrate -of default=nk=1:nw=1 input.mp4
(参见FFprobe Tips)。 bit_rate
流并不总是可用(尝试 mkv 输入),因此必须通过除以 视频流大小/持续时间 来获取它。当输出为 mp4 时,-f flv
是什么?
@lordneckbeard 检索到的单词对应于 N 的值。在我的系统上,编解码器是单词 4,比特率是单词 15,但你是对的,这在其他系统上很容易不同。 Op 需要对其进行测试以验证它是否适用于他的配置。由于某种原因,脚本在没有 -f flv 的情况下在我的系统上失败。【参考方案2】:
ffmpeg
没有复制相同比特率的功能,但它会自动复制帧率、宽度、高度、像素格式、纵横比、音频通道数、音频采样率等,(取决于编码器)。
我不建议复制相同的比特率,原因有很多,最终会变成多个段落。简而言之,让编码器自动处理。
但是,这是一个简单的 bash 脚本。您需要对其进行调整以包含音频流信息和您想要的任何其他参数。
#!/bin/bash
# Copies the same video codec and bitrate: usually this is not a good idea.
# Usage: ./vidsame input output
echo "Calculating video bitrate. This can take a while for long videos."
# Alternatively you could just use ffprobe to get video stream bitrate,
# but not all inputs will show stream bitrate info, so ffmpeg is used instead.
size="$(ffmpeg -i "$1" -f null -c copy -map 0:v:0 - |& awk -F'[:|kB]' '/video:/ print $2')"
codec="$(ffprobe -loglevel error -select_streams v:0 -show_entries stream=codec_name -of default=nk=1:nw=1 "$1")"
duration="$(ffprobe -loglevel error -select_streams v:0 -show_entries format=duration -of default=nk=1:nw=1 "$1")"
bitrate="$(bc -l <<< "$size"/"$duration"*8.192)"
ffmpeg -i "$1" -c:v "$codec" -b:v "$bitrate"k "$2"
echo
echo "Duration: $duration seconds"
echo "Video stream size: $size KiB"
echo "Video bitrate: $bitrate kb/s"
echo "Video codec: $codec"
如果您需要其他参数,请使用ffprobe
查看可用参数列表:
ffprobe -loglevel error -show_streams input.mkv
然后如脚本所示使用-select_entries
。
请注意,codec_name
并不总是与编码器名称匹配,但通常它会正常工作。见ffmpeg -encoders
。
【讨论】:
以上是关于ffmpeg/avconv:使用相同的编解码器和参数作为输入进行转码的主要内容,如果未能解决你的问题,请参考以下文章
如何在不创建新文件的情况下使用 ffmpeg/avconv 更改元数据?