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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:04:55