如何通过 Python 将视频压缩到目标大小?

How to compress video to target size by Python?

我正在通过 Python 程序将文本和视频上传到网站。该站点表示他们只接收最大 50 MB 的视频文件。否则,他们将拒绝视频和其他相关信息。

为确保我可以连续发送视频,我想在发送前将其压缩到目标大小(例如 50 MB)。因为没有质量损失是不可能的,所以视频或音频中有适度的清晰度损失是可以的。

在Python中有什么优雅的方法可以达到这个目的吗?谢谢!

我以前用过MoviePy,效果不错。 另一种选择(不是最安全的)可能是 运行 FFMpeg 作为外部进程来压缩或调整媒体文件的大小。

通过Python和FFmpeg

压缩视频文件

工具

FFmpeg is a powerful tool for video editing. And there is a great Python binding named ffmpeg-python (API Reference) for this. Firstly, pip install ffmpeg-python and install FFmpeg.

步骤

通过函数ffmpeg.probe()探测视频配置,获取时长、音视频码率等。并根据我们已有的计算出目标文件的码率。然后,通过ffmpeg.input()ffmpeg.output()构造命令。终于,运行啦。

代码

以下是示例代码。如果需要,可以根据您的情况更改压缩算法。为了简单follow-up,我隐藏了边界条件的代码。我使用的代码在 GitHub Gist 中。欢迎任何错误报告!

import os, ffmpeg
def compress_video(video_full_path, output_file_name, target_size):
    # Reference: https://en.wikipedia.org/wiki/Bit_rate#Encoding_bit_rate
    min_audio_bitrate = 32000
    max_audio_bitrate = 256000

    probe = ffmpeg.probe(video_full_path)
    # Video duration, in s.
    duration = float(probe['format']['duration'])
    # Audio bitrate, in bps.
    audio_bitrate = float(next((s for s in probe['streams'] if s['codec_type'] == 'audio'), None)['bit_rate'])
    # Target total bitrate, in bps.
    target_total_bitrate = (target_size * 1024 * 8) / (1.073741824 * duration)

    # Target audio bitrate, in bps
    if 10 * audio_bitrate > target_total_bitrate:
        audio_bitrate = target_total_bitrate / 10
        if audio_bitrate < min_audio_bitrate < target_total_bitrate:
            audio_bitrate = min_audio_bitrate
        elif audio_bitrate > max_audio_bitrate:
            audio_bitrate = max_audio_bitrate
    # Target video bitrate, in bps.
    video_bitrate = target_total_bitrate - audio_bitrate

    i = ffmpeg.input(video_full_path)
    ffmpeg.output(i, os.devnull,
                  **{'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 1, 'f': 'mp4'}
                  ).overwrite_output().run()
    ffmpeg.output(i, output_file_name,
                  **{'c:v': 'libx264', 'b:v': video_bitrate, 'pass': 2, 'c:a': 'aac', 'b:a': audio_bitrate}
                  ).overwrite_output().run()

compress_video('input.mp4', 'output.mp4', 50 * 1000)

备注

  1. 不要浪费你的时间!压缩前判断文件大小

  2. 您可以通过仅保留第二个 ffmpeg.output() 不带参数 'pass': 2.

    来禁用 two-pass 功能
  3. 如果视频码率<1000,会抛出异常Bitrate is extremely low

  4. 我推荐的最大最小文件大小是:

# Best min size, in kB.
best_min_size = (32000 + 100000) * (1.073741824 * duration) / (8 * 1024)
  1. 如果您指定一个非常小的目标文件大小,生成的文件大小可能会超过它。大多数时候,这不会发生。