python - 在 python 中播放 mp3 时 window.read() 和 time.sleep() 的问题
问题描述
我正在用 pafy、vlc、PySimpleGUI 制作一个程序,它需要一个 youtube url 并将其作为 mp3 播放。当我第一次尝试控制台模式时遇到的问题是 mp3 会在一段时间后停止,我用 time.sleep 修复了它(秒),现在在控制台版本中一切正常。当我尝试使用 PySimpleGUI 使其成为 GUI 时出现问题,当我使用 time.sleep(seconds) GUI 冻结直到 mp3 结束时,我搜索并发现 window.read() 可以解决问题并且它确实解决了问题,但我暂停后无法继续播放 mp3(如控制台模式),当我按下播放时它播放,当我按下暂停时它暂停,当我再次按下播放时它从头开始但我希望它从它开始暂停是因为 window.read() 吗?抱歉,如果我不能清楚地解释它。控制台模式:
import pafy
import vlc
player = vlc.Instance()
media_player = player.media_player_new()
def readurl():
url=input("URL : ")
vid=pafy.new(url)
l=vid.length
aud=vid.getbestaudio()
media = player.media_new(aud.url)
media.get_mrl()
media_player.set_media(media)
def ans(a):
if(a.upper()=="S"):
media_player.pause()
elif(a.upper()=="P"):
media_player.play()
elif(a.upper()=="R"):
media_player.pause()
readurl()
ans("P")
else:
exit()
readurl()
while True:
a=input("Choose from options P to play, S to stop(pause), Q to quit, R to get another video. ")
ans(a)
图形用户界面模式:
import PySimpleGUI as sg
import vlc
import pafy
import time
player = vlc.Instance()
media_player = player.media_player_new()
sg.theme('DarkBlue')
def btn(name):
return sg.Button(name, size=(6, 1), pad=(1, 1))
layout = [[sg.Button(button_text='Get video from youtube url : ', size=(20,1), key='geturl'),sg.Input(default_text='', size=(50, 10), key='-VIDEO_LOCATION-')],
[btn('play'), btn('pause')]]
window = sg.Window('Youtube Radio Mode', layout, element_justification='center', finalize=True, resizable=True)
#------------ Media Player Setup ---------#
"""
"""
def ans(a,q):
if(a.upper()=="S"):
media_player.pause()
#window.read(q)
elif(a.upper()=="P"):# or (a.upper()=="R")):
media_player.play()
window.read(q)
else:
exit()
#------------ The Event Loop ------------#
#def vi()
while True:
event, values = window.read(timeout=1000)
url=values['-VIDEO_LOCATION-']
z=''
if event == sg.WIN_CLOSED:
break
if (url!='' or event == 'geturl'):
vid=pafy.new(url)
#l=vid.length
aud=vid.getbestaudio()
media = player.media_new(aud.url)
media.get_mrl()
media_player.set_media(media)
z='l'
q=vid.length*1000
if event == 'play':
if(z!='l'):
sg.popup_error('PLEASE GET A URL FIRST')
continue
ans("P",q)
#window.refresh()
z=''
if event == 'pause':
ans("S",q)
window.close()
解决方案
定义你的 GUI,然后进入你的事件循环,并确保你的 GUI 中会发生什么事件,那么下一步该做什么。
这里,修改后的代码供大家参考,不对代码进行测试。
import PySimpleGUI as sg
import vlc
import pafy
import time
def vlc_player():
player = vlc.Instance()
media_player = player.media_player_new()
return media_player
def Button(button_text):
return sg.Button(button_text, size=(6, 1), pad=(1, 1))
media_player = vlc_player()
sg.theme('DarkBlue')
sg.set_options(font=("Courier New", 16))
layout = [
[sg.Button(button_text='Get video from youtube url : ', size=(20,1), key='-GET_URL-'),
sg.Input(default_text='', size=(50, 10), key='URL')],
[Button('PLAY'), BUTTON('PAUSE'), Button('QUIT')],
[sg.Text("", size=(0, 1), key='-STATUS-')],
]
window = sg.Window('Youtube Radio Mode', layout, element_justification='center',
finalize=True, resizable=True)
status = window['-STATUS-']
mp3_load = False
#------------ The Event Loop ------------#
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, 'QUIT'):
break
status.update(value='')
if event == '-GET_URL-':
"""
if player.is_playing():
player.stop()
"""
url = values['-URL-'].strip()
try:
vid = pafy.new(url)
aud = vid.getbestaudio()
media = player.media_new(aud.url)
media.get_mrl()
media_player.set_media(media)
mp3_load = True
continue
except:
pass
status.update('URL load failed !')
mp3_load = False
elif event == 'PLAY' and mp3_load:
media_player.play()
elif event == 'PAUSE' and mp3_load:
media_player.pause()
if player.is_playing():
media_player.stop()
window.close()
如果需要很长时间,您可以使用多线程从 Youtube 加载 mp3,并设置一些标志以确认是否正在下载或下载完成,或者禁用按钮 '-GET_URL-' 或其他按钮。
不要在另一个线程中直接更新 GUI,您可以调用window.write_event_value
生成新事件,然后在事件循环中更新 GUI。
参考https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Media_Player_VLC_Based.py
推荐阅读
- youtube - 如何在使用 video.js 7 播放时获取 youtube 元数据
- sql - SQL 查询以选择有空间的储物柜用于包裹
- git - 如何禁用 github 上的环境选项卡
- bash - 在 bash 中按列格式化输出
- android - 单击后如何保持列表视图项处于选中状态
- hbase - 如何安全关闭整个hbase集群?
- java - Maven 构建罐
- java - Spring @Scheduled(cron = "0 * * * * ?") 不是每小时运行一次
- javascript - nextProps 和 NextState 总是等价的
- apache-spark - pyspark 动态过滤