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

基于Python mido库获取MIDI文件音符起止时间的相关问题

问题1解答

你对这两条消息的时间理解是错误的:

  • mido中消息的time字段是delta time,代表当前消息与上一条消息的时间间隔,单位为ticks(MIDI时钟滴答数),不是毫秒。
  • 你给出的两条消息的实际含义是:上一条事件执行完成后,间隔1个tick触发64号音符按下;再间隔119个tick触发64号音符释放(velocity为0的note_on消息是MIDI标准中约定的音符停止事件,等价于note_off)。
  • 该音符的起始时间是当前这条note_on之前所有消息的time累加得到的总ticks值,结束时间是起始时间 + 119 ticks。

更优的获取音符起止时间的方案:
不要将MidiFile对象转成字符串导出到文本再解析,直接遍历mido读取到的轨道对象即可,还可以直接调用库内置方法转换为实际秒数,示例代码如下:

from mido import MidiFile, tick2second

mid = MidiFile('./midi/piano/WA_Mozart_Marche_Turque_Turkish_March_fingered.mid', clip=True)
ticks_per_beat = mid.ticks_per_beat
current_tempo = 500000 # MIDI默认初始速度是500000微秒/四分音符,即120BPM
current_time = 0 # 累计总ticks
active_notes = {} # 存储已按下未释放的音符,key为note值,value为起始ticks
note_list = [] # 存储最终的音符信息:[note编号, 起始时间秒, 结束时间秒, 力度]

for track in mid.tracks:
    for msg in track:
        # 先累加当前delta time到总时间
        current_time += msg.time
        # 处理速度变化元消息
        if msg.type == 'set_tempo':
            current_tempo = msg.tempo
        # 处理音符按下事件
        elif msg.type == 'note_on' and msg.velocity > 0:
            active_notes[msg.note] = current_time
        # 处理音符释放事件
        elif (msg.type == 'note_off') or (msg.type == 'note_on' and msg.velocity == 0):
            if msg.note in active_notes:
                start_tick = active_notes.pop(msg.note)
                # 转成实际秒数
                start_sec = tick2second(start_tick, ticks_per_beat, current_tempo)
                end_sec = tick2second(current_time, ticks_per_beat, current_tempo)
                note_list.append([msg.note, start_sec, end_sec, msg.velocity])

这个方案可以直接得到每个音符对应的实际秒级起止时间,避免手动解析字符串出错。

问题2解答

有两个核心原因:

  1. 你看到的time是单条消息和上一条消息的间隔,不是从曲目开头算起的总时间,所有消息的time累加得到的总ticks数才对应整个曲目的时间长度。
  2. ticks是MIDI的相对时间单位,需要结合MIDI文件的ticks_per_beat(每个四分音符对应的ticks数,你提供的文件里对应值为24)和实时速度(set_tempo消息定义的微秒每四分音符)才能转换为实际秒数。单条消息的间隔ticks数值本身就不会很大,累加后转换得到的总时长就和你在编辑器里看到的3分钟。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:15:04