PyQt+moviepy音视频剪辑实战2:一个剪裁视频文件精华内容留存工具的实现
一、引言
最近网上会议很多,网上会议工具大多提供了录播的功能,有些会议内容比较精彩,但中间穿插有些无用的内容,或者有些只有几段精彩,大部分内容可以去除。这就需要对该录播文件进行剪辑,取其精华留存,这样可以节约后续重温或者给其他人共享的时间。本文介绍的开发方法就是要实现这样的一个工具。
二、背景知识介绍
2.1、视频的读取和输出保存
本部分知识请参考《moviepy音视频剪辑:音视频的加载和输出》或专栏《PyQt+moviepy音视频剪辑实战》相关文章即可。
2.2、视频的截取
视频的截取使用subclip方法,该方法为clip类的方法,moviepy中clip类是所有剪辑的基类。
语法如下: subclip(self, t_start=0, t_end=None)
2.3、视频的拼接
本节的案例是从同一个视频取几段顺序拼接合成,这些段的分辨率相同,因此可以用保持分辨率拼接和统一分辨率拼接都可以,相关知识请参考《moviepy音视频剪辑:多个视频合成一个视频》或专栏《PyQt+moviepy音视频剪辑实战》相关文章即可。
三、图形界面设计
本程序除了主界面之外的部分都是复用《PyQt+moviepy音视频剪辑实战1:多个音视频合成顺序播放或同屏播放的视频文件实现详解》、《PyQt+moviepy音视频剪辑实战1:多视频合成顺序播放或同屏播放的视频文件》的公用框架。
主界面如下:
该界面的不同部分留了过多的空间,这是为了要在底部动态构建一个停靠窗部件用于显示输出信息使用。
四、代码实现
4.1、主界面类及构造方法
class mainWin(QtWidgets.QMainWindow,ui_multiSegmentClip.Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.initValues()
self.initSignalAndSlots()
self.initPublicFrame()
4.2、槽和信号连接方法initSignalAndSlots
def initSignalAndSlots(self):
self.btn_choiceSrc.clicked.connect(self.chooseFile)
self.videoFile.textChanged['QString'].connect(self.fileNameInputed)
self.btn_choiceDest.clicked.connect(self.chooseFile)
self.startPos.editingFinished.connect(self.getDestFName)
self.endPos.editingFinished.connect(self.getDestFName)
self.actionmergeClips.triggered.connect(self.convert)
self.actionridClips.triggered.connect(self.convert)
4.3、视频文件、输出文件手工输入或选择方法
def fileNameInputed(self,fname=None): #源视频文件手工输入编辑完成后调用本方法
ret = False
if not fname or fname==True:fname = self.videoFile.text()
if self.srcDir:
dir = QtCore.QDir(self.srcDir)
ret = dir.exists(fname)
self.actionmergeClips.setEnabled(ret)
self.actionridClips.setEnabled(ret)
self.getDestFName()
def chooseFile(self): #点击输出文件选择或视频文件选择调用本槽方法用于选择文件
btnName = self.sender().objectName()
if btnName == 'btn_choiceSrc':
if self.srcDir:fname = self.srcDir
else:fname = ""
fileName = self.fileDialog.getOpenFileName(self, "选择视频文件",fname, "video Files (*.mp4)")# *.wmv *.rm *.avi *.flv *.webm *.wav *rmvb )")
if fileName[0]=='':return
fileName = QtCore.QDir.toNativeSeparators(fileName[0])
self.videoFile.setText(fileName)
self.fileNameInputed(fileName)
else:
if self.destDir: fname = self.destDir
else: fname = r""
fileName = self.fileDialog.getSaveFileName(self, "选择要保存的视频存储文件",fname,"video Files (*.mp4)")# *.wmv *.rm *.avi *.flv *.webm *.wav *rmvb)")
if fileName[0] == '': return
fileName = QtCore.QDir.toNativeSeparators(fileName[0])
self.saveFile.setText(fileName)
destDir = fileName.rsplit('\\',1)[0]
self.destDir = destDir
print(self.destDir)
def getDestFName(self): #根据视频文件和视频剪辑时间段设置自动生成一个输出文件名
srcFile = self.videoFile.text()
if not srcFile:return
file_pre, file_type = srcFile.split('.')
if not file_type: return
##计算文件名长度是否小于255
lenPre = len(file_pre)
segStart = self.startPos.text().strip(" \r\n")
segEnd = self.endPos.text().strip(" \r\n")
lenSegStart = len(segStart)
lenSegEnd = len(segEnd)
if (lenPre + lenSegStart + lenSegEnd) > 240:
lenSeg = (240 - lenPre) / 2
segStart = segStart[0:lenSeg]
segEnd = segEnd[0:lenSeg]
else:
segStart = segStart[0:]
segEnd = segEnd[0:]
self.videoFName = file_pre +'_'+segStart+ '_' + segEnd + '.'+file_type
self.videoFName = self.videoFName.replace(',','_')
destDir = file_pre.rsplit('\\', 1)[0]
self.srcDir = destDir
self.destDir = destDir
self.saveFile.setText(self.videoFName)
4.4、视频拼接处理方法
def convertByMoviepy(self,srcFile,destFile,isMergeClip)://执行视频拼接处理
paths = destFile.rsplit('\\',1)
if len(paths)==2:
path = paths[0]
fname = paths[1]
else:
fname = destFile
path = ''
if isMergeClip:
fname = 'merge_'+fname
else:fname = 'rid_'+fname
if path=='':destFile = fname
else:destFile = path+'\\'+fname
print("执行视频提取开始,源文件:",srcFile,' --> 目标文件:',destFile)
start = time.clock()
print(start)
try:
validClipDistance = self.validateSlipDistance(isMergeClip)
if not validClipDistance:return
videoFile = mpe.VideoFileClip(srcFile)
print(f"视频总长:{videoFile.duration}秒")
self.destClip = None
destClip = None
for dist in validClipDistance:
destClip = self.mergeClip(videoFile,dist)
print("开始写目标文件.")
destClip.write_videofile(destFile)
print("目标文件生成完成")
videoFile.close()
destClip.close()
print("执行视频提取成功,保存在文件:", destFile)
except Exception as e:
info = f"视频文件无法读取,可能是因为格式不支持:{e}"
print(info)
print("任务无法执行!")
finally:
print("处理耗时(秒):",time.clock()-start)
def mergeClip(self,clip,distance):#从clip取distance指定的视频段合并到输出剪辑 self.destClip
start, end = distance
try:
duration = int(clip.duration)
if end>duration:end = duration
if start>duration:start = duration
if not end:end = duration
subClip = clip.subclip(start,end)
if self.destClip:
self.destClip = mpe.concatenate_videoclips([self.destClip, subClip])
else: self.destClip = subClip
except Exception as e:
print(f"合并片段:{start}--{end}失败,原因:{e}")
return None
else:
print(f"合并片段:{start}--{end}成功")
return self.destClip
五、运行界面
5.1、初始主界面
主界面上可以选择视频源文件、设定视频段,不过视频段的设置比较简陋,所有开始位置用英文逗号分隔放在“视频段开始位置”后面的编辑框中,结束位置放在“视频段结束位置”,两者数字和逗号都是纯ASCII半角字符,且二者的数字和逗号个数相等,且必须从低到高排列、除最后一个外结束位置必须大于开始位置,如果结束位置为0,则表示到视频最后。
5.2、进行视频裁剪的运行过程界面
这是从F:\video\顺流逆流.mp4取0-3秒和20-25秒两段视频合并成一个视频输出。如果是指定视频段输出,输出文件名以merge开头,否则以rid开头。
六、打包成windows执行文件
使用《PyQt(Python+Qt)学习随笔:windows下使用pyinstaller将PyQt文件打包成exe可执行文件》介绍的方法进行打包。
老猿前不久用该工具实现了对一个长达150多分账的视频会议录播视频的23处精华内容进行了剪裁合并,最终生成文件为43分钟。不过在处理前要观看视频确认需要留存内容。
在win7、win10上可运行的可执行程序包已经上传到百度云,大家可以下载下来长期免费使用。具体下载地址为百度网盘。
链接:https://pan.baidu.com/s/1UNaA2UqQBoxx-v8rCIPDhA
提取码:yh2d
选择该链接下的:视频剪裁工具1.0.rar 即可。
注意:
百度云上分享的《咖啡狗免费工具软件共享空间》下的不同软件安装时必须解压到不同目录,如果解压到同一目录可能有冲突导致不能正常运行,
但解压后遵循如下要求可以将其聚合到同一个目录:
- 放置到同一目录的不同软件的版本必须相同,版本为压缩文件名中VX.X标注;
- 聚合拷贝时除拷贝执行文件外,还有resource目录必须拷贝,如果resource目录下有相同文件名可以覆盖;
- 聚合拷贝exe文件和resource目录及其下文件到其他已解压工具目录后,源目录可以删除。
更多moviepy的介绍请参考《PyQt+moviepy音视频剪辑实战文章目录》或《moviepy音视频开发专栏》。
关于收费专栏
老猿的付费专栏《使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,付费专栏《moviepy音视频开发专栏》详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,两个专栏加起来只需要19.9元,都适合有一定Python基础但无相关专利知识的小白读者学习。这2个收费专栏都有对应免费专栏,只是收费专栏的文章介绍更具体、内容更深入、案例更多。
收费专栏文章目录:《moviepy音视频开发专栏文章目录》、《使用PyQt开发图形界面Python应用专栏目录》,本文收费专栏对应文章为《PyQt+moviepy音视频剪辑实战2:实现一个剪裁视频文件精华内容留存工具》。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《专栏:Python基础教程目录》从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。
跟老猿学Python、学5G!
PyQt+moviepy音视频剪辑实战2:一个剪裁视频文件精华内容留存工具的实现的更多相关文章
- PyQt+moviepy音视频剪辑实战2:实现一个剪裁视频文件精华内容留存工具
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.引言 ...
- PyQt+moviepy音视频剪辑实战1:多视频合成顺序播放或同屏播放的视频文件
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.引言 在<moviepy音视频剪辑:音视 ...
- PyQt+moviepy音视频剪辑实战文章目录
☞ ░ 前往老猿Python博文目录 ░ 本专栏为moviepy音视频剪辑合成相关内容介绍的免费专栏,对应的收费专栏为<moviepy音视频开发专栏>. 一.moviepy基础能力系统介绍 ...
- PyQt+moviepy音视频剪辑实战1:多个音视频合成顺序播放或同屏播放的视频文件实现详解
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一. ...
- Moviepy音视频开发:视频转gif动画或jpg图片exe图形化工具开发案例
☞ ░ 前往老猿Python博文目录 ░ 一.引言 老猿之所以学习和研究Moviepy的使用,是因为需要一个将视频转成动画的工具,当时在网上到处搜索查找免费使用工具,结果找了很多自称免费的工具,但转完 ...
- moviepy音视频剪辑:使用concatenate_videoclips和clips_array将多个视频合成一个顺序播放或同屏播放的视频
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.视频合成概述 视频合成,也称为非线性编辑,实际 ...
- moviepy音视频开发:音频剪辑基类AudioClip
☞ ░ 前往老猿Python博文目录 ░ 一.背景知识介绍 1.1.声音三要素: 音调:人耳对声音高低的感觉称为音调(也叫音频).音调主要与声波的频率有关.声波的频率高,则音调也高. 音量:也就是响度 ...
- moviepy音视频剪辑:AudioClip帧处理时报TypeError: only size-1 arrays can be converted to Python scalar错
☞ ░ 前往老猿Python博文目录 ░ 一.环境 操作系统:win7 64位 moviepy:1.0.3 numpy:1.19.0 Python:3.7.2 二.应用代码及报错信息 程序代码 if ...
- moviepy音视频剪辑:视频变换处理与内容相关的变换函数headblur、mask_and/or、mirror_x/y、rotate、painting、scroll介绍
一.引言 在<moviepy音视频剪辑:moviepy中的剪辑基类Clip详解>介绍了剪辑基类的fl.fl_time.fx方法,在<moviepy音视频剪辑:视频剪辑基类VideoC ...
随机推荐
- SAP S/4HANA 2020安装实录
欢迎关注微信公众号:sap_gui (ERP咨询顾问之家) 今天开始试着安装SAP S/4HANA 2020版本,也是目前SAP ERP最高的版本,总安装文件大小大概50GB,数据库版本必须是HANA ...
- 【故障公告】Memcached 的“惹祸”,不知在为谁背锅
在 .NET 5.0 背锅 . Memcached 的惹祸 .缓存雪崩之后,我们没有找到问题的真正原因,我们知道没有找到根源的故障总是会再次光临的,不是在这周就是在下周,也许就在双11前后. 就在今天 ...
- 腾讯云--对象存储cos绑定自定义域名
1.登录腾讯云控制台,找到对象存储一栏 2.选择一个你想绑定域名的存储桶 3.进入你选择的存储桶,点击域名管理 4.选择自定义源站域名.在域名处填写你要设置的自定义域名,在源站类型处选择静态网站源站, ...
- 后端狗的Vue学习历程(一) - demo示例与基本逻辑语法
目录 demo的三部分结构 判断:v-if.v-else-if.v-else 循环:v-for 事件绑定 v-on:eventType 内容输入的双向绑定v-model 源码:Github demo的 ...
- VirtualBox上桥接方式安装CentOS之后借助宿主上网
VirtualBox上桥接方式安装CentOS之后借助宿主上网: 修改centos文件: 1 vi /etc/sysconfig/network-scripts/ifcfg-eth0 增加以下几项: ...
- [MIT6.006] 4. Heaps and Heap Sort 堆,堆排序
第4节课仍然是讲排序,但介绍的是一种很高效的堆排序. 在编程过程中,有时候会需要进行extrat_max的操作,即从一个数列里挨个抽取最大值并将其它从原数列中移除.而排序问题也可以看作是一个extra ...
- spark-submit提交python脚本过程记录
最近刚学习spark,用spark-submit命令提交一个python脚本,一开始老报错,所以打算好好整理一下用spark-submit命令提交python脚本的过程.先看一下spark-submi ...
- 分库分表神器 Sharding-JDBC,几千万的数据你不搞一下?
今天我们介绍一下 Sharding-JDBC框架和快速的搭建一个分库分表案例,为讲解后续功能点准备好环境. 一.Sharding-JDBC 简介 Sharding-JDBC 最早是当当网内部使用的一款 ...
- SSTI Flask
1.什么是SSTI?什么是Flask? SSTI称为服务端模板注入,主要为Python.Java.PHP的框架在使用渲染函数时,由于代码不规范或者对于用户输入过于信任而导致产生了SSTI.类似于S ...
- Tomcat口令暴力猜解&&后台getshell
Tomcat环境搭建 windows系统xampp搭建tomcat linux yum搭建tomcat 修改tomcat目录下的conf/tomcat-users.xml文件开启管理后台口令认证 &l ...