Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 8, 2017 14:35:08

newbe
Зарегистрирован: 2017-06-08
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

аудио плеер для youtube (pygtk, vlc)

Решил написать плеер для yotube, для удобства прослушивания треков.
Столкнулся с такой проблемой, что не могу нормально в поток пустить получение ссылки на стрим и начать ее проигрывать, либо фризить все окно, либо вылетает, вот весь главный код:

 import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject, GLib, Gdk
import threading
import vlc
from time import sleep
from time import time
import helpers.search
import json
MRL = ""
class ApplicationWindow(Gtk.Window):    
    def __init__(self):        
        Gtk.Window.__init__(self, title="YAudio", resizable=False)
        header = Gtk.HeaderBar(title="YAudio")
        header.set_subtitle("Youtube audio streaming player")
        header.props.show_close_button = True
        self.set_titlebar(header)
        self.set_border_width(10)
        self.set_default_size(500, 600)
        self.set_hexpand(False)
        self.player_paused=False
        self.is_player_active = False
        self.connect("destroy",Gtk.main_quit)
        self.updateFullTime = True        
           
    def show(self):
        self.show_all()
        
    def setup_objects_and_events(self):
        self.test = Gtk.Button("test")
        self.playback_button = Gtk.Button()
        self.stop_button = Gtk.Button()
        
        
        self.play_image = Gtk.Image.new_from_icon_name(
                "gtk-media-play",
                Gtk.IconSize.MENU
            )
        self.pause_image = Gtk.Image.new_from_icon_name(
                "gtk-media-pause",
                Gtk.IconSize.MENU
            )
        self.stop_image = Gtk.Image.new_from_icon_name(
                "gtk-media-stop",
                Gtk.IconSize.MENU
            )
        
        self.playback_button.set_image(self.play_image)
        self.stop_button.set_image(self.stop_image)        
        
        
        self.playback_button.connect("clicked", self.toggle_player_playback)
        self.stop_button.connect("clicked", self.stop_player)
        # self.test.connect("clicked", self.tester)        
        # start boxes
        self.vbox = Gtk.VBox()
        self.add(self.vbox)        
        # header box
        self.header = Gtk.HBox()
        self.header_left = Gtk.HBox()
        self.header_right = Gtk.VBox()
        self.header.pack_start(self.header_left, False, True, 0)
        self.header.pack_start(self.header_right, True, True, 0)
        self.vbox.pack_start(self.header, False, True, 0)
        # controls box 
        self.controls = Gtk.HBox(spacing=8)
        self.controls.set_border_width(8)
        self.header_right.pack_start(self.controls, False, True, 0)
        # button play
        self.controls.pack_start(self.playback_button, False, True, 0)
        # button stop
        self.controls.pack_start(self.stop_button, False, True, 0)
        self.controls.pack_start(Gtk.HSeparator(), False, True, 0)
        # progress
        self.slider = Gtk.HScale.new_with_range(0, 100, 1)
        self.slider_update_signal_id = self.slider.connect(
             "value-changed", self.on_slider_changed)
        self.slider.set_draw_value(False)
        self.slider.set_sensitive(True)
        self.seek_panel = Gtk.VBox()
        self.controls.pack_start(self.seek_panel, True, True, 0)
        self.seek_labels = Gtk.HBox()
        self.seek_panel.pack_start(self.seek_labels, True, True, 10)
        self.track_title = Gtk.Label('', halign=Gtk.Align.START, valign=Gtk.Align.END)
        self.track_title.set_use_markup(True)
        self.track_title.set_markup('<span font="Roboto 10" weight="300">Idle</span>')
        self.seek_labels.pack_start(self.track_title, True, True, 0)
        self.track_time = Gtk.Label('05:00', halign=Gtk.Align.END, valign=Gtk.Align.END)
        self.track_time.set_use_markup(True)
        self.track_time.set_markup('<span font="Roboto 24" weight="100">0:00:00</span>')
        self.seek_labels.pack_start(self.track_time, True, True, 0)
        self.seek_panel.pack_start(self.slider, True, True, 0)
        # entry search
        self.vbox.pack_start(Gtk.HSeparator(), False, False, 0)
        self.search_panel = Gtk.VBox()
        self.vbox.pack_start(self.search_panel, False, False, 5)
        self.search_entry_box = Gtk.HBox()
        self.search_panel.pack_start(self.search_entry_box, True, True, 0)
        self.search_entry = Gtk.Entry()
        self.search_entry.set_text("")
        self.search_entry.set_placeholder_text("Поиск...")
        self.search_entry_box.pack_start(self.search_entry, True, True, 0)
        # search result
        self.vbox.pack_start(Gtk.HSeparator(), False, False, 0)
        self.search_result_box = Gtk.VBox()
        self.vbox.pack_start(self.search_result_box, False, False, 0)
        self.search_result_text = Gtk.VBox()
        self.search_result_box.pack_start(self.search_result_text, False, False, 0)
        self.result_label = Gtk.Label('', halign=Gtk.Align.START, valign=Gtk.Align.END)
        self.result_label.set_use_markup(True)        
        self.search_result_text.pack_start(self.result_label, False, False, 0)
        
    
        raw_html = helpers.search.get_search_results_html('mops')
        vids = helpers.search.get_videos(raw_html)
        
        self.scrolled = Gtk.ScrolledWindow()
        self.scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
        for _ in vids:
            attrs = helpers.search.get_video_attrs(_)
            
            self.label_p = Gtk.Label(attrs['title'])
            self.listhbox = Gtk.HBox()
            self.vbox.pack_start(self.listhbox, False, False, 5)
            self.button_p = Gtk.Button()
            self.play_image = Gtk.Image.new_from_icon_name(
                "gtk-media-play",
                Gtk.IconSize.MENU
            )
            self.button_p.set_image(self.play_image)
            self.button_p.connect("clicked", self.get_url_and_start, attrs['id'])
            self.listhbox.pack_start(self.button_p, False, True, 2)
            self.listhbox.pack_start(Gtk.HSeparator(), False, False, 2)
            self.listhbox.pack_start(self.label_p, False, True, 2)
        self.scrolled.add_with_viewport(self.listhbox)
        # self.connect("realize",self._realized)
        # self.scrolled.show()        
        # self.result_label.set_markup('<span font="Roboto 10">'+res+'</span>')
    def get_url_and_start(self, widget, id):
        thread = threading.Thread(target=self._realized, args=(id,))
        thread.daemon = True
        thread.start()        
        
    def stop_player(self, widget, data=None):
        self.player.stop()
        self.is_player_active = False
        self.playback_button.set_image(self.play_image)
        self.player.set_position(0.0)
    def on_slider_changed(self, range):
        length = self.slider.get_value()
        self.player.set_position(length / 100.0)
        
    def toggle_player_playback(self, widget, data=None):
        if self.is_player_active == False and self.player_paused == False:
            self.player.play()
            self.playback_button.set_image(self.pause_image)
            self.is_player_active = True
        elif self.is_player_active == True and self.player_paused == True:
            self.player.play()
            self.playback_button.set_image(self.pause_image)
            self.player_paused = False
        elif self.is_player_active == True and self.player_paused == False:
            self.player.pause()
            self.playback_button.set_image(self.play_image)
            self.player_paused = True
        else:
            pass
        
    def _realized(self, id):
        url = helpers.search.get_youtube_streams(id)
        self.vlcInstance = vlc.Instance("--no-xlib")
        self.player = self.vlcInstance.media_player_new()
        # win_id = widget.get_window().get_xid()
        # self.player.set_xwindow(win_id)
        self.player.set_mrl(str(url['audio']))
        self.player.play()          
        self.playback_button.set_image(self.pause_image)
        self.is_player_active = True
        GObject.timeout_add(1000, self.timing)        
    def timing(self):        
        if self.updateFullTime:
            self._m, self._s = divmod(int(self.player.get_length() / 1000), 60)
            self._h, self._m = divmod(self._m, 60)        
            self.full_time_human = "%d:%02d:%02d" % (self._h, self._m, self._s)
            self.updateFullTime = False
        m, s = divmod(int(self.player.get_time() / 1000), 60)
        h, m = divmod(m, 60)
        self.con_time_human = "%d:%02d:%02d" % (h, m, s)
        # if stream ended
        if self.full_time_human == self.con_time_human:
            self.player.stop()
            self.is_player_active = False
            self.playback_button.set_image(self.play_image)
            self.player.set_position(0.0)
        length = self.player.get_position()        
        self.track_time.set_markup('<span font="Roboto 24" weight="100">'+self.con_time_human+'</span>')
        # self.slider.set_digits("%d:%02d:%02d" % (h, m, s))
        self.slider.handler_block(self.slider_update_signal_id)        
        self.slider.set_value(length * 100.0)
        self.slider.handler_unblock(self.slider_update_signal_id)
        return True
