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

使用Python的mido库无法读取MIDI文件正确速度信息如何解决?

解决MIDI文件正确速度读取问题

核心排查方向

MuseScore能识别正确速度,说明速度信息肯定在文件里,大概率是你没遍历到所有轨道的消息,或者忽略了非标准的速度控制方式。以下是具体的Python实现方案:


1. 遍历所有轨道的set_tempo元消息

很多MIDI文件会把速度信息放在非首轨道(比如专门的标记轨道),或者存在多个速度变更事件。用mido遍历所有轨道的所有消息,筛选出所有set_tempo消息:

import mido

def get_actual_tempo(midi_path):
    mid = mido.MidiFile(midi_path)
    default_tempo = 500000  # 对应120 BPM
    actual_tempo = None

    # 遍历所有轨道的所有消息
    for track in mid.tracks:
        for msg in track:
            if msg.type == 'set_tempo':
                if msg.tempo != default_tempo:
                    actual_tempo = msg.tempo
                    # 转成BPM输出
                    print(f"找到实际速度: {mido.tempo2bpm(actual_tempo)} BPM")
                    return actual_tempo
    # 如果所有set_tempo都是默认值,再确认一遍
    if not actual_tempo:
        for track in mid.tracks:
            for msg in track:
                if msg.type == 'set_tempo':
                    print(f"仅找到默认速度: {mido.tempo2bpm(msg.tempo)} BPM")
                    return msg.tempo
    return default_tempo

# 调用示例
get_actual_tempo("your_midi_file.mid")

2. 检查MIDI控制变更(CC)消息

部分MIDI文件会用控制号114的CC消息来调整速度(范围0-127,对应0-200%的基准速度),MuseScore会识别这类控制:

def check_cc_tempo(midi_path, base_bpm=120):
    mid = mido.MidiFile(midi_path)
    for track in mid.tracks:
        for msg in track:
            if msg.type == 'control_change' and msg.control == 114:
                speed_ratio = msg.value / 127
                actual_bpm = base_bpm * speed_ratio
                print(f"通过CC消息识别速度: {actual_bpm:.2f} BPM")
                return actual_bpm
    return None

# 调用示例
check_cc_tempo("your_midi_file.mid")

3. 极端情况:检查文本元消息

少数文件会把速度信息放在文本标记里(比如marker或text类型的元消息),可以额外排查:

def check_text_tempo(midi_path):
    mid = mido.MidiFile(midi_path)
    keyword = ["BPM", "速度"]
    for track in mid.tracks:
        for msg in track:
            if msg.type in ['text', 'marker']:
                for kw in keyword:
                    if kw in msg.text:
                        print(f"文本中找到速度相关信息: {msg.text}")
                        return msg.text
    return None

# 调用示例
check_text_tempo("your_midi_file.mid")

注意事项

  • ticks_per_beat是MIDI文件头的固定参数,不会随速度变化,你可以直接用mid.ticks_per_beat获取。
  • 如果以上方法都没找到,建议用十六进制编辑器查看MIDI文件的元数据段,重点找FF 51 03开头的字节(set_tempo消息的标识),后面的3个字节就是微秒每拍的数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 17:36:24