ffmpeg视频压缩/特定文件大小

jes*_*s88 11 ffmpeg

目前我有80mb电影,我想用ffmpeg转换成大约10mb或15mb.我知道会有质量损失,但他们需要有声音.有没有办法指定文件大小或更高的压缩比我以前做的

ffmpeg -i movie.mp4 -b 2255k -s 1280x720 movie.hd.ogv
Run Code Online (Sandbox Code Playgroud)

它们目前约为25mb

aer*_*tal 22

如果您要定位某个输出文件大小,最好的方法是使用H.264双通道编码.

这里有一个很好的例子,但复制粘贴太大了:https: //trac.ffmpeg.org/wiki/Encode/H.264

您使用计算目标比特率bitrate = file size / duration并启动ffmpeg两次:一次分析媒体,第二次执行实际编码:

ffmpeg -y -i input -c:v libx264 -preset medium -b:v 555k -pass 1 -c:a libfdk_aac -b:a 128k -f mp4 /dev/null && \
ffmpeg -i input -c:v libx264 -preset medium -b:v 555k -pass 2 -c:a libfdk_aac -b:a 128k output.mp4
Run Code Online (Sandbox Code Playgroud)

编辑:H.265(HEVC)在压缩方面甚至更好(在某些情况下为H.264大小的50%),但支持尚未普及,因此现在坚持使用H.264.

  • 在您的计算中,文件大小和持续时间的单位是多少? (2认同)
  • @DrewChapin千比特/秒 (2认同)

Mar*_*nar 14

灵感来自 Hashbrown 的回答。此版本保持原始音频质量,并调整为目标大小。

用法

./script original_video.mp4 size

大小 = 以 MB 为单位的整数

脚本

#!/bin/bash

target_video_size_MB="$2"
origin_duration_s=$(ffprobe -v error -show_streams -select_streams a "$1" | grep -Po "(?<=^duration\=)\d*\.\d*")
origin_audio_bitrate_kbit_s=$(ffprobe -v error -pretty -show_streams -select_streams a "$1" | grep -Po "(?<=^bit_rate\=)\d*\.\d*")
target_audio_bitrate_kbit_s=$origin_audio_bitrate_kbit_s # TODO for now, make audio bitrate the same
target_video_bitrate_kbit_s=$(\
    awk \
    -v size="$target_video_size_MB" \
    -v duration="$origin_duration_s" \
    -v audio_rate="$target_audio_bitrate_kbit_s" \
    'BEGIN { print  ( ( size * 8192.0 ) / ( 1.048576 * duration ) - audio_rate ) }')

ffmpeg \
    -y \
    -i "$1" \
    -c:v libx264 \
    -b:v "$target_video_bitrate_kbit_s"k \
    -pass 1 \
    -an \
    -f mp4 \
    /dev/null \
&& \
ffmpeg \
    -i "$1" \
    -c:v libx264 \
    -b:v "$target_video_bitrate_kbit_s"k \
    -pass 2 \
    -c:a aac \
    -b:a "$target_audio_bitrate_kbit_s"k \
    "${1%.*}-$2mB.mp4"
Run Code Online (Sandbox Code Playgroud)

待办事项/愿望清单

  1. 如果目标大小小于可能的大小,则中止(假设用户要求的大小小于音频流大小等)
  2. 警告目标大小是否会导致视频比特率严重降低

笔记

  • 我试图避免bc作为计算器并选择awk(不确定这是否很酷,但无论如何)
  • 我的视频收到“输出中的非单调 DTS”警告 - 如何解决?
  • 如果尝试将其移植到 Windows 脚本:用户应使用NUL代替/dev/null^代替\.

来源

Hashbrown 的回答(这里)/sf/answers/4068594141/

二通方法https://trac.ffmpeg.org/wiki/Encode/H.264#twopass

  • 如果文件路径包含空格,则应在第 4 行和第 5 行引用“$1”。与此相关的是,“编辑必须至少有 6 个字符”对于编程网站来说是一条愚蠢的规则。 (5认同)
  • 使用 `origin_duration_s=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$1")` 消除 `grep`。请注意,“origin_audio_bitrate_kbit_s”不适用于所有格式,尤其是 Matroska (mkv) 输入。但你也可以从中删除`grep`:`origin_audio_bitrate_kbit_s=$(ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate -of csv=p=0 "$1")` (4认同)
  • 它不需要是一个整数,我没有运行你的,但我原来的需要“7.5”,所以我认为你的可能/可以。这很方便,因为算法似乎超出了范围(8 生成了一个 8.5mB 的文件,discord 不喜欢这种文件,但 7.8 非常准确,不会下降到 7-flat) (2认同)

Has*_*own 6

这是一种使用 bash 脚本自动执行此操作的方法
只需调用./script.sh file.mp4 15for15mB

bitrate="$(awk "BEGIN {print int($2 * 1024 * 1024 * 8 / $(ffprobe \
    -v error \
    -show_entries format=duration \
    -of default=noprint_wrappers=1:nokey=1 \
    "$1" \
) / 1000)}")k"
ffmpeg \
    -y \
    -i "$1" \
    -c:v libx264 \
    -preset medium \
    -b:v $bitrate \
    -pass 1 \
    -an \
    -f mp4 \
    /dev/null \
&& \
ffmpeg \
    -i "$1" \
    -c:v libx264 \
    -preset medium \
    -b:v $bitrate \
    -pass 2 \
    -an \
    "${1%.*}-$2mB.mp4"
Run Code Online (Sandbox Code Playgroud)

注意我正在切断音频

  • 好的。解决方案是删除带有“-an”的行 (2认同)