pyqt5 制作视频剪辑软件,切割视频
该软件用于切割视频,手动选取视频片段的起始帧和结束帧并保存为json文件。gui界面如下:包含快进、快退、暂停等功能,
代码如下:
# coding=UTF-8
"""
theme: pyqt5实现动作起始帧和结束帧的定位,将定位到的帧数保存json文件
time: 2024-6-27
author: cong
"""
import json
import re
import sys
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QMediaPlaylist
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *# 使用 QMediaPlayer 可以进行视频文件解码,视频播放必须将视频帧在某个界面组件上显示,
# 有 QVideoWidget 和 QGraphicsVideoItem 两种视频显示组件,也可以从这两个类继承,自定义视频显示组件。
# QMediaPlayer 也可以结合 QMediaPlaylist 实现视频文件列表播放。class VideoWin(QWidget):save_flag = 0save_start_count = 1save_end_count = 2def __init__(self):super(VideoWin, self).__init__()self.setWindowTitle("MediaPlayer")# 播放画面self.player = QMediaPlayer()self.video_widget = QVideoWidget(self) # 定义视频显示的widget,界面组件self.video_widget.setFixedSize(1280,720)self.player.setVideoOutput(self.video_widget) # 视频播放输出的widget,就是上面定义的# 当前播放的进度,显示调整视频进度条self.label_time = QLabel()self.timeSlider = QSlider()self.timeSlider.setOrientation(Qt.Horizontal)self.timeSlider.setValue(0)self.timeSlider.setMinimum(0)self.player.positionChanged.connect(self.get_time)self.timeSlider.sliderPressed.connect(self.player.pause)self.timeSlider.sliderMoved.connect(self.change_time)self.timeSlider.sliderReleased.connect(self.player.play)# 打开视频self.open_button = QPushButton('打开')self.open_button.clicked.connect(self.open_file)# 快进self.right_button = QPushButton('快进')self.right_button.clicked.connect(self.up_time)# playself.play_button = QPushButton('播放')self.play_button.clicked.connect(self.player.play)# pauseself.mid_button = QPushButton('暂停')self.mid_button.clicked.connect(self.player.pause)# 快退self.left_button = QPushButton('快退')self.left_button.clicked.connect(self.down_time)# 保存开始时间self.start_button = QPushButton('保存动作开始时间')self.start_button.clicked.connect(self.save_start_time)# 保存结束时间self.end_button = QPushButton('保存动作结束时间')self.end_button.clicked.connect(self.save_end_time)# 所有时间选定,最终保存按钮self.done_button = QPushButton('完成并保存')self.done_button.setFixedSize(100,40)self.done_button.clicked.connect(self.save_json)# 视频路径 entry 布局self.path_entry = QLineEdit()# 创建一个网格布局grid_layout = QGridLayout()self.entry_names = [f'entry_{i + 1}' for i in range(80)]for i in range(80):if (i+1) % 2 == 1:label = QLabel(f"start_frame_d{int((i+1)// 2 + 1)}:")else:label = QLabel(f"end_frame_d{int((i+1) / 2)}:")self.entry_names[i] = QLineEdit(self)grid_layout.addWidget(label, i // 2, (i % 2) * 2)grid_layout.addWidget(self.entry_names[i], i // 2, (i % 2) * 2 + 1)# 上述按钮布局button_layout = QHBoxLayout()button_layout.addWidget(self.open_button)button_layout.addWidget(self.right_button)button_layout.addWidget(self.play_button)button_layout.addWidget(self.mid_button)button_layout.addWidget(self.left_button)button_layout.addWidget(self.start_button)button_layout.addWidget(self.end_button)# 左侧布局left_layout = QVBoxLayout()left_layout.addWidget(self.video_widget)left_layout.addWidget(self.label_time, alignment=Qt.AlignRight)left_layout.addWidget(self.timeSlider)left_layout.addLayout(button_layout)left_layout.addSpacing(100)left_layout.addWidget(QLabel("视频路径:"))left_layout.addWidget(self.path_entry)# 中间布局middle_layout = QVBoxLayout()middle_layout.addLayout(grid_layout)# 右侧布局right_layout = QVBoxLayout()right_layout.addWidget(self.done_button)# 总布局all_layout = QHBoxLayout()all_layout.addLayout(left_layout)all_layout.addLayout(middle_layout)all_layout.addLayout(right_layout)self.setLayout(all_layout)self.showMaximized()# 打开视频def open_file(self):a = QFileDialog.getOpenFileUrl()[0]self.video_path = a.toString()self.player.setMedia(QMediaContent(a)) # 选取视频文件msg = QMessageBox.information(self, '提示', "已经打开视频文件")self.path_entry.setText(self.video_path)# 调节播放进度def change_time(self, num):self.player.setPosition(num)# 快进def up_time(self):# print(self.player.duration())# num = self.player.position() + int(self.player.duration() / 20)num = self.player.position() + 200self.player.setPosition(num)# 快退def down_time(self):# num = self.player.position() - int(self.player.duration() / 20)num = self.player.position() - 200self.player.setPosition(num)# 获取进度条进度def get_time(self, num):self.timeSlider.setMaximum(self.player.duration())self.timeSlider.setValue(num)frame_count = int(num / 1000 * 30)# d = QDateTime.fromMSecsSinceEpoch(num).toString("mm:ss")# print(d)all = self.player.duration()total_count = int(all / 1000 * 30)# all_d = QDateTime.fromMSecsSinceEpoch(all).toString("mm:ss")self.label_time.setText(str(frame_count) + '/' + str(total_count))def closeEvent(self, event): # 关闭前需要self.player.pause()操作,否则报错self.player.pause()reply = QMessageBox.question(self, '提示',"是否退出",QMessageBox.Yes | QMessageBox.No,QMessageBox.No)if reply == QMessageBox.Yes:event.accept()else:event.ignore()def save_start_time(self):if self.save_flag == 0:self.save_flag = 1start_time = self.player.position()start_frame = int(start_time / 1000 * 30)self.entry_names[self.save_start_count-1].setText(str(start_frame))self.save_start_count += 2QMessageBox.information(self, "保存成功", f"已保存当前时间点:第{start_frame}帧 ")else:QMessageBox.information(self, "保存失败", f"请先保存动作结束时间 ")def save_end_time(self):if self.save_flag == 1:self.save_flag = 0end_time = self.player.position()end_frame = int(end_time / 1000 * 30)self.entry_names[self.save_end_count-1].setText(str(end_frame))self.save_end_count += 2QMessageBox.information(self, "保存成功", f"已保存当前时间点:第{end_frame}帧 ")else:QMessageBox.information(self, "保存失败", f"请先保存动作开始时间 ")def save_json(self):result = {}single_part = {}video_path = self.video_pathprint('当前保存结果来源于视频文件', video_path)result['video_path'] = video_pathresult['split_result'] = []# video_path: 'file:///D:/SplitVideo/dmh2.avi'file_path = re.split('/', video_path)[-1] + '.json'for i in range(len(self.entry_names)):if self.entry_names[i].text() != '':if (i + 1) % 2 == 1:label_key = f"start_frame_d{int((i + 1) // 2 + 1)}:"else:label_key = f"end_frame_d{int((i + 1) / 2)}:"single_part[label_key]= int(self.entry_names[i].text())# print(self.single_part)result['split_result'].append(single_part)with open(file_path, 'w') as f:json.dump(result, f)if __name__ == '__main__':app = QApplication(sys.argv)app.aboutToQuit.connect(app.deleteLater)win = VideoWin()win.show()sys.exit(app.exec())
相关文章:

