Python调用pydub读取MP3报错:系统找不到指定文件
问题描述
我正在开发一款节奏游戏,核心功能是导入歌曲后按固定间隔(比如5秒)检测该时间段内音量最高的音符,在对应时间点生成可点击按钮。现在卡在音频分析功能上,遇到了无法解决的错误。
我的代码
import pyautogui import win32api, win32con import threading import time from time import sleep import keyboard import random from ast import Str import pygame from pygame import * import sys import math import numpy import matplotlib import matplotlib.pyplot import pydub from pydub import AudioSegment song = AudioSegment.from_mp3(r"C:\Users\William Cunningham\Desktop\Stuff\Visual Studio\Games\KeyClickGame\AlienWaifus.mp3") SEGMENT_MS = 50 volume = [segment.dBFS for segment in song[::SEGMENT_MS]] x_axis = numpy.arrange(len(volume)) * (SEGMENT_MS / 1000) matplotlib.pyplot.plot(x_axis, volume) matplotlib.pyplot.show
报错信息
C:\Users\William Cunningham\AppData\Local\Programs\Python\Python310\lib\site-packages\pydub\utils.py:170: RuntimeWarning: Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work warn("Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work", RuntimeWarning) C:\Users\William Cunningham\AppData\Local\Programs\Python\Python310\lib\site-packages\pydub\utils.py:198: RuntimeWarning: Couldn't find ffprobe or avprobe - defaulting to ffprobe, but may not work warn("Couldn't find ffprobe or avprobe - defaulting to ffprobe, but may not work", RuntimeWarning) Traceback (most recent call last): File "c:\Users\William Cunningham\Desktop\Stuff\Visual Studio\Games\KeyClickGame\AudioStuff.py", line 33, in <module> song = AudioSegment.from_mp3(file=r"C:\Users\William Cunningham\Desktop\Stuff\Visual Studio\Games\KeyClickGame\AlienWaifus.mp3") File "C:\Users\William Cunningham\AppData\Local\Programs\Python\Python310\lib\site-packages\pydub\audio_segment.py", line 796, in from_mp3 return cls.from_file(file, 'mp3', parameters=parameters) File "C:\Users\William Cunningham\AppData\Local\Programs\Python\Python310\lib\site-packages\pydub\audio_segment.py", line 728, in from_file info = mediainfo_json(orig_file, read_ahead_limit=read_ahead_limit) File "C:\Users\William Cunningham\AppData\Local\Programs\Python\Python310\lib\site-packages\pydub\utils.py", line 274, in mediainfo_json res = Popen(command, stdin=stdin_parameter, stdout=PIPE, stderr=PIPE) File "C:\Users\William Cunningham\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 969, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "C:\Users\William Cunningham\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1438, in _execute_child hp, ht, pid, tid = _winapi.CreateProcess(executable, args, FileNotFoundError: [WinError 2] The system cannot find the file specified
已尝试的方法
- 修改MP3文件路径写法(添加
file参数、去掉r前缀、改用相对路径) - 改用
from_file方法加载音频 - 先打开文件对象再传入加载函数
需求
编写代码实现:
- 读取MP3文件
- 按固定间隔(比如10秒)检测该时间段内音量最高的时间点(以分贝为单位)
- 生成音量随时间变化的图表
优先通过代码解决,尽量不额外安装软件。
解决方案
错误原因解析
报错里的FileNotFoundError不是找不到你的MP3文件,而是pydub依赖的ffmpeg/ffprobe工具不存在。pydub本身不处理音频解码,需要调用外部的ffmpeg工具来解析MP3文件,你的系统里没装这个工具,所以触发了错误。
替代方案:用pygame处理音频(无需额外装软件)
你已经导入了pygame,它可以直接解码MP3,不需要依赖外部工具,刚好符合你的需求。下面是完整的实现代码:
import pygame import numpy as np import matplotlib.pyplot as plt # 初始化pygame音频模块 pygame.mixer.init() # 加载MP3文件 audio_path = r"C:\Users\William Cunningham\Desktop\Stuff\Visual Studio\Games\KeyClickGame\AlienWaifus.mp3" audio = pygame.mixer.Sound(audio_path) # 获取音频参数 sample_rate = audio.get_frequency() channels = audio.get_num_channels() total_samples = int(audio.get_length() * sample_rate) samples = audio.get_raw() # 将原始音频数据转换为numpy数组(单声道处理) if channels == 2: # 双声道转单声道,取平均值 sample_array = np.frombuffer(samples, dtype=np.int16).reshape(-1, 2).mean(axis=1) else: sample_array = np.frombuffer(samples, dtype=np.int16) # 计算分贝:dB = 20 * log10(abs(sample) / max_sample) max_sample = np.iinfo(np.int16).max db_values = 20 * np.log10(np.abs(sample_array) / max_sample) # 处理0值避免log报错 db_values[db_values == -np.inf] = -90 # 把无限小的分贝值设为-90 # 设置分段间隔(比如10秒,单位:秒) segment_duration = 10 segment_samples = segment_duration * sample_rate # 遍历每个分段,找音量最高的时间点 peaks = [] for i in range(0, len(sample_array), segment_samples): segment_end = min(i + segment_samples, len(sample_array)) segment_db = db_values[i:segment_end] # 找到当前分段内分贝最高的索引 peak_idx_in_segment = np.argmax(segment_db) peak_time = (i + peak_idx_in_segment) / sample_rate peak_db = segment_db[peak_idx_in_segment] peaks.append((peak_time, peak_db)) print(f"分段 {i//segment_samples + 1}:最高音量时间点 {peak_time:.2f}秒,分贝值 {peak_db:.2f}dB") # 生成音量随时间变化的图表 time_axis = np.linspace(0, audio.get_length(), len(db_values)) plt.figure(figsize=(12, 6)) plt.plot(time_axis, db_values, alpha=0.5, label='实时音量') # 标记每个分段的峰值点 peak_times, peak_dbs = zip(*peaks) plt.scatter(peak_times, peak_dbs, color='red', label='分段峰值') plt.xlabel('时间(秒)') plt.ylabel('音量(dB)') plt.title('音频音量随时间变化') plt.legend() plt.show()
代码说明
- 音频加载:用pygame的
Sound类加载MP3,直接获取原始采样数据 - 分贝计算:将原始采样值转换为分贝值,处理了0值避免对数计算报错
- 分段检测峰值:按指定间隔(10秒)切分音频,找到每个分段内分贝最高的时间点
- 图表生成:用matplotlib绘制整体音量曲线,并标记每个分段的峰值点
注意事项
- 如果你的音频是其他格式,pygame也支持大部分常见音频格式(如WAV、OGG)
- 代码里默认把双声道转成单声道处理,如果你需要保留双声道,可以分别计算每个声道的峰值
- 运行前确保pygame已经安装:
pip install pygame(你应该已经装了,因为之前的代码里导入了)
内容的提问来源于stack exchange,提问作者WilliamC
相关产品推荐
相关产品推荐

