【问题标题】:How to compress video to target size by Python?如何通过 Python 将视频压缩到目标大小?
【发布时间】:2020-10-19 15:47:29
【问题描述】:

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

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

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

【问题讨论】:

    标签: python video-compression


    【解决方案1】:

    通过 Python 和 FFmpeg 压缩视频文件

    工具

    FFmpeg 是一款强大的视频编辑工具。为此,有一个很棒的 Python 绑定,名为 ffmpeg-python (API Reference)。首先是pip install ffmpeg-pythoninstall 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_video('input.mp4', 'output.mp4', 50 * 1000)
    

    注意事项

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

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

    3. 如果视频码率Bitrate is extremely low。

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

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

    【讨论】:

    • 如何处理音频文件?
    • @MmBaguette 也许,这值得提出一个新问题。有2个解决方案。 1)通过ffmpeg将您的音频文件转换为视频,并直接使用这个sn-p。 2) 运行ffmpeg.output 时只通过audio_bitrate。喜欢ffmpeg.output(i, output_file_name, **{'b:a': audio_bitrate, 'f': 'mp3'}).overwrite_output().run()
    • 您好,即使在指定输入和输出视频文件的整个路径后,我仍然收到以下错误:` p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess. PIPE)文件“D:\Coding\Python\lib\subprocess.py”,第 854 行,在 init self._execute_child(args,可执行文件,preexec_fn,close_fds,文件“D:\Coding\Python \lib\subprocess.py", line 1307, in _execute_child hp, ht, pid, tid = _winapi.CreateProcess(executable, args, FileNotFoundError: [WinError 2] 系统找不到指定的文件`
    • @Dhruv-2676 你好像没有安装ffmpeg,是吗?
    • 我认为我下载正确,如果您有任何检查的想法,请告诉我...
    【解决方案2】:

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

    【讨论】:

    • 太棒了!我会试一试的。
    猜你喜欢
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多