pyqt5 制作视频剪辑软件,切割视频
该软件用于切割视频,手动选取视频片段的起始帧和结束帧并保存为json文件。gui界面如下:包含快进、快退、暂停等功能, 代码如下: # codingUTF-8 """ theme: pyqt5实现动作起始帧和结束帧的定位,将定位到…...
VUE----通过nvm管理node版本
使用 NVM(Node Version Manager)来管理和切换 Node.js 版本是一个很好的选择。以下是在 苹果电脑macos系统 上使用 NVM 安装和切换 Node.js 版本的步骤: 1. 安装 NVM 如果你还没有安装 NVM,可以按照以下步骤进行安装:…...
R语言进行字符的替换和删减gsub,substr函数
目录 R语言读文件“-“变成“.“ 提取列字符前几个 提取列字符末尾几个 进行字母替换 paste0函数使用 长宽数据转换 R语言读文件“-“变成“.“ R语言读文件“-“变成“.“_r语言 列名中的-变成了点-CSDN博客 怎样将"."还原为"-" rm(list = ls()…...

2024年6月27日,欧盟REACH法规新增第31批1项SVHC高关注物质
ECHA公布第31批1项SVHC,物质已增至241项 2024年6月27日,ECHA公布第31批1项SVHC,总数达241项。新增物质未包括磷酸三苯酯,仍在评议中。REACH法规要求SVHC含量超0.1%需告知下游,出口超1吨须通报ECHA。SCIP通报要求SVHC含…...

高通410-linux棒子设置网络驱动
1.首先打开设备管理器 2.看到其他设备下的RNDIS,右键更新驱动程序 3.点击浏览我的电脑… 最后一个...
PostgreSQL的系统视图pg_stat_archiver
PostgreSQL的系统视图pg_stat_archiver 在 PostgreSQL 数据库中,pg_stat_archiver 视图提供了关于归档进程(archiver process)的统计信息。归档进程负责将 WAL(Write-Ahead Logging)日志文件复制到归档存储࿰…...

【D3.js in Action 3 精译】第一部分 D3.js 基础知识
第一部分 D3.js 基础知识 欢迎来到 D3.js 的世界!可能您已经迫不及待想要构建令人惊叹的数据可视化项目了。我们保证,这一目标很快就能达成!但首先,我们必须确保您已经掌握了 D3.js 的基础知识。这一部分提到的概念将会在您后续的…...
面试经验分享 | 渗透测试工程师(实习岗)
所面试的公司:某安全厂商 所在城市:南京 面试职位:渗透测试工程师实习岗位 面试过程: 腾讯会议(视频) 面试过程:整体流程就是自我介绍加上一些问题问题balabalabala。。。由于面的岗位是渗透…...

STM32 IWDG(独立看门狗)
1 IWDG简介 STM32有两个看门狗:一个是独立看门狗(IWDG),另外一个是窗口看门狗。独立看门狗也称宠物狗,窗口看门狗也称警犬。本文主要分析独立看门狗的功能和它的应用。 独立看门狗用通俗一点的话来解释就是一个12位的…...
ios swift5 获取wifi列表
参考博客: iOS之Wifi开发探究 - 稀土掘金 iOS 无法获取 WiFi 列表?一定是因为你不知道这个框架 - 稀土掘金 iOS获取Wifi列表详解 - 简书...
回溯法c++学习 解决八皇后问题
使用回溯法解决八皇后问题 八皇后问题是一个以国际象棋为背景的问题:如何能够在88 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。这…...

5. Spring IoCDI ★ ✔
5. Spring IoC&DI 1. IoC & DI ⼊⻔1.1 Spring 是什么?★ (Spring 是包含了众多⼯具⽅法的 IoC 容器)1.1.1 什么是容器?1.1.2 什么是 IoC?★ (IoC: Inversion of Control (控制反转))总…...

数据库自动备份到gitee上,实现数据自动化备份
本人有个不太好的习惯,每次项目的数据库都是在线上创建,Navicat 连接线上数据库进行处理,最近有一个项目需要二次升级,发现老项目部署的服务器到期了,完蛋,数据库咩了!!!…...
探索 Spring Cloud Gateway:构建微服务架构的关键一环
1. 简介 在当今的分布式系统中,微服务架构已经成为了一种流行的架构模式。在微服务架构中,服务被拆分为小型、可独立部署的服务单元,这些服务单元能够通过网络互相通信,形成一个整体的应用系统。然而,随着微服务数量的…...
P1114 “非常男女”计划最优解
原题地址 P1114 “非常男女”计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码题解 AC代码(1) 因为用的是级的算法,所以最后一个 了,这里使用特判来得到的,给你们放一下代码: #include <bi…...

C++ | Leetcode C++题解之第187题重复的DNA序列
题目: 题解: class Solution {const int L 10;unordered_map<char, int> bin {{A, 0}, {C, 1}, {G, 2}, {T, 3}}; public:vector<string> findRepeatedDnaSequences(string s) {vector<string> ans;int n s.length();if (n < L…...
构建、标记和发布镜像
构建、标记和发布镜像 目录 构建镜像标记镜像发布镜像实践 设置构建镜像推送镜像 在本指南中,您将学习以下内容: 构建镜像:基于Dockerfile构建镜像的过程。标记镜像:为镜像命名的过程,这也决定了镜像的分发位置。发…...

[Go Web] Kratos 使用的简单总结
文章目录 1.Kratos 简介2.传输协议3.日志4.错误处理5.配置管理6.wire 1.Kratos 简介 Kratos并不绑定于特定的基础设施,不限定于某种注册中心,或数据库ORM等,所以您可以十分轻松地将任意库集成进项目里,与Kratos共同运作。 API -&…...

首个实时 AI 视频生成技术发布;科大讯飞发布星火大模型 4.0 丨 RTE 开发者日报
开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…...
什么是容器镜像
什么是容器镜像? 1. 容器镜像的两个重要原则 容器镜像是容器化应用程序的基础,它包含了运行应用程序所需的一切——代码、运行时、库和依赖项。理解容器镜像的两个重要原则非常重要: 不可变性:容器镜像一旦构建,就不…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...

使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...