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

武状元*_*武状元 11 python video-compression

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

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

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

武状元*_*武状元 21

使用Python和FFmpeg压缩视频文件

工具

FFmpeg是一个强大的视频编辑工具。为此,有一个名为ffmpeg-pythonAPI 参考)的很棒的 Python 绑定。首先,pip install ffmpeg-python安装FFmpeg

脚步

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

代码

以下是示例代码。如果需要,请根据您的情况更改压缩算法。为了方便后续,我隐藏了边界条件的代码。我使用的代码位于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 input.mp4 to 50MB and save as output.mp4
compress_video('input.mp4', 'output.mp4', 50 * 1000)
Run Code Online (Sandbox Code Playgroud)

笔记

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

  2. ffmpeg.output()您可以通过仅保留第二个而不带参数来禁用双遍功能'pass': 2

  3. 如果视频比特率<1000,则会抛出异常Bitrate is extremely low

  4. 我建议的最大最小文件大小是:

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