if __name__ == '__main__':
      
    # MRL = url
    window = ApplicationWindow()
    window.setup_objects_and_events()
    window.show()
    Gtk.main()
    window.player.stop()
    # window.vlcInstance.release()
метод _realized как видно по коду, получает ссылку под id (около 3х секунд) и должен начинать проигрывать, но сам вижу что данных подход не правильный, подскажите, как лучше и грамотней сделать?

Отредактировано newbe (Июнь 8, 2017 14:36:38)

Офлайн

#2 Июнь 9, 2017 03:45:37

delvin-fil
Зарегистрирован: 2015-11-27
Сообщения: 95
Репутация: +  4  -
Профиль   Отправить e-mail  

аудио плеер для youtube (pygtk, vlc)

ссылку под id (около 3х секунд) и должен начинать проигрывать, но сам вижу что данных подход не правильный
Эммм…
Речь о питоне и засим закономерный вопрос: Вы youtube-dl -F(ибо прога как раз на питоне) на сей плейлист делали?
Предположение, не более - может там не mp3, не ac3, может там что-то совершенно иное. Проверьте на другом плейлисте.
Посмотрите, там наверняка есть “audio-only”



 import __hello__

Отредактировано delvin-fil (Июнь 9, 2017 03:45:58)

Офлайн

