使用 pygame 从流中播放 MIDI 文件

Using pygame to play a MIDI file from stream

我想做的是:创建一个 MIDI 文件,但只在内存中,并将其输入 pygame.mixer.music.load()。这是我一直在尝试的(我正在使用 here 的 MidiFile):

import pygame.mixer
import MidiFile3
import io

pygame.mixer.init()

midi = MidiFile3.MIDIFile(1) # midi file with one track
midi.addTrackName(0,0,"Track 1") #Track Name on track 0, position 0
midi.addTempo(0,0,120) #Tempo to 120 bpm on track 0, position 0

for i in range(8):
    midi.addNote(0,0,60,i,1,100) #add 8 c1-notes to the track

bytestream = io.BytesIO()
midi.writeFile(bytestream)
pygame.mixer.music.load(bytestream.getvalue())

这里我收到错误信息

pygame.error: File path 'MThd' contains null characters

当我做的时候

bytestream = open('file.mid','wb')
midi.writeFile(bytestream)
bytestream.close()
pygame.mixer.music.load('file.mid')

它按预期工作。

当然,我知道包含文件名的字符串和包含文件内容的字节串是有区别的。但我发现这个 Post on Daniweb 使用字节流,这个例子对我有用。

我只是想不出如何让我的示例起作用。

music.load() 函数需要文件名或文件对象。

bytestream.getvalue()是字节流的内容,貌似是文件名

您必须使用文件/BytesIO 对象本身:

pygame.mixer.music.load(bytestream)

我修复了如下问题:

bytestream = io.BytesIO()
midi.writeFile(bytestream)
temp = io.BytesIO(bytestream.getvalue())
pygame.mixer.music.load(temp)

看起来,writeFile() 操作以某种方式使 BytesIO 对象对 pygame.mixer.music.load() 方法无效。通过使用正确创建的字节流再次使用 BytesIO 的构造函数,我们神奇地得到了一个有效的字节流,我们可以传递给 pygame.mixer.music.load().

接受的答案虽然有效,但并不是正确的解决方案。写入字节流后,您需要做的就是将指针重置为开头。正确的代码(部分)如下:

bytestream = io.BytesIO()
midi.writeFile(bytestream)
bytestream.seek(0)
pygame.mixer.music.load(bytestream)

其实我也回答过类似的问题here