Pyglet 音频队列 - Python

问题描述

import pyglet,pafy
from pyglet.window import key
import urllib.request
from urllib.parse import *
from googleapiclient.discovery import build

api_key = ''
yt = build('youtube','v3',developerKey=api_key)

def download_file(search):
    try:
        os.remove("song.m4a")
    except:
        pass
    
    request = yt.search().list(
        part="snippet",maxResults=1,q=search
    )   
    response = request.execute()
    items = response['items']
    item = items[0]
    snippet = item['snippet']
    title = snippet['title']
    id_ = item["id"]
    videoid = id_["videoId"]
    url = "https://www.youtube.com/watch?v=" + videoid

    info = pafy.new(url)
    audio = info.getbestaudio(preftype="m4a")
    audio.download('song.m4a',quiet=True)


file = 'song.m4a'
#if len(sys.argv)>1:
#    file = sys.argv[1]
#
window = pyglet.window.Window()

#music = pyglet.resource.media(file)

player = pyglet.media.Player()

#player.queue(music)
#player.play()

paused = False

def help():
    print("""\nCommands:
\tEsc or x \t Exit program
\tp \t Pause/unpause music
\th \t See this list again""")

print("""Welcome to this music player!
You can give a file as an argument or use the commands below.""")

help()

@window.event
def on_key_press(symbol,modifiers):
    global paused
    global player
    global window
    file = 'song.m4a'
    if symbol == key.P:
        if paused:
            print("Resume")
            player.play()
            paused = False
        else:
            print("Pause")
            player.pause()
            paused = True
    elif symbol == key.R:
        pass
        #Doesn't work :P
        #player.seek(0)
    elif symbol == key.H:
        help()
    elif symbol == key.ESCAPE:
        try:
            os.remove("song.m4a")
        except:
            pass
        window.close()

    elif symbol == key.Q:
        srch = input("Queue Song: ")
        download_file(srch)
        music = pyglet.media.load(file)
        player.queue(music)
        #music.play()
        player.next_source()
        print(f'Added to queue.')
        
    elif symbol == key.S:
        srch = input("Play Song: ")
        download_file(srch)
        music = pyglet.media.load(file)
        #music.play()
        player.queue(music)
        player.next_source()
            
pyglet.app.run()
pyglet.app.exit()

所以我遇到了 Pyglet 库的一些问题。我似乎无法让这部分工作。我是否正确调用player.next_source()?因为我刚刚运行了 symbol == key.S 并为 srch 设置了一个值,但没有播放任何内容。我的目标是使我在按下 q 时输入的输入将歌曲排队并在当前歌曲之后自动播放,同时按下 s 并在那里输入一个值将覆盖队列并优先考虑.一些帮助将不胜感激。

解决方法

首先,您使用的是 player.next_source()。这会迫使玩家进入队列中的下一个。所以你的Q键功能不对,你不是在排队,你是在排队然后强制播放。这就是你应该用你的 S 键做什么。我认为您对 next_source 的实际作用感到困惑或混淆。

其次,当加载音乐时,它流式传输来自文件本身。每次按下一个键时,您似乎都在覆盖文件(这并不理想,而且这样做容易出错)。所以这不适用于流式传输。

最好的办法是完整加载文件,这样如果文件被覆盖,就不会导致排队缓冲区出现奇怪的问题。尝试改变你的 music = pyglet.media.load(file)music = pyglet.media.load(file,streaming=False)

您也可以更好地将文件下载到单独的文件或临时文件(请参阅 tempfile 库),而不是尝试重复使用相同的文件名。

此外,您很可能必须将 music 存储到全局字典或全局列表中,以防止它被垃圾收集。因为 music 是函数的局部变量,一旦事件结束就会消失。 (这也意味着当您不再需要它们以防止内存泄漏时,您必须从列表中删除它们)