使用MIDIUtil保存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的音符事件时,找不到对应的数据条目。核心诱因包括:
- 无效的音符时长:当AI生成的时间间隔过小时,转换为MIDI ticks后可能得到0或负数,导致音符的结束时间早于或等于开始时间,打乱了库的事件处理顺序。
- 时间累加逻辑错误:当前代码先累加
time再添加音符,第一个音符的起始时间是duration而非0,后续音符的时间轴也会整体偏移,可能引发事件顺序冲突。 - 非法音高:如果计算出的
pitch超出MIDI合法范围(0-127),也可能导致库处理异常。
修复方案
- 过滤无效时长:添加判断跳过时长为0或负数的音符:
# 转换时长后增加判断 duration = int(note[2] / (1000 / (tempo / 60 * ticks_per_quarter_note))) if duration <= 0: continue # 跳过无效时长的音符
- 修正时间累加逻辑:先添加音符再累加时间,确保第一个音符从时间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
- 校验音高范围:确保生成的音高在MIDI合法区间内,避免非法值导致的异常。
内容的提问来源于stack exchange,提问作者Maxim Mashkov

