Pyqt制作B站视频下载软件

本文详细介绍了一款基于Pyqt的B站视频下载软件的设计与实现过程,包括视频URL提取、音频与视频分离下载及合成、线程下载管理等关键技术点。

界面

在这里插入图片描述
在这里插入图片描述

B站下载视频Url提取

需要注意的是B站的音频和视频是分开的,也就是说要下载两个东西,然后自己合并才能变成一个完整的视频,如下:
sText为请求的视频网站的内容

 self.m_oRequest =requests.session()
 oResult = self.m_oRequest.get(sUrl, headers=base_headers, timeout=3)
 sText = oResult.text
    def getVideoLinks(self, sText):
        # get video download links
        from public import tools
        dctDownloadLink = {
   
   }
        try:
            data = re.findall(r'<script>window\.__playinfo__=(.*?)</script>', sText)[0]
            dctBiliData = json.loads(data)
            #pprint.pprint(dctBiliData)
            lstLinkData = dctBiliData['data']['dash']['video']
            sAudioUrl = dctBiliData['data']['dash']['audio'][0]["base_url"].replace("http", "https")
            sVideoUrl = dctBiliData['data']['dash']['video'][0]["base_url"].replace("http", "https")
            dctDownloadLink["AudioUrl"] = sAudioUrl
            dctDownloadLink["VideoUrl"] = sVideoUrl
        except:
            print("解析地址失败...")
        print("下载链接 ", dctDownloadLink)
        return dctDownloadLink

视频和音频的合成

这里使用了第三方软件
ffmpeg
网上下载该软件,里面会有exe执行文件,将该执行文件路径加入到系统环境变量中去
合成代码如下

    # 合成音频和视频
    def combineVideo(self, sAudioPath, sVideoPath, sOutputPath):
        import subprocess
        import ffmpeg
        print("开始合成音频和视频...", sAudioPath, sVideoPath, sOutputPath)
        sCmd = 'ffmpeg -i ' + sAudioPath + ' -i ' + sVideoPath + ' -vcodec copy -acodec copy -y ' + sOutputPath
        subprocess.run(sCmd, shell=True)
        print("合成完成...")
        self.combineFinish()

知识点

线程下载

支持暂停,继续,停止

