網站首頁 編程語言 正文
一、運行環境
????????python3.6,linux18.04,pyqt5
二、主體代碼
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '/home/SENSETIME/wangwenjun1.vendor/PycharmProjects/pyqt/frame.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import os
import shutil
import time
from subprocess import PIPE, Popen
from uuid import uuid4
from multiprocessing import Queue
class Ui_MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(Ui_MainWindow, self).__init__()
self.setupUi(self)
self.retranslateUi(self)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(90, 20, 80, 23))
self.pushButton.setObjectName("pushButton")
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setGeometry(QtCore.QRect(530, 280, 221, 23))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(530, 240, 80, 23))
self.pushButton_2.setObjectName("pushButton_2")
self.listView_2 = QtWidgets.QListView(self.centralwidget)
self.listView_2.setGeometry(QtCore.QRect(80, 80, 441, 201))
self.listView_2.setObjectName("listView_2")
self.listView = QtWidgets.QListView(self.centralwidget)
self.listView.setGeometry(QtCore.QRect(80, 310, 441, 211))
self.listView.setObjectName("listView")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(80, 60, 121, 16))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(80, 290, 211, 16))
self.label_2.setObjectName("label_2")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 20))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.pushButton_2.clicked.connect(self.onStart)
self.timer = QBasicTimer()
self.step = 0
self.failed_file = Queue()
self.mp4_files = []
self.target_folder = 'picture'
self.finish_file = Queue()
self.pushButton.clicked.connect(self.openfile)
# 實例化列表模型,添加數據
self.slm = QStringListModel()
self.failed_slm = QStringListModel()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "視頻抽幀小工具"))
self.pushButton.setText(_translate("MainWindow", "打開"))
self.pushButton_2.setText(_translate("MainWindow", "開始"))
self.label.setText(_translate("MainWindow", "總量"))
self.label_2.setText(_translate("MainWindow", "失敗: 0"))
def openfile(self):
openfile_name = QFileDialog.getOpenFileNames(self, '選擇文件', '', 'Excel files(*.mp4)')
self.mp4_files = list(self._filter_file(openfile_name[0]))
self.target_folder = os.path.join(os.path.split(self.mp4_files[0])[0], self.target_folder)
QMessageBox.warning(self, '保存路徑', f'本次圖片保存在{self.target_folder}, 默認會清理該路徑,請及時轉移文件!')
try:
shutil.rmtree(self.target_folder)
except:
pass
print(f'total: {len(self.mp4_files)}')
self.label.setText(f"總量: {len(self.mp4_files)}")
# 設置模型列表視圖,加載數據列表
self.slm.setStringList(self.mp4_files)
# 設置列表視圖的模型
self.listView_2.setModel(self.slm)
def _filter_file(self, mp4_files):
t_set = set()
for filename in mp4_files:
if os.path.isfile(filename):
new_f = filename.replace(' ', '').replace('(', '').replace(')', '').strip()
try:
os.rename(filename, new_f)
except shutil.SameFileError:
print('no copy!')
except:
import traceback
print(traceback.format_exc())
if new_f in t_set:
continue
t_set.add(new_f)
return t_set
def timerEvent(self, event):
self.progressBar.setValue(self.finish_file.qsize() * 100 / len(self.mp4_files))
self.label_2.setText(f"失敗: {self.failed_file.qsize()}")
# 設置模型列表視圖,加載數據列表
_t = []
while not self.failed_file.empty():
_t.append(self.failed_file.get())
self.failed_slm.setStringList(_t)
# 設置列表視圖的模型
self.listView.setModel(self.failed_slm)
if self.finish_file.qsize() >= len(self.mp4_files):
print(self.finish_file.qsize())
self.timer.stop()
self.pushButton_2.setText('Start')
QMessageBox.information(self, '抽幀完成提醒', f'本次圖片保存在{self.target_folder}')
self.finish_file = Queue()
self.failed_file = Queue()
return
def onStart(self):
self.label.setText(f"總量: {len(self.mp4_files)}")
if not len(self.mp4_files):
QMessageBox.critical(self, '抽幀視頻數錯誤', '總量數為0不可執行抽幀操作!')
return
if self.timer.isActive():
self.proc.terminate()
self.proc.join()
self.timer.stop()
self.mp4_files.clear()
self.progressBar.setValue(0)
self.label.setText(f"總量: {len(self.mp4_files)}")
self.listView_2.setModel(self.slm.setStringList([]))
self.listView.setModel(self.slm.setStringList([]))
self.pushButton_2.setText('Start')
self.finish_file = Queue()
self.failed_file = Queue()
else:
self.timer.start(0, self)
from multiprocessing import Process
self.proc = Process(target=self.extract_frame_files, args=(self.mp4_files, self.finish_file, self.failed_file))
self.proc.start()
self.pushButton_2.setText('End')
def extract_frame_files(self, files, finish_q, failed_q):
for file in files:
self.extract_frame(file, finish_q, failed_q)
def extract_frame(self, file, finish_q, failed_q):
picture_id = str(uuid4())
os.makedirs(self.target_folder, exist_ok=True)
command = f"ffmpeg -i {file} -vf fps=2 {self.target_folder}/frame{picture_id}_xxx.png"
command = command.replace('xxx', '%d')
proc = Popen(command, shell=True,
stdout=PIPE,
stderr=PIPE)
return_code = None
while return_code is None:
return_code = proc.poll()
time.sleep(0.01)
out, err = proc.communicate()
proc.kill()
finish_q.put(1)
if return_code == 0:
pass
else:
failed_q.put(1)
print(f'[{file}]出錯結束')
print(f"err: \n{err}")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
三、運行效果
????????
?
原文鏈接:https://blog.csdn.net/CrazyCosin/article/details/119885851
相關推薦
- 2022-07-01 Python錯誤+異常+模塊總結_python
- 2022-10-23 C#中const,readonly和static關鍵字的用法介紹_C#教程
- 2022-05-08 ASP.NET?MVC視圖尋址_實用技巧
- 2022-09-25 edge或谷歌瀏覽器打開默認是百度或其他,怎么修改成自己想要的頁面
- 2022-08-22 pyecharts繪制時間輪播圖柱形圖+餅圖+玫瑰圖+折線圖_python
- 2023-03-22 gin正確多次讀取http?request?body內容實現詳解_Golang
- 2022-05-06 resty更新header控制api版本數據源讀寫分離_其它綜合
- 2022-07-08 go語言代碼生成器code?generator使用示例介紹_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支