如何在 Pyglet 中连续播放音乐(同时使用 tkinter)?

时间:2021-05-01 07:52:33

标签: python audio media pyglet

我正在尝试通过制作播放列表将一些音乐放入我的游戏中,当音乐结束时下一个音乐开始......并且在寻找解决方案数小时后我仍然找不到...... 我知道如何使用 next_source 播放一首音乐以及如何播放下一首音乐,但我不知道如何让它在音乐结束时自动播放。这就是我在这里的原因。 我发现许多网站/论坛都告诉您使用 on_eos,但我无法让它发挥作用。

player = pyglet.media.Player()
music1 = pyglet.media.load('somemusic.wav')
music2 = pyglet.media.load('someothermusic.wav')
player.queue(music1)
player.queue(music2)

#the part i'm struggling with (I've tried that)

player.on_eos = pyglet.media.Player.on_eos
@player.event
def on_eos():
    #some function
    print("on player eos")

player.push_handlers(on_eos)

#

player.play()

2 个答案:

答案 0 :(得分:1)

player = pyglet.media.Player()
music1 = 'somemusic.wav'
music2 = 'someothermusic.wav'
music = [music1, music2]

@player.event
def on_eos():
    print("[event] on_eos: end of file")

@player.event
def on_player_eos():
    print("[event] on_player_eos: end of queue")

media = []
for filename in music:
    print('load:', filename)
    item = pyglet.media.load(filename)
    media.append(item)

def create_queue():
    for item in media:
        print('queue:', item)
        player.queue(item)

def play():
    create_queue()
    player.play()

def update(event):
    root.update()

def on_close():
    clock.unschedule(update)
    root.destroy()  #edit:useless --> It even creates problems!
    pyglet.app.exit()  #this line does the work without the previous one

is_paused = False

root.protocol("WM_DELETE_WINDOW", on_close)

clock.schedule(update)

这给了我错误:TypeError: queue() missing 1 required positional argument: 'source' #edit: no more(已解决),问题出在其他地方。

播放按钮:

Button(StartPage, text="Play", command=play).pack()

注意:如果您像我一样将键绑定到函数(使用 tkinter)并且它们不再起作用,请使用 window.focus_force() 它将解决您的问题。

答案 1 :(得分:0)

它可以正确运行,您必须在代码末尾使用 pyglet.app.run()。它将运行 event loop,后者将运行播放下一首音乐的代码。它还将运行分配给 on_eos 等的代码。

import pyglet

files = [
    'somemusic1.wav',
    'somemusic2.wav',
    'somemusic3.wav',
]
    
player = pyglet.media.Player()

@player.event
def on_eos():
    print("[event] on_eos: end of file")

@player.event
def on_player_eos():
    print("[event] on_player_eos: end of queue")

musics = []

for filename in files:
    item = pyglet.media.load(filename) 
    musics.append( item )
    print('load:', filename)
    
    player.queue(item)
    print('queue:', item)

player.play()

pyglet.app.run()  # need it to run `event loop` 

如果你想用 tkinter 运行它,那么它可能会出现问题,因为 pyglet 运行阻塞代码的事件循环 pyglet.app.run()tkinter 必须运行自己的事件循环 { {1}} 也会阻塞代码。此循环之一必须在单独的线程中运行 - 类似于 Playing music with Pyglet and Tkinter in Python

中的 answer

我尝试在此代码中使用线程,但是当我按下 root.mainloop() 中的按钮时,我只播放了第一首音乐。所以我辞职了。

我还尝试在 tkinter 中构建自己的循环(参见 并添加 piglet 而不是 root.update() 但它需要更多的东西才能正常工作。所以我辞职了。

root.mainloop()

对我来说最好的解决方案是使用 while True: pyglet.clock.tick() for window in pyglet.app.windows: window.switch_to() window.dispatch_events() window.dispatch_event('on_draw') window.flip() root.update() 。它用于创建 PyQt 并且它有许多 wigdets 和许多用于其他任务的类。

我使用了一些带有 GUIQMediaPlayer 的示例代码,在点击按钮后一一播放所有音乐。它也有改变 QMediaPlaylist 的功能,但我没有测试。

它不仅可以加载声音,还可以加载可以在 volume 中显示的视频。它可以直接从互联网(URL)加载文件。

QVideoWidget

编辑:

我使用 from PyQt5.QtMultimediaWidgets import QVideoWidget from PyQt5.QtCore import QUrl from PyQt5.QtWidgets import QApplication, QPushButton from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer, QMediaPlaylist import sys files = [ 'somemusic1.wav', 'somemusic2.wav', 'somemusic3.wav', ] class VideoPlayer: def __init__(self): #self.video = QVideoWidget() #self.video.resize(300, 300) #self.video.move(0, 0) self.playlist = QMediaPlaylist() for item in files: self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(item))) self.playlist.setCurrentIndex(1) self.player = QMediaPlayer() #self.player.setVideoOutput(self.video) self.player.setPlaylist(self.playlist) def callback(self): self.player.setPosition(0) # to start at the beginning of the video every time #self.video.show() self.player.play() if __name__ == '__main__': app = QApplication(sys.argv) v = VideoPlayer() b = QPushButton('start') b.clicked.connect(v.callback) b.show() sys.exit(app.exec_()) Pyglet 创建了工作代码,使用 tkinter 定期运行 pyglet.clock.schedule()

root.update()