使用mido与pydub转换MIDI到MP3时遇「系统找不到指定文件」错误
问题:MIDI转MP3时出现「系统找不到指定文件」错误
我用music21生成MIDI文件,想转成浏览器能播放的MP3,用mido和pydub写了转换代码,虽然melody.mid和代码同路径,但运行时还是报文件找不到的错,最终想得到可播放的MP3。
我写的转换代码
import mido from pydub import AudioSegment def midi_to_mp3(midi_path, mp3_path): # Load MIDI file midi = mido.MidiFile(midi_path) # Create an empty list to store notes notes = [] for track in midi.tracks: # Iterate through MIDI messages in track for msg in track: # Check if message is a note on event if msg.type == 'note_on': # Add note (pitch, velocity, time) to notes list notes.append((msg.note, msg.velocity, msg.time)) tempo = 120 duration = 1000 segments = [] for note in notes: pitch, velocity, time = note # Calculate duration of note based on tempo and time note_duration = int(duration * (mido.tick2second(time, midi.ticks_per_beat, tempo) * 1000)) # Create audio segment for note segment = AudioSegment.silent(duration=note_duration) segments.append(segment) audio = sum(segments) audio.export(mp3_path, format="mp3") midi_to_mp3("melody.mid", "output.mp3")
完整报错信息
C:\Dipika\Study\musicrypt\env\Scripts\python.exe "C:/Program Files/JetBrains/PyCharm 2023.1.3/plugins/python/helpers/pydev/pydevd.py" --multiprocess --qt-support=auto --client 127.0.0.1 --port 56448 --file C:\Dipika\Study\musicrypt\musicrypt.py Connected to pydev debugger (build 231.9161.41) C:\Dipika\Study\musicrypt\env\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:\Dipika\Study\musicrypt\env\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:\Program Files\JetBrains\PyCharm 2023.1.3\plugins\python\helpers\pydev\pydevd.py", line 1496, in _exec pydev_imports.execfile(file, globals, locals) # execute the script ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\JetBrains\PyCharm 2023.1.3\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile exec(compile(contents+"\n", file, 'exec'), glob, loc) File "C:\Dipika\Study\musicrypt\musicrypt.py", line 70, in <module> convert_to_mp3('melody.mid', 'audio.mp3') File "C:\Dipika\Study\musicrypt\musicrypt.py", line 46, in convert_to_mp3 midi_audio = AudioSegment.from_file(midi_path, format="midi") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Dipika\Study\musicrypt\env\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:\Dipika\Study\musicrypt\env\Lib\site-packages\pydub\utils.py", line 274, in mediainfo_json res = Popen(command, stdin=stdin_parameter, stdout=PIPE, stderr=PIPE) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\subprocess.py", line 1026, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "C:\Users\Admin\AppData\Local\Programs\Python\Python312\Lib\subprocess.py", line 1538, in _execute_child hp, ht, pid, tid = _winapi.CreateProcess(executable, args, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\JetBrains\PyCharm 2023.1.3\plugins\python\helpers\pydev\_pydev_bundle\pydev_monkey.py", line 585, in new_CreateProcess return getattr(_subprocess, original_name)(app_name, patch_arg_str_win(cmd_line), *args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: [WinError 2] The system cannot find the file specified python-BaseException Process finished with exit code 1
解决方案
1. 先解决FFmpeg缺失问题
报错里的RuntimeWarning已经明确提示找不到ffmpeg/ffprobe,这是pydub处理音频的核心依赖,必须安装:
- 下载FFmpeg压缩包,解压到本地路径(比如
C:\ffmpeg) - 把
C:\ffmpeg\bin添加到系统的Path环境变量中 - 重启IDE或终端,确保环境变量生效
2. 修复代码逻辑问题
你当前的代码只是生成了静音片段,根本没有把MIDI音符转换成实际音频。推荐改用fluidsynth合成MIDI音频,再用pydub转MP3:
- 安装依赖:
pip install mido fluidsynth pydub
- 下载通用SoundFont文件(比如
GeneralUser GS.sf2),放到代码同目录 - 修改后的可用代码:
import mido from pydub import AudioSegment import fluidsynth import os def midi_to_mp3(midi_path, mp3_path, soundfont_path="GeneralUser GS.sf2"): # 检查文件是否存在 if not os.path.exists(midi_path): print(f"错误:找不到文件 {midi_path}") return if not os.path.exists(soundfont_path): print(f"错误:找不到SoundFont文件 {soundfont_path}") return # 初始化fluidsynth fs = fluidsynth.Synth() fs.start(driver="dsound") # Windows用dsound,Linux用alsa,Mac用coreaudio sfid = fs.sfload(soundfont_path) fs.program_select(0, sfid, 0, 0) # 加载MIDI文件并读取tempo midi = mido.MidiFile(midi_path) ticks_per_beat = midi.ticks_per_beat tempo = 500000 # 默认MIDI tempo for track in midi.tracks: for msg in track: if msg.type == 'set_tempo': tempo = msg.tempo break if tempo != 500000: break ticks_per_second = mido.tick2second(1, ticks_per_beat, tempo) ** -1 sample_rate = 44100 audio_data = [] current_time = 0 # 处理MIDI事件,生成音频 for track in midi.tracks: track_events = list(track) for idx, msg in enumerate(track_events): current_time += msg.time if msg.type == 'note_on' and msg.velocity > 0: # 查找对应note_off事件,计算音符持续时间 note_off_time = current_time for future_msg in track_events[idx+1:]: note_off_time += future_msg.time if future_msg.type in ('note_off', 'note_on') and future_msg.note == msg.note and future_msg.velocity == 0: break # 转换为采样数并生成音频 start_sample = int(current_time * ticks_per_second * sample_rate) end_sample = int(note_off_time * ticks_per_second * sample_rate) fs.noteon(0, msg.note, msg.velocity) samples = fs.get_samples(end_sample - start_sample) audio_data.append(samples) fs.noteoff(0, msg.note) # 合并音频并导出为MP3 if audio_data: audio_bytes = b''.join(audio_data) audio = AudioSegment( audio_bytes, frame_rate=sample_rate, sample_width=2, channels=2 ) audio.export(mp3_path, format="mp3") print(f"MP3文件已生成:{mp3_path}") else: print("错误:未从MIDI文件中读取到有效音符") fs.delete() # 调用函数,可替换为完整路径 midi_to_mp3("melody.mid", "output.mp3")
3. 确认文件路径正确性
如果还是提示找不到文件,在代码开头添加路径检查:
import os print("当前工作目录:", os.getcwd()) print("MIDI文件是否存在:", os.path.exists("melody.mid"))
如果输出False,就把MIDI文件的完整路径传入函数,比如"C:/Dipika/Study/musicrypt/melody.mid"
内容的提问来源于stack exchange,提问作者Dipika Sengupta
相关产品推荐
相关产品推荐

