You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
13 KiB
Python

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc
from pytube import Playlist, YouTube, exceptions
import sys
import os
from range_slider import RangeSlider
from PyQt5.QtWidgets import QApplication, QGridLayout, QWidget, QListWidget, QVBoxLayout, QLabel, QPushButton, QListWidgetItem, \
QHBoxLayout
#Todo ersetzen durch QNetworkRequest and QNetworkReply -> soll besser und sicherer funktionieren da urllib blocken kann
from urllib.request import urlopen
import urllib.request
import resources
class QYTVidItem(qtw.QWidget):
def __init__(self, parent=None):
super(QYTVidItem, self).__init__(parent)
sizePolicy = qtw.QSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Minimum)
#self.sizePolicy = qtw.QSizePolicy(qtw.QSizePolicy.Maximum, qtw.QSizePolicy.Maximum)
#sizePolicy.setHeightForWidth(messageformForm.sizePolicy().hasHeightForWidth())
#self.sizePolicy.setHorizontalStretch(True)
self.setSizePolicy(sizePolicy)
self.vid_layout = qtw.QHBoxLayout()
self.vidDetailLayout = qtw.QVBoxLayout()
self.vidHeaderLayout = qtw.QHBoxLayout()
self.vidSpecsLayout = qtw.QHBoxLayout()
self.vidStartEndLayout = qtw.QHBoxLayout()
self.buttonLayout = qtw.QHBoxLayout()
self.buttonLayout.setSizeConstraint(qtw.QLayout.SizeConstraint.SetMinimumSize)
self.title = ""
self.url = ""
self.currentFormat = 'mp4'
self.currentRes = 'best'
self.defaultThumbPix = qtg.QPixmap(":/assets/bagi_default.png")
#debug -> Rosa hintergrund für Size test
pal = qtg.QPalette()
pal.setColor(qtg.QPalette.Background, qtg.QColor(218, 94, 242))
self.setPalette(pal)
self.setAutoFillBackground(True)
def setData(self,purl):
print("setdata for: {}".format(purl))
self.url = purl.strip()
errTxt = self.checkLink(purl)
if (errTxt != "OK"):
return errTxt
# Youtube vid infos laden
#debug
#purl = "https://www.youtube.com/watch?v=Lrj2Hq7xqQ8"
self.yt_vid = YouTube(url=purl)
print("Url Found. Title:{}".format(self.yt_vid.title))
self.title = self.yt_vid.title
#url = "https://i.ytimg.com/vi/Lrj2Hq7xqQ8/maxresdefault.jpg"
thumbNail_url = self.yt_vid.thumbnail_url
thumbPixmap = qtg.QPixmap()
try: #wenn thumbnail url ungültig oder nicht geladen werden konnte -> default setzen
request = urllib.request.Request(thumbNail_url)
response = urllib.request.urlopen(request)
data = response.read()
thumbPixmap.loadFromData(data)
except Exception:
self.thumbPixmap.load(":/assets/bragi_default.png")
##Linke Seite:
# Thumbnail des Videos (oder default wenn keins vorhanden)
icoLabel = qtw.QLabel()
icoLabel.setPixmap(thumbPixmap.scaled(150,150,aspectRatioMode=qtc.Qt.KeepAspectRatio))
self.vid_layout.addWidget(icoLabel)
##Rechte Seite des Widgets
# Oberste Reihe:
# Titel, btn_edit, btn_remove
self.title_edit = qtw.QLineEdit(self.yt_vid.title)
self.title_edit.setReadOnly(True)
self.vidHeaderLayout.addWidget(self.title_edit)
#self.vidHeaderLayout.addStretch()
pixmap_edit = qtg.QPixmap(":/assets/edit.svg")
icon_edit = qtg.QIcon(pixmap_edit.scaled(50,50,aspectRatioMode=qtc.Qt.KeepAspectRatio))
self.btn_edit = qtw.QToolButton()
self.btn_edit.setIcon(icon_edit)
self.btn_edit.clicked.connect(self.toggleTitleEditable)
self.vidHeaderLayout.addWidget(self.btn_edit)
pixmap_remove = qtg.QPixmap(":/assets/cancel2.svg")
icon_remove = qtg.QIcon(pixmap_remove.scaled(50,50,aspectRatioMode=qtc.Qt.KeepAspectRatio))
self.btn_remove = qtw.QToolButton()
self.btn_remove.setIcon(icon_remove)
self.vidHeaderLayout.addWidget(self.btn_remove)
self.vidDetailLayout.addItem(self.vidHeaderLayout)
# Mittlere Reihe:
# Video Specs
dur_time = self.yt_vid.length
duration = qtw.QLabel("Duration: {} sec".format(dur_time))
self.vidSpecsLayout.addWidget(duration)
#self.vidSpecsLayout.addStretch()
self.vidDetailLayout.addItem(self.vidSpecsLayout)
# vorletze reihe:
# Start/Ende Marker
self.vidStartEndLayout.setContentsMargins(5,0,5,0)
self.vidStartEndLayout.setSpacing(10);
self.vidStartEndLayout.setAlignment(qtc.Qt.AlignLeft)
slider = RangeSlider(qtc.Qt.Horizontal)
slider.setMinimumHeight(10)
slider.setMaximumWidth(200)
slider.setMinimum(0)
slider.setMaximum(dur_time)
slider.setLow(0)
slider.setHigh(dur_time)
slider.setTickPosition(qtw.QSlider.TicksBelow)
slider.sliderMoved.connect(self.updateSliderVal)
#QtCore.QObject.connect(slider, QtCore.SIGNAL('sliderMoved(int)'), echo)
slider.show()
slider.raise_()
self.vidStartEndLayout.addWidget(slider)
#self.vidStartEndLayout.addStretch()
vid_start_txt = qtw.QLabel("start at(sec):")
vid_start_txt.setAlignment(qtc.Qt.AlignLeft|qtc.Qt.AlignVCenter)
self.vidStartEndLayout.addWidget(vid_start_txt)
lowVal = slider.low()
self.vid_start = qtw.QLabel(str(lowVal))
self.vid_start.setAlignment(qtc.Qt.AlignLeft|qtc.Qt.AlignVCenter)
self.vidStartEndLayout.addWidget(self.vid_start)
vid_end_txt = qtw.QLabel("end at(sec):")
vid_end_txt.setAlignment(qtc.Qt.AlignLeft|qtc.Qt.AlignVCenter)
self.vidStartEndLayout.addWidget(vid_end_txt)
highVal = slider.high()
self.vid_end = qtw.QLabel(str(highVal))
self.vidStartEndLayout.addWidget(self.vid_end)
self.vidStartEndLayout.setAlignment(qtc.Qt.AlignLeft|qtc.Qt.AlignVCenter)
self.vidDetailLayout.addItem(self.vidStartEndLayout)
# Unterste Reihe:
# Combobox für Streamauswahl +
# Video spezifische Buttons (ordentliche pics)
#self.buttonLayout.setContentsMargins(5,0,5,0)
self.buttonLayout.setSpacing(10);
self.buttonLayout.setAlignment(qtc.Qt.AlignLeft)
self.format_combo = qtw.QComboBox()
self.format_combo.addItem('mp4(Video)')
self.format_combo.addItem('mp3(Audio)')
self.format_combo.setCurrentIndex(0)
self.buttonLayout.addWidget(self.format_combo)
self.resolution_combo = qtw.QComboBox()
#print(self.yt_vid.streams[0].itag)
for stream in self.yt_vid.streams:
print("{}\n".format(stream))
#self.resolution_combo.addItem(stream.value)
self.buttonLayout.addWidget(self.resolution_combo)
#self.buttonLayout.addStretch()
pixmap_play = qtg.QPixmap(":/assets/play2.svg")
icon_play = qtg.QIcon()
icon_play.addPixmap(pixmap_play.scaled(50,50,aspectRatioMode=qtc.Qt.KeepAspectRatio))
btn_play = qtw.QToolButton()
#btn_play.setPixmap(pixmap_play.scaled(25,25,aspectRatioMode=qtc.Qt.KeepAspectRatio))
btn_play.setIcon(icon_play)
btn_play.clicked.connect(self.playItem)
self.buttonLayout.addWidget(btn_play)
pixmap_stop = qtg.QPixmap(":/assets/stop2.svg")
icon_stop = qtg.QIcon()
icon_stop.addPixmap(pixmap_stop.scaled(50,50,aspectRatioMode=qtc.Qt.KeepAspectRatio))
btn_stop = qtw.QToolButton()
#btn_stop.setPixmap(pixmap_stop.scaled(25,25,aspectRatioMode=qtc.Qt.KeepAspectRatio))
btn_stop.setIcon(icon_stop)
btn_play.clicked.connect(self.stopItem)
self.buttonLayout.addWidget(btn_stop)
pixmap_download = qtg.QPixmap(":/assets/download.svg")
icon_download = qtg.QIcon()
icon_download.addPixmap(pixmap_download.scaled(50,50,aspectRatioMode=qtc.Qt.KeepAspectRatio))
self.btn_download = qtw.QToolButton()
#btn_download.setPixmap(pixmap_download.scaled(25,25,aspectRatioMode=qtc.Qt.KeepAspectRatio))
self.btn_download.setIcon(icon_download)
#self.btn_download.clicked.connect(self.downloadItem)
self.buttonLayout.addWidget(self.btn_download)
self.vidDetailLayout.addItem(self.buttonLayout)
#Layouts zusammenfügen und setzen
self.vid_layout.addItem(self.vidDetailLayout)
#self.vid_layout.setSizeConstraint()
self.setLayout(self.vid_layout)
return errTxt
def toggleTitleEditable(self):
if self.title_edit.isReadOnly():
self.title_edit.setReadOnly(False)
self.title_edit.selectAll()
self.btn_download.setEnabled(False)
pixmap_edit = qtg.QPixmap(":/assets/check.svg")
icon_edit = qtg.QIcon(pixmap_edit.scaled(50,50,aspectRatioMode=qtc.Qt.KeepAspectRatio))
self.btn_edit.setIcon(icon_edit)
else:
self.title_edit.deselect()
self.title_edit.setReadOnly(True)
self.btn_download.setEnabled(True)
pixmap_edit = qtg.QPixmap(":/assets/edit.svg")
icon_edit = qtg.QIcon(pixmap_edit.scaled(50,50,aspectRatioMode=qtc.Qt.KeepAspectRatio))
self.btn_edit.setIcon(icon_edit)
def toggleFormatResolution(self):
if self.currentFormat == 'mp4':
pass
else:
pass
def updateSliderVal(self,low_value, high_value):
self.vid_start.setText(str(low_value))
self.vid_end.setText(str(high_value))
def playItem(self):
pass
def stopItem(self):
pass
def downloadItem(self,path):
#self.yt_vid.streams.get_by_itag(251).download(path)
# download the file
out_file = self.yt_vid.streams.get_highest_resolution().download(output_path=path)
# save the file
base, ext = os.path.splitext(out_file)
print("base:{}".format(base))
new_file = base + '.mp4'
print("new:{}".format(new_file))
os.rename(out_file, new_file)
print("Download Triggered")
def checkLink(self,url):#done
try:
yttest = YouTube(url)
yttest.check_availability()
return "OK"
except exceptions.RegexMatchError:
errTxt = "Video Link invalid({}). Link is no valid url.".format(url)
print(errTxt)
return errTxt
except exceptions.MembersOnly:
errTxt = "Video Link invalid({}). Only available to Members of that group.".format(url)
print(errTxt)
return errTxt
except exceptions.RecordingUnavailable:
errTxt = "Video Link invalid({}). Live-Stream not available.".format(url)
print(errTxt)
return errTxt
except exceptions.VideoRegionBlocked:
errTxt = "Video Link invalid({}). Not available in your region.".format(url)
print(errTxt)
return errTxt
except exceptions.VideoPrivate:
errTxt = "Video Link invalid({}). Video is set to private.".format(url)
print(errTxt)
return errTxt
except exceptions.VideoUnavailable:
errTxt = "Video Link invalid({}).".format(url)
print(errTxt)
return errTxt
else:
return "OK"
if __name__ == '__main__': #Zum testen des Widget-Designs
app = QApplication(sys.argv)
window = QWidget()
title = QLabel("Demo for widgets in a QListWidget")
scrollA = qtw.QScrollArea()
scrollLayout = QGridLayout()
item_1 =QYTVidItem()
item_2 =QYTVidItem()
item_3 =QYTVidItem()
scrollLayout.addWidget(item_1,scrollLayout.count(),0)
item_1.setData("https://www.youtube.com/watch?v=Lrj2Hq7xqQ8")
scrollLayout.addWidget(item_2,scrollLayout.count(),0)
item_2.setData("https://www.youtube.com/watch?v=lL7jwhWAU_k")
#scrollLayout.addWidget(item_3)
scrollA.setLayout(scrollLayout)
window_layout = QVBoxLayout(window)
window_layout.addWidget(title)
window_layout.addWidget(scrollA)
window.setLayout(window_layout)
window.show()
sys.exit(app.exec_())