class CDownloader(QThread):
    """download class"""
    oSignalDownload = pyqtSignal(QThread, int) # 下载量信号 list: value flag
    oSignalFinish = pyqtSignal(QThread, int) # 下载结束信号
    def __init__(self, iAvID, dctLinks):
        super(CDownloader, self).__init__()
        self.m_iAvID = iAvID
        self.m_dctLinks = dctLinks
        self.m_oEventPause = threading.Event()     # pause flag
        self.m_oEventPause.set()       # True
        self.m_oEventRunning = threading.Event()      # stop flag
        self.m_oEventRunning.set()      # True
        sScrPath = os.getcwd()
        self.m_sDir = os.path.join(sScrPath, "./videos")
        if not os.path.exists(self.m_sDir):
            os.mkdir(self.m_sDir
<think> 我们正在制作一个视频预览截图插件。根据引用[2]中的描述,我们可以使用PyQt5来构建界面,并利用OpenCV(cv2)进行视频读取和帧提取。功能包括: 1. 从本地选择视频文件 2. 预览视频(在界面上播放) 3. 进行截图(可以指定时间点或按固定间隔截图) 我们将分步骤实现: 步骤1:设计UI界面(参考引用[2]的布局) 步骤2:实现视频加载和预览功能(使用OpenCV读取视频并在QLabel上显示) 步骤3:实现截图功能(从当前视频帧保存为图片) 注意:为了避免中文乱码,我们将确保所有路径和文件名处理使用正确的编码(UTF-8)。 以下是详细的实现方案: </think> ### Python视频预览截图插件开发指南 #### 1. 核心功能设计 ```mermaid graph TD A[视频预览截图插件] --> B[视频加载模块] A --> C[预览播放模块] A --> D[截图控制模块] A --> E[文件保存模块] B --> F[本地文件选择] B --> G[格式兼容处理] C --> H[帧率控制] C --> I[实时预览] D --> J[手动截图] D --> K[自动间隔截图] E --> L[路径管理] E --> M[文件名生成] ``` #### 2. 核心代码实现 ```python import sys import cv2 import os from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * class VideoPreviewApp(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("视频预览截图工具") self.setGeometry(100, 100, 1200, 800) # 创建控件 self.video_label = QLabel("视频预览区域") self.video_label.setAlignment(Qt.AlignCenter) self.video_label.setStyleSheet("background-color: black;") self.btn_open = QPushButton("选择视频") self.btn_screenshot = QPushButton("截图") self.btn_auto_snap = QPushButton("自动截图") # 布局 control_layout = QHBoxLayout() control_layout.addWidget(self.btn_open) control_layout.addWidget(self.btn_screenshot) control_layout.addWidget(self.btn_auto_snap) main_layout = QVBoxLayout() main_layout.addLayout(control_layout) main_layout.addWidget(self.video_label) central_widget = QWidget() central_widget.setLayout(main_layout) self.setCentralWidget(central_widget) # 信号连接 self.btn_open.clicked.connect(self.open_video) self.btn_screenshot.clicked.connect(self.take_screenshot) self.btn_auto_snap.clicked.connect(self.auto_screenshot) # 视频变量初始化 self.cap = None self.timer = QTimer() self.timer.timeout.connect(self.update_frame) def open_video(self): file_path, _ = QFileDialog.getOpenFileName( self, "选择视频文件", "", "视频文件 (*.mp4 *.avi *.mkv *.mov)" ) if file_path: # 解决中文路径问题[^1] if os.name == 'nt': encoded_path = file_path.encode('gbk') else: encoded_path = file_path.encode('utf-8') self.cap = cv2.VideoCapture(encoded_path) if self.cap.isOpened(): self.timer.start(30) # 30ms更新一帧 ≈ 33fps else: QMessageBox.warning(self, "错误", "无法打开视频文件") def update_frame(self): ret, frame = self.cap.read() if ret: # 转换OpenCV格式到Qt格式 rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgb_image.shape bytes_per_line = ch * w qt_image = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888) self.video_label.setPixmap(QPixmap.fromImage(qt_image)) def take_screenshot(self): if self.cap and self.cap.isOpened(): # 获取当前帧 ret, frame = self.cap.read() if ret: file_path, _ = QFileDialog.getSaveFileName( self, "保存截图", "", "图片文件 (*.png *.jpg *.jpeg)" ) if file_path: # 解决中文路径问题 cv2.imwrite(file_path.encode('utf-8').decode('latin1'), frame) def auto_screenshot(self): """自动按时间间隔截图功能实现""" if self.cap and self.cap.isOpened(): interval, ok = QInputDialog.getInt( self, "自动截图", "截图间隔(秒):", 5, 1, 60 ) if ok: # 创建保存目录(使用UTF-8编码) save_dir = QFileDialog.getExistingDirectory(self, "选择保存目录") if save_dir: cap = self.cap fps = cap.get(cv2.CAP_PROP_FPS) frame_interval = int(fps * interval) frame_count = 0 while cap.isOpened(): ret, frame = cap.read() if not ret: break if frame_count % frame_interval == 0: # 生成带时间戳的文件名 timestamp = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000 filename = f"截图_{timestamp:.1f}s.jpg" save_path = os.path.join(save_dir, filename) # 解决中文路径问题 cv2.imwrite(save_path.encode('utf-8').decode('latin1'), frame) frame_count += 1 QMessageBox.information(self, "完成", f"已保存{frame_count//frame_interval}张截图") def closeEvent(self, event): if self.cap: self.cap.release() if self.timer.isActive(): self.timer.stop() if __name__ == "__main__": app = QApplication(sys.argv) window = VideoPreviewApp() window.show() sys.exit(app.exec_()) ``` #### 3. 关键技术要点 1. **视频加载与预览** - 使用OpenCV的`VideoCapture`读取视频[^1] - 通过QTimer定时刷新预览画面 - 格式转换:`BGR→RGB→QImage→QPixmap` 2. **中文路径处理** ```python # Windows系统特殊处理 if os.name == 'nt': encoded_path = file_path.encode('gbk') else: encoded_path = file_path.encode('utf-8') # 保存文件时 cv2.imwrite(save_path.encode('utf-8').decode('latin1'), frame) ``` 3. **自动截图算法** $$ \text{截图间隔帧数} = \lfloor \text{FPS} \times \text{时间间隔(秒)} \rfloor $$ 4. **UI优化建议** - 添加进度条显示视频位置 - 增加截图历史记录面板 - 支持快捷键操作(如空格暂停/播放) #### 4. 扩展功能建议 1. **视频处理增强** - 添加滤镜效果(灰度、边缘检测) - 支持关键帧提取算法 ```python # 关键帧检测示例 def detect_keyframes(cap, threshold=100): prev_frame = None keyframes = [] while cap.isOpened(): ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) if prev_frame is not None: diff = cv2.absdiff(gray, prev_frame) if diff.mean() > threshold: keyframes.append(cap.get(cv2.CAP_PROP_POS_MSEC)) prev_frame = gray return keyframes ``` 2. **集成到图像处理框架** 可结合ImagePy等框架添加更多专业功能[^3]: - 批量处理视频文件 - 添加水印和标注 - 生成预览缩略图网格 #### 5. 性能优化技巧 1. 使用多线程处理视频解码 2. 对长视频使用帧采样预览 3. 启用OpenCV硬件加速: ```python cap.set(cv2.CAP_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY) ``` --- ### 相关问题 1. 如何提升OpenCV视频读取性能? 2. PyQt5中如何实现视频播放进度控制? 3. 自动截图时如何避免保存相似度过高的帧? 4. 如何为截图添加时间戳和水印? 5. 视频处理中如何检测场景切换点? 6. 多语言界面(中英文切换)如何实现? 7. 如何将截图功能集成到现有图像处理软件? 8. 视频截图插件如何支持GPU加速? 9. 如何批量处理文件夹中的所有视频文件? 10. 截图质量参数(压缩率/分辨率)如何动态调整?
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值