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

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方法加载音频
  • 先打开文件对象再传入加载函数

需求

编写代码实现:

  1. 读取MP3文件
  2. 按固定间隔(比如10秒)检测该时间段内音量最高的时间点(以分贝为单位)
  3. 生成音量随时间变化的图表
    优先通过代码解决,尽量不额外安装软件。

解决方案

错误原因解析

报错里的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()

代码说明

  1. 音频加载:用pygame的Sound类加载MP3,直接获取原始采样数据
  2. 分贝计算:将原始采样值转换为分贝值,处理了0值避免对数计算报错
  3. 分段检测峰值:按指定间隔(10秒)切分音频,找到每个分段内分贝最高的时间点
  4. 图表生成:用matplotlib绘制整体音量曲线,并标记每个分段的峰值点

注意事项

  • 如果你的音频是其他格式,pygame也支持大部分常见音频格式(如WAV、OGG)
  • 代码里默认把双声道转成单声道处理,如果你需要保留双声道,可以分别计算每个声道的峰值
  • 运行前确保pygame已经安装:pip install pygame(你应该已经装了,因为之前的代码里导入了)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:20:21