如何将Pytube与PySide6 Progress Bar结合实现下载进度显示?
PySide6 YouTube下载进度条实现方案
核心逻辑
把下载任务放到独立线程中执行,避免阻塞GUI主线程;通过PySide6的Signal将下载进度从子线程传递到主线程,主线程接收信号后更新进度条。
代码改造示例
1. 定义下载线程类
这个类负责执行下载任务,并通过信号发送进度:
from PySide6.QtCore import QThread, Signal import yt_dlp class DownloadThread(QThread): # 定义进度更新信号,参数为进度百分比(0-100) progress_updated = Signal(int) # 定义下载完成信号,参数表示是否成功 download_finished = Signal(bool) def __init__(self, url, save_path, quality, parent=None): super().__init__(parent) self.url = url self.save_path = save_path self.quality = quality def run(self): # 进度回调函数,由yt-dlp触发 def progress_callback(data): if data['status'] == 'downloading': # 计算当前下载进度 downloaded = data.get('downloaded_bytes', 0) total = data.get('total_bytes', data.get('total_bytes_estimate', 1)) progress = int((downloaded / total) * 100) self.progress_updated.emit(progress) elif data['status'] == 'finished': self.download_finished.emit(True) # yt-dlp配置项 ydl_config = { 'format': self.quality, 'outtmpl': f'{self.save_path}/%(title)s.%(ext)s', 'progress_hooks': [progress_callback], } try: with yt_dlp.YoutubeDL(ydl_config) as ydl: ydl.download([self.url]) except Exception as e: print(f"下载错误: {str(e)}") self.download_finished.emit(False)
2. 主窗口中集成线程与进度条
在你的MainWindow类中,绑定线程信号到进度条,并处理下载触发逻辑:
from PySide6.QtWidgets import QMainWindow from ui_mainwindow import Ui_MainWindow class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) # 绑定下载按钮点击事件(根据你的UI控件名称调整) self.download_btn.clicked.connect(self.start_download) self.download_thread = None def start_download(self): # 获取用户输入的参数 video_url = self.url_input.text().strip() save_dir = self.save_path_input.text().strip() selected_quality = self.quality_combo.currentText() if not video_url or not save_dir: return # 初始化并启动下载线程 self.download_thread = DownloadThread(video_url, save_dir, selected_quality) # 连接进度信号到进度条的setValue方法 self.download_thread.progress_updated.connect(self.progressBar.setValue) # 连接完成信号处理后续操作 self.download_thread.download_finished.connect(self.handle_download_result) # 启动线程 self.download_thread.start() def handle_download_result(self, success): # 下载完成后的处理逻辑 self.progressBar.setValue(0) if success: print("下载完成") # 可添加弹窗提示、日志记录等操作 else: print("下载失败")
关键注意事项
- 禁止子线程操作UI:所有对进度条等UI控件的更新必须通过信号在主线程执行,PySide6不允许跨线程直接操作UI。
- 进度计算容错:yt-dlp的回调数据中,
total_bytes可能为空,需用total_bytes_estimate作为备选。 - 线程资源管理:下载完成后可通过
finished信号清理线程对象,避免内存泄漏。
内容的提问来源于stack exchange,提问作者WigoWigo
相关产品推荐
相关产品推荐

