klu*_*utt 5 compression ffmpeg video
我想减小视频的大小,以便能够通过电子邮件等方式发送。我看了这个问题:如何使用 ffmpeg 减小视频的大小?我在那里得到了关于如何减少它的好建议。问题是我需要手动计算比特率。而且在执行此操作时,我必须通过手动试错来完成。
有什么好的方法可以使用ffmpeg
(或其他工具)将视频的大小减小到目标大小?
注意来自froschutz的评论:
过分担心大小并选择固定文件大小而不管视频长度/分辨率/帧率/内容如何,在大多数情况下都不会给出令人满意的结果......将其上传到某个地方,通过电子邮件发送链接。如果您必须对其进行编码,请设置质量级别,保持比特率动态。如果很明显不满足大小,则取消编码并相应地调整质量级别。冲洗并重复。
总的来说是个好建议,但它不适合我的用例。由于技术限制,上传到外部链接不是一种选择,其中之一是接收者没有 http 访问权限。
我还可以澄清,我不是在寻找的正是我指定的大小。如果它合理地接近我想要的就足够了(可能最多低 5% 或 10% 左右),但应该保证它不会超过我的目标限制。
tob*_*bek 12
@philip-couling 的答案很接近,但缺少几部分:
length
(而不是精确使用或向上舍入)将导致文件大小稍微超过目标大小-b
标志指定平均比特率:实际上,编码器会让比特率稍微跳跃,结果可能会超出您的目标大小。-maxrate
但是,您可以使用和来指定最大比特率-bufsize
对于我的用例,我还想要一个硬编码的音频比特率,并相应地调整视频(这似乎也更安全,我不能 100% 确定 ffmpeg 的-b
标志是否一起指定视频和音频流的比特率)。
考虑到所有这些并严格限制为 25MB:
file="input.mp4"
target_size_mb=25 # 25MB target size
target_size=$(( $target_size_mb * 1000 * 1000 * 8 )) # target size in bits
length=`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file"`
length_round_up=$(( ${length%.*} + 1 ))
total_bitrate=$(( $target_size / $length_round_up ))
audio_bitrate=$(( 128 * 1000 )) # 128k bit rate
video_bitrate=$(( $total_bitrate - $audio_bitrate ))
ffmpeg -i "$file" -b:v $video_bitrate -maxrate:v $video_bitrate -bufsize:v $(( $target_size / 20 )) -b:a $audio_bitrate "${file}-${target_size_mb}mb.mp4"
Run Code Online (Sandbox Code Playgroud)
请注意,当-maxrate
限制-bufsize
最大比特率时,平均比特率必然会降低,因此在我的测试中视频将低于目标大小多达 5-10%(在各种目标大小的 20 秒视频上)。的值-bufsize
很重要,上面使用的计算值(基于目标大小)是我的最佳猜测。太小了,它会大大降低质量,并且低于目标大小约 50%,但太大,我认为它可能会超过目标大小?
如果您没有严格的最大文件大小,为了给编码器提供更大的灵活性,删除-maxrate
和-bufsize
会带来更好的质量,但在我的测试中可能会导致视频超出目标大小 5%。文档中的更多信息,您将在其中看到此警告:
注意:如果视频难以编码,限制比特率可能会导致输出质量低下。在大多数情况下(例如存储文件进行存档),让编码器选择合适的比特率是恒定质量或基于 CRF 的编码。
您可以使用以下代码来声明可重用的 bash 函数:
ffmpeg_resize () {
file=$1
target_size_mb=$2 # target size in MB
target_size=$(( $target_size_mb * 1000 * 1000 * 8 )) # target size in bits
length=`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file"`
length_round_up=$(( ${length%.*} + 1 ))
total_bitrate=$(( $target_size / $length_round_up ))
audio_bitrate=$(( 128 * 1000 )) # 128k bit rate
video_bitrate=$(( $total_bitrate - $audio_bitrate ))
ffmpeg -i "$file" -b:v $video_bitrate -maxrate:v $video_bitrate -bufsize:v $(( $target_size / 20 )) -b:a $audio_bitrate "${file}-${target_size_mb}mb.mp4"
}
ffmpeg_resize file1.mp4 25 # resize `file1.mp4` to 25 MB
ffmpeg_resize file2.mp4 64 # resize `file2.mp4` to 64 MB
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3631 次 |
最近记录: |