#3 Июнь 9, 2017 08:45:47

newbe
Зарегистрирован: 2017-06-08
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

аудио плеер для youtube (pygtk, vlc)

delvin-fil
Эммм…
Речь о питоне и засим закономерный вопрос: Вы youtube-dl -F(ибо прога как раз на питоне) на сей плейлист делали?
Предположение, не более - может там не mp3, не ac3, может там что-то совершенно иное. Проверьте на другом плейлисте.
Посмотрите, там наверняка есть “audio-only”
да, по id получает ссылку вида:
https://r8—sn-bpb5oxu-3c2s.googlevideo.com/videoplayback?keepalive=yes&itag=251&requiressl=yes&ei=3H04WfzrF8WuYK_5iNAC&mn=sn-bpb5oxu-3c2s&gir=yes&mm=31&dur=2930.881&id=o-AFgdCjwDraufG3D9c6fsuf6Rkjf82Frb7asFkxAJfQuQ&source=youtube&ip=31.170.131.52&clen=45959913&mv=m&mt=1496874344&ms=au&expire=1496896060&signature=A7ECF9A90A7BAFE95B1F3A9A5644B2063B3D9914.6A7933DF5201DFE460D6625F75D573783ADB3776&lmt=1494123310691320&mime=audio%2Fwebm&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Ckeepalive%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Crequiressl%2Csource%2Cexpire&key=yt6&pl=24&ipbits=0&initcwndbps=4175000&ratebypass=yes
Вопрос именно в том, как это на отдельный поток грамотно бросить, что бы не фризить gui

Офлайн

#4 Июнь 10, 2017 02:19:15

delvin-fil
Зарегистрирован: 2015-11-27
Сообщения: 95
Репутация: +  4  -
Профиль   Отправить e-mail  

аудио плеер для youtube (pygtk, vlc)

newbe
что бы не фризить gui
ГУЙ обязателен?



 import __hello__

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version