You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenCV逐帧处理视频并保留音频,或降低内存占用?

大视频逐帧处理并保留音频的解决方案

问题背景

用OpenCV逐帧读取大视频、处理后写入新文件的方式,能避免将整个视频加载到内存,但无法保留音频。事后用MoviePy添加音频时,因需要重新编码完整视频,速度极慢,相关代码如下:

# OpenCV逐帧处理逻辑
success, img = vidObj.read()
img = processImg(img)
vidWriter.write(img)  

# MoviePy事后添加音频的代码
def addAudio(audioSource, videoSource, savePath):
    source_audio = AudioFileClip(audioSource)
    target_video = VideoFileClip(videoSource)
    target_video = target_video.set_audio(source_audio)
    target_video.write_videofile(savePath, audio_codec='aac')  

可行解决方案

1. 用PyAV实现逐帧处理视频+直接复制音频流

PyAV基于FFmpeg,支持对流式音视频进行处理,能在逐帧处理视频的同时,直接复制原视频的音频流,无需重新编码音频,既节省内存又保证速度。

示例代码:

import av

def process_video_with_audio(input_path, output_path, process_func):
    # 打开输入视频容器
    input_container = av.open(input_path)
    # 创建输出视频容器
    output_container = av.open(output_path, 'w')

    # 初始化音频输出流(直接复用原音频参数)
    audio_out_stream = None
    for stream in input_container.streams:
        if stream.type == 'audio':
            audio_out_stream = output_container.add_stream(template=stream)
            audio_out_stream.codec_context.codec = None  # 标记为直接复制

    # 逐帧处理视频并写入
    for stream in input_container.streams:
        if stream.type == 'video':
            video_out_stream = output_container.add_stream(template=stream)
            for frame in input_container.decode(stream):
                # 转换为OpenCV兼容的numpy数组
                img = frame.to_ndarray(format='bgr24')
                # 执行自定义帧处理
                processed_img = process_func(img)
                # 转回AVFrame并保留时间戳(保证音视频同步)
                processed_frame = av.VideoFrame.from_ndarray(processed_img, format='bgr24')
                processed_frame.pts = frame.pts
                # 编码写入输出容器
                for packet in video_out_stream.encode(processed_frame):
                    output_container.mux(packet)
            # 结束视频流编码
            for packet in video_out_stream.encode():
                output_container.mux(packet)

    # 复制原音频流数据包到输出容器
    if audio_out_stream:
        for stream in input_container.streams:
            if stream.type == 'audio':
                for packet in input_container.demux(stream):
                    packet.stream = audio_out_stream
                    output_container.mux(packet)

    # 关闭容器
    input_container.close()
    output_container.close()

# 调用示例:传入自定义的processImg处理函数
process_video_with_audio('input.mp4', 'output.mp4', processImg)

2. 用FFmpeg命令行快速合并音频与处理后的视频

如果已经用OpenCV处理完无音频的视频文件,可以直接用FFmpeg命令行不重新编码视频,仅将原视频的音频复制到处理后的视频中,速度极快:

ffmpeg -i processed_video.mp4 -i original_video.mp4 -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 final_output.mp4

参数说明:

  • -c:v copy:直接复制处理后的视频流,跳过重新编码
  • -c:a aac:指定音频编码为AAC(若原音频编码兼容,可替换为copy进一步提速)
  • -map 0:v:0:取第一个输入文件的视频流
  • -map 1:a:0:取第二个输入文件的音频流

核心优势

  • 两种方案都无需将整个视频加载到内存,适配大文件处理场景
  • 音频流直接复制或复用原编码,彻底避免了MoviePy重新编码全视频的耗时问题

内容的提问来源于stack exchange,提问作者Frobot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 18:57:36