I'm trying to show the live progress of download in the gui. I'm getting the live progress of download in cmd but gui only updates when the download is complete.
def myhook(self,d):
self.percentage=QLabel(self)
self.d=d
if self.d['status']=='finished':
print("finished")
if self.d['status']=='downloading':
print(self.d['filename'],self.d['total_bytes'],self.d['downloaded_bytes'],self.d['elapsed'],self.d['eta']
,str(str(self.d['speed']/1000)[0:5]+'KiB/s')
,str((self.d['downloaded_bytes']*100)/self.d['total_bytes'])[0:5]+'%')
if self.d['total_bytes']>1048576:
total_size=self.d['total_bytes']/1048576
total_size=str(total_size)[0:5]+' MB'
if self.d['total_bytes']>1073741824:
total_size=self.d['total_bytes']/1073741824
total_size=str(total_size)[0:5]+' GB'
self.percentage.setText('{} {}'.format(total_size
,str((self.d['downloaded_bytes']*100)/self.d['total_bytes'])[0:5]+' %'))
self.percentage.setStyleSheet('color:white;border-bottom:2px solid orange;')
self.percentage.setFont(QFont('Arial',15))
self.percentage.resize(500,30)
self.percentage.move(320,650)
self.percentage.show()
self.url=self.urlfield.text()
print("144p")
options={'format':'bestvideo[height=144]+bestaudio/best','noplaylist':True,'postprocessors':[{'key':'FFmpegMetadata'}]
,'noprogress':True,'progress_hooks':[self.myhook]}
with youtube_dl.YoutubeDL(options) as ydll:
ydll.download(['{}'.format(self.url)])
Since many times you have wondered about how is the correct way to obtain information from youtube-dl and show it in a GUI written with pyqt5, I will take the license to go beyond the current question and show a more generic example.
The youtube_dl download method is very time consuming so it should not be executed in the main thread as it generates unwanted effects such as window freezing. On the other hand, there are 2 means of information provided by youtube_dl: the hooks and the logger. And these media are executed in the same thread as the download method, so they should not be accessed directly but through signals.
qyoutubedl.py
import threading
from PyQt5 import QtCore
import youtube_dl
class QLogger(QtCore.QObject):
messageChanged = QtCore.pyqtSignal(str)
def debug(self, msg):
self.messageChanged.emit(msg)
def warning(self, msg):
self.messageChanged.emit(msg)
def error(self, msg):
self.messageChanged.emit(msg)
class QHook(QtCore.QObject):
infoChanged = QtCore.pyqtSignal(dict)
def __call__(self, d):
self.infoChanged.emit(d.copy())
class QYoutubeDL(QtCore.QObject):
def download(self, urls, options):
threading.Thread(
target=self._execute, args=(urls, options), daemon=True
).start()
def _execute(self, urls, options):
with youtube_dl.YoutubeDL(options) as ydl:
ydl.download(urls)
for hook in options.get("progress_hooks", []):
if isinstance(hook, QHook):
hook.deleteLater()
logger = options.get("logger")
if isinstance(logger, QLogger):
logger.deleteLater()
main.py
from PyQt5 import QtWidgets
from qyoutubedl import QLogger, QHook, QYoutubeDL
from hurry.filesize import size
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.url_le = QtWidgets.QLineEdit()
self.download_btn = QtWidgets.QPushButton(self.tr("Download"))
self.progress_lbl = QtWidgets.QLabel()
self.download_pgb = QtWidgets.QProgressBar()
self.log_edit = QtWidgets.QPlainTextEdit(readOnly=True)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QGridLayout(central_widget)
lay.addWidget(QtWidgets.QLabel(self.tr("url:")))
lay.addWidget(self.url_le, 0, 1)
lay.addWidget(self.download_btn, 0, 2)
lay.addWidget(self.progress_lbl, 1, 1, 1, 2)
lay.addWidget(self.download_pgb, 2, 1, 1, 2)
lay.addWidget(self.log_edit, 3, 1, 1, 2)
self.progress_lbl.hide()
self.downloader = QYoutubeDL()
self.download_btn.clicked.connect(self.download)
self.url_le.setText("https://www.youtube.com/watch?v=BaW_jenozKc")
self.resize(640, 480)
def download(self):
qhook = QHook()
qlogger = QLogger()
url = self.url_le.text()
options = {
"format": "bestvideo[height=144]+bestaudio/best",
"noplaylist": True,
"postprocessors": [{"key": "FFmpegMetadata"}],
"noprogress": True,
"logger": qlogger,
"progress_hooks": [qhook],
}
self.downloader.download([url], options)
qhook.infoChanged.connect(self.handle_info_changed)
qlogger.messageChanged.connect(self.log_edit.appendPlainText)
self.download_pgb.setRange(0, 1)
def handle_info_changed(self, d):
if d["status"] == "downloading":
self.progress_lbl.show()
total = d["total_bytes"]
downloaded = d["downloaded_bytes"]
self.progress_lbl.setText("{} of {}".format(size(downloaded), size(total)))
self.download_pgb.setMaximum(total)
self.download_pgb.setValue(downloaded)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()