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

使用MIDIUtil保存AI生成的MIDI文件时出现KeyError错误求助

问题:AI生成无规律时间间隔的音符序列保存MIDI时触发KeyError错误

我加载了一个包含[音符、八度、与上一音符的时间间隔]的数组,序列由AI生成,时间间隔无固定规律。尝试保存为MIDI文件时失败并触发错误,想确认是否是时间间隔无规律导致的问题?

错误回溯信息

Error:Traceback (most recent call last):
File "C:\Users\user\Desktop\MusicGen\outputs\get_midi.py", line 44, in
midi_file.writeFile(output_file)
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\midiutil\MidiFile.py", line 1637, in writeFile
self.close()
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\midiutil\MidiFile.py", line 1688, in close
self.tracks[i].closeTrack()
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\midiutil\MidiFile.py", line 826, in closeTrack
self.processEventList()
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\midiutil\MidiFile.py", line 789, in processEventList
self.deInterleaveNotes()
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\site-packages\midiutil\MidiFile.py", line 885, in deInterleaveNotes
if len(stack[noteeventkey]) > 1:
KeyError: '50'
exception: '50' None

相关代码

import pickle
from midiutil import MIDIFile

out = pickle.load(open("generated_sequence", "rb"))

ticks_per_quarter_note = 220  
track_number = 0
channel_number = 0
tempo = 150

notes_array = [[i[0]%12, i[0]//12, i[1]] for i in out]

# Create a MIDIFile object
midi_file = MIDIFile(numTracks=1)
midi_file.addTrackName(track_number, 0, "Track 0")
midi_file.addTempo(track_number, 0, tempo)

# Loop through the notes and add them to the MIDI file
time = 0
for note in notes_array:
    
    # Calculate the note's pitch
    pitch = note[0] + (note[1] * 12)
    
    # Convert the note's duration from milliseconds to ticks
    duration = int(note[2] / (1000 / (tempo / 60 * ticks_per_quarter_note)))

    # Calculate the note's position in time
    time += duration
    # Add the note to the MIDI file
    midi_file.addNote(
        track_number,
        channel_number,
        pitch,
        time,
        duration,
        100  # you can adjust the velocity (volume) here
    )

# Save the MIDI file
with open("my_midi_file.mid", "wb") as output_file:
    midi_file.writeFile(output_file)

解答

这个错误不是时间间隔无规律导致的,问题出在midiutil库处理音符事件的逻辑以及你的代码实现细节上。

错误原因分析

KeyError: '50'说明库在处理音高为50的音符事件时,找不到对应的数据条目。核心诱因包括:

  1. 无效的音符时长:当AI生成的时间间隔过小时,转换为MIDI ticks后可能得到0或负数,导致音符的结束时间早于或等于开始时间,打乱了库的事件处理顺序。
  2. 时间累加逻辑错误:当前代码先累加time再添加音符,第一个音符的起始时间是duration而非0,后续音符的时间轴也会整体偏移,可能引发事件顺序冲突。
  3. 非法音高:如果计算出的pitch超出MIDI合法范围(0-127),也可能导致库处理异常。

修复方案

  1. 过滤无效时长:添加判断跳过时长为0或负数的音符:
# 转换时长后增加判断
duration = int(note[2] / (1000 / (tempo / 60 * ticks_per_quarter_note)))
if duration <= 0:
    continue  # 跳过无效时长的音符
  1. 修正时间累加逻辑:先添加音符再累加时间,确保第一个音符从时间0开始,后续音符的起始时间符合“与上一音符的时间间隔”的定义:
time = 0
for note in notes_array:
    # 计算pitch和duration
    pitch = note[0] + (note[1] * 12)
    duration = int(note[2] / (1000 / (tempo / 60 * ticks_per_quarter_note)))
    
    if duration <= 0 or not (0 <= pitch <= 127):
        continue
    
    # 先添加音符,再累加时间
    midi_file.addNote(
        track_number,
        channel_number,
        pitch,
        time,
        duration,
        100
    )
    time += duration
  1. 校验音高范围:确保生成的音高在MIDI合法区间内,避免非法值导致的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:47:49