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

使用AudioSegment合并大MP3文件时触发MemoryError(内存充足)

解决Pydub合并大MP3文件触发MemoryError的问题

我明白你遇到的困扰——小文件合并没问题,大文件就内存溢出,这其实是Pydub的工作机制导致的:Pydub会把整个音频文件解码成未压缩的PCM格式加载到内存中,而MP3压缩后的体积和解码后的PCM体积差距极大(比如128kbps的MP3,解码后体积大概是原文件的10倍以上),大文件很容易就把内存撑爆了。

下面给你几个实用的解决方案,按推荐程度排序:

方案一:改用FFmpeg流式合并(最推荐)

Pydub底层依赖FFmpeg,不如直接调用FFmpeg的原生concat功能,它是流式处理,完全不需要把整个文件加载到内存里,效率和内存占用都友好很多。

修改后的代码示例

首先确保你已经安装了FFmpeg,并将其添加到系统PATH中(或者在代码里指定FFmpeg的完整路径):

from pydub import AudioSegment
import eyed3
import os
import psutil
import subprocess

def make_files(path_to_files, audiofiles):
    pre_sermon_path = "pre_sermon.mp3"
    # 确保输出目录存在
    os.makedirs('combined', exist_ok=True)
    
    for file_name in audiofiles:
        sermon_path = os.path.join(path_to_files, file_name)
        output_path = os.path.join('combined', file_name)
        
        # 1. 创建临时的合并列表文件(FFmpeg concat需要)
        temp_concat_file = "temp_concat_list.txt"
        with open(temp_concat_file, 'w', encoding='utf-8') as f:
            # 写入要合并的两个文件路径(必须是绝对路径,避免FFmpeg报错)
            f.write(f"file '{os.path.abspath(pre_sermon_path)}'\n")
            f.write(f"file '{os.path.abspath(sermon_path)}'\n")
        
        # 2. 获取原音频的标签信息
        audio_metadata = {}
        try:
            audiofile = eyed3.load(sermon_path)
            if audiofile.tag:
                audio_metadata['title'] = audiofile.tag.title or ""
                audio_metadata['artist'] = audiofile.tag.artist or ""
                audio_metadata['album'] = audiofile.tag.album or ""
                audio_metadata['comment'] = audiofile.tag.comments[0].text if audiofile.tag.comments else ""
        except Exception as e:
            print(f"读取{file_name}标签失败:{e}")
        
        # 3. 构建FFmpeg命令:合并音频+设置标签+指定比特率
        ffmpeg_cmd = [
            'ffmpeg',
            '-f', 'concat',          # 使用concat demuxer模式
            '-safe', '0',            # 允许使用绝对路径
            '-i', temp_concat_file,  # 输入合并列表
            '-b:a', '128k',          # 设置输出比特率
            '-y',                    # 覆盖已存在的输出文件
        ]
        
        # 添加元数据参数
        for key, value in audio_metadata.items():
            ffmpeg_cmd.extend(['-metadata', f'{key}={value}'])
        
        # 添加输出路径
        ffmpeg_cmd.append(output_path)
        
        # 4. 执行FFmpeg命令
        try:
            subprocess.run(ffmpeg_cmd, check=True, capture_output=True, text=True)
            print(f"✅ 成功合并:{file_name}")
        except subprocess.CalledProcessError as e:
            print(f"❌ 合并{file_name}失败:{e.stderr}")
        finally:
            # 删除临时文件
            if os.path.exists(temp_concat_file):
                os.remove(temp_concat_file)

# 原有逻辑保持不变
general_path = 'C:\\projects\\python\\files\\mp3\\sermons\\'
files = set(os.listdir('sermons/'))
combined_files = set(os.listdir('combined/'))
difference = {filename: f"{os.stat(os.path.join(general_path, filename)).st_size/1000000:.2f} MB" 
              for filename in (files - combined_files)}

print("当前内存状态:", psutil.virtual_memory())
print("待处理文件:", difference)
make_files('sermons/', difference.keys())

为什么这个方案更好?

  • FFmpeg是专业的音视频处理工具,流式处理不会加载整个文件到内存,大文件也能轻松处理
  • 处理速度比Pydub更快,因为不需要解码再重新编码(如果原文件编码参数一致,甚至可以直接拷贝流,不过这里因为要统一比特率还是会重新编码)

方案二:优化Pydub的内存使用(不推荐,仅作参考)

如果一定要用Pydub,可以尝试分块读取大文件,但实现起来比较麻烦,而且内存优化效果有限。核心思路是把大文件切成小块,合并后再逐块拼接:

def load_large_mp3(path, chunk_size=60*1000):  # 每次加载60秒的块
    audio = AudioSegment.empty()
    start = 0
    while True:
        try:
            chunk = AudioSegment.from_mp3(path)[start:start+chunk_size]
            if len(chunk) == 0:
                break
            audio += chunk
            start += chunk_size
            gc.collect()  # 每加载一块就回收内存
        except Exception as e:
            print(f"加载块失败:{e}")
            break
    return audio

然后在make_files里用这个函数替代AudioSegment.from_mp3,但这个方法依然会占用不少内存,只是比直接加载整个文件好一点,还是不如FFmpeg方案靠谱。

方案三:升级Python版本(辅助优化)

你使用的Python3.6.2已经比较老旧了,新版本的Python(比如3.8+)在内存管理和垃圾回收上有不少优化,升级后可能会缓解内存问题,但这只能作为辅助方案,不能从根本上解决大文件加载的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:21:46