python视频转码脚本

今天有一个临时的需求,就是需要将一个wmv的初步转码成mp4的格式。找了一圈,免费的工具少,即使有免费的工具,在功能上也是有所限制,或者会给你塞广告或者附带安装其它流氓小游戏或者杀毒程序。

我并非不支持正版,我本人不是专业的视频创作者,平日里对视频转码编辑的需求极少,为这临时需要而买个正常软件,一没必要,二不划算。

FFmpeg 是一个强大的开源视频工具包,通过命令行可以轻易的将一个 wmv 文件转码成需要的目标格式文件,例如转码成mp4

Python 也是个很好用的脚本语言。为可以快速的搜索视频文档,然后对其进行转码操作,使用Python写了一个简单的脚本,该脚本可以借助Everything的强大搜索功能,协助用户快速的搜索定位需要转码的文档,然后对其进行转码。

Python 脚本

Python脚本比较简单,逻辑也比较清晰。截图如下:

20240511141928

如👆上图所示,脚本首先定义了一个命令行入参的类,用于管理和解析命令行传入的参数。
然后定义了一个小的函数,这个函数并不是核心功能,仅用于对比两个指定的字符串中的差异。

在主程序中(if __name__ == '__main__'部分),脚本首先解析了来自命令行的参数;
然后定义了一个Everything搜索接口对象(该Everything搜索接口对象提供了基于Everything的搜索功能),用于协助用户快速的搜索定位兴趣文档。

在功能逻辑循环体中,首先引导用户搜索定位待转码的视频文档;然后与用户交互确定转码的目标格式;最后借助 moviepy这个Python包完成视频转码操作。

以上,脚本逻辑清晰自然,贴出Python代码如下👇。

# -*- coding:UTF-8 -*-
"""
@author: dyy
@contact: douyaoyuan@126.com
@time: 2024/5/10 21:40
@file: 视频转码.py
@desc: xxxxxx
"""

# region 引入必要的依赖
import os

模块名 = 'DebugInfo'
try:
    from DebugInfo.DebugInfo import *
except ImportError as impErr:
    print(f"尝试导入 {模块名} 依赖时检测到异常:{impErr}")
    print(f"尝试安装 {模块名} 模块:")
    try:
        os.system(f"pip install {模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {模块名} 时检测到异常:{osErr}")
        exit(0)
    else:
        try:
            from DebugInfo.DebugInfo import *
        except ImportError as impErr:
            print(f"再次尝试导入 {模块名} 依赖时检测到异常:{impErr}")
            exit(0)

模块名 = 'difflib'
try:
    import difflib  # 需要安装 difflib 模块,以支持字符差异对比操作
except ImportError as impErr:
    print(f"尝试导入 {模块名} 依赖时检测到异常:{impErr}")
    print(f"尝试安装 {模块名} 模块:")
    try:
        os.system(f"pip install {模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {模块名} 时检测到异常:{osErr}")
        exit(0)
    else:
        try:
            import difflib
        except ImportError as impErr:
            print(f"再次尝试导入 {模块名} 依赖时检测到异常:{impErr}")
            exit(0)

模块名 = 'moviepy'
try:
    from moviepy.editor import VideoFileClip  # 需要引入 moviepy 模块,以支持视频转码的操作
except ImportError as impErr:
    print(f"尝试导入 {模块名} 依赖时检测到异常:{impErr}")
    print(f"尝试安装 {模块名} 模块:")
    try:
        os.system(f"pip install {模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {模块名} 时检测到异常:{osErr}")
        exit(0)
    else:
        try:
            from moviepy.editor import VideoFileClip
        except ImportError as impErr:
            print(f"再次尝试导入 {模块名} 依赖时检测到异常:{impErr}")
            exit(0)
# endregion

# 定义一个 命令行参数类,用于解析和记录命令行参数
class 命令行参数类(入参基类):
    def __init__(self):
        super().__init__()
        self._添加参数('搜索关键字', str, '指定文档搜索的关键字')
        self._添加参数('everything服务端口', str, 'everything HTTP 服务端口', '22')

    # region 访问器
    @property
    def jsonCfg(self) -> str:
        if 'jsonCfg' in self._参数字典:
            return self._参数字典['jsonCfg'].else:
            return ''

    @jsonCfg.setter
    def jsonCfg(self,: str):
        if 'jsonCfg' in self._参数字典:
            self._参数字典['jsonCfg'].= str()

    @property
    def 搜索关键字(self) -> str:
        if '搜索关键字' in self._参数字典:
            return self._参数字典['搜索关键字'].else:
            return ''

    @搜索关键字.setter
    def 搜索关键字(self,: str):
        if '搜索关键字' in self._参数字典:
            self._参数字典['搜索关键字'].= str()

    @property
    def everything服务端口(self) -> str:
        if 'everything服务端口' in self._参数字典:
            return self._参数字典['everything服务端口'].else:
            return ''

    @everything服务端口.setter
    def everything服务端口(self,: str):
        if 'everything服务端口' in self._参数字典:
            self._参数字典['everything服务端口'].= str()
    # endregion


# 标注两个字符串的差异项
def 差异标注(字串1: str, 字串2: str) -> tuple[str, str]:
    字串1 = str(字串1 if 字串1 else '').strip()
    字串2 = str(字串2 if 字串2 else '').strip()

    # region 原文档变动对齐
    # 使用SequenceMatcher()类计算两个字符串的相似度
    匹配器 = difflib.SequenceMatcher(None, 字串1, 字串2)
    差异 = 匹配器.get_opcodes()

    # 差异标注
    字串1差异标注: str = ''
    字串2差异标注: str = ''
    for opcode, i1, i2, j1, j2 in 差异:
        if opcode == 'equal':
            字串1差异标注 = 字串1差异标注 + 字串1[i1:i2]
            字串2差异标注 = 字串2差异标注 + 字串2[j1:j2]
        elif opcode == 'delete':
            字串1差异标注 = 字串1差异标注 + 红字(字串1[i1:i2])
        elif opcode == 'insert':
            字串2差异标注 = 字串2差异标注 + 绿字(字串2[j1:j2])
        elif opcode == 'replace':
            字串1差异标注 = 字串1差异标注 + 红字(字串1[i1:i2])
            字串2差异标注 = 字串2差异标注 + 绿字(字串2[j1:j2])

    return 字串1差异标注, 字串2差异标注


if __name__ == '__main__':
    画板 = 打印模板(False)
    画板.执行位置(__file__)

    # region 解析入参
    入参 = 命令行参数类()
    入参.解析Json(画板=画板.副本.缩进())
    入参.解析入参(画板=画板.副本.缩进())
    if 画板.正在调试:
        入参.展示(画板=画板.副本.缩进())

    搜索关键字: str = 入参.搜索关键字 if 入参.搜索关键字 else ''
    # endregion

    # region 定义搜索接口
    本地搜索: 搜索接口类 = 搜索接口类()
    if 在nt系统中():
        if 入参.everything服务端口:
            本地搜索.everything服务端口 = int(入参.everything服务端口)
        else:
            画板.提示错误('入参.everything服务端口 参数无效')
            exit(1)
    # endregion

    # region 开始逻辑循环
    while True:
        def 文档排除规则(文档: str) -> bool:  # 排除一些不必要的干扰文档
            if not 文档:  # 空文档不要
                return True
            if '\\recent\\' in 文档.lower():  # recent 文档夹内的文档不要
                return True
            if 文档.lower().endswith('.lnk'):  # *.lnk 文档不要
                return True

        # region 引导用户选择需要转码的视频文档
        while True:
            原视频文档列表 = 交互接口类.指定选择文档(输入提示='请输入关键字以定位视频文档(0: 退出程序):',
                                                 搜索接口=本地搜索,
                                                 搜索关键字=搜索关键字,
                                                 候选项上限=250,
                                                 排除规则=文档排除规则,
                                                 多选=True,
                                                 画板=画板.副本.缩进())
            if '0' in 原视频文档列表:
                # 用户要求退出程序
                exit(0)

            if 原视频文档列表:
                画板.消息('您选择的文档列出如下:')
                for 文档 in 原视频文档列表:
                    画板.消息(绿字(文档))
                break
        # endregion

        # region 目标格式信息交互
        目标视频文档列表: list[str] = []
        while True:
            目标格式后缀名: str = 交互接口类.发起文本交互(输入提示='请输入视频目标格式(0: 退出程序):',
                                                          画板=画板.副本.缩进())
            if '0' == 目标格式后缀名:
                # 用户要求退出程序
                exit(0)

            if 目标格式后缀名.startswith('。'):
                目标格式后缀名 = f'.{目标格式后缀名[1:]}'
            if not 目标格式后缀名.startswith('.'):
                目标格式后缀名 = f'.{目标格式后缀名}'

            if not 目标格式后缀名.strip('.'):
                # 如果后缀名是空的,则重新要求输入
                continue

            # 后缀名统一转换成小写格式
            目标格式后缀名 = 目标格式后缀名.lower()

            # 合成目标文档名:
            for 文档 in 原视频文档列表:
                目标视频文档列表.append(f'{文档}{目标格式后缀名}')

            # 打的并提示用户确认转换方式
            画板.消息(黄字('即将启动的视频转码如下:'))
            画板.准备表格(对齐控制串='rl')
            for 序号 in range(len(原视频文档列表)):
                原文档,目标文档 = 差异标注(原视频文档列表[序号],目标视频文档列表[序号])
                画板.添加一行(原文档,洋红字('->'),目标文档)
            画板.展示表格(列间距=[0,0])

            转码确认: str = 交互接口类.发起文本交互(输入提示='是否确认转码?(y: 确认; n: 修改目标格式; 0: 退出程序)',
                                                    限定范围='YyNn0',
                                                    画板=画板.副本.缩进())
            if '0' == 转码确认:
                # 用户要求退出
                exit(0)
            elif 'y' == 转码确认.lower():
                # 用户确认转码
                break
        # endregion

        # region 开始视频转码
        编解码格式: str = ''
        for 序号 in range(len(原视频文档列表)):
            视频切片 = VideoFileClip(原视频文档列表[序号])
            while True:
                if not 编解码格式:
                    编解码格式 = 交互接口类.发起文本交互(输入提示=f'默认 codec 参数是 libx264, 输入 {绿字("y")} 以确认; '
                                                                  f'或者您可以输入其它编码格式({红字("0")}: {红字("退出程序")}):',
                                                         画板=画板.副本.缩进())
                if '0' == 编解码格式:
                    # 用户要求退出程序
                    exit(0)
                编解码格式 = 编解码格式.lower()
                if 'y' == 编解码格式:
                    # 用户确认使用 libx264 作为 codec 参数
                    编解码格式 = 'libx264'

                try:
                    if 目标格式后缀名.endswith('gif'):
                        视频切片.write_gif(filename=目标视频文档列表[序号])
                    elif 编解码格式:
                        视频切片.write_videofile(filename=目标视频文档列表[序号], codec=编解码格式)
                    else:
                        视频切片.write_videofile(filename=目标视频文档列表[序号])
                except Exception as exp:
                    画板.提示错误('视频转码遇到异常如下:')
                    画板.消息(exp.__str__())

                    # 清除 codec 参数,重新发起交互
                    编解码格式 = ''
                    continue
                else:
                    # 如果转码顺利完成,则关闭 视频切片,开始下一段视频的处理
                    视频切片.close()
                    break
        # endregion
    # endregion

使用演示

👉第一步,脚本首先引导用户搜索和定位视频文件,我们可以输入视频文件名信息以定位视频文档,然后参过序号选择目标文档;如下👇:
20240511144403

👉第二步,脚本询问我们需要将视频文档转换为什么样的目标格式,我们输入目标文档的后缀名,然后再一次确认脚本的问询;如下👇:
20240511144652
在这一步中,如果我们输入了错误的目标格式,我们还可以输入 n 来重新修改目标格式。

👉第三步,脚本会询问我们是否使用默认的 codec 参数(默认为libx264)进行视频转码,如果我们希望使用其它 codec 参数,例如 png,或者libvorbis 等,我们也可以直接输入 codec 值来告诉脚本;如下👇:
Snipaste_2024-05-11_14-51-48
Snipaste_2024-05-11_14-51-52
以上👆脚本交互完成后,脚本即开始了视频转码过程,我们耐心等待转码完成即可,如下👇:
20240511145705

懒人包

以上Python脚本的功能比较简单,对于视频转码的参数控制较少,但如果大家有需要,可以轻易的加入更多的转码参数控制功能。

以上 Python脚本,对应的bat调用脚本,和对应的cfg参数文档,统一进行了打包,见:Python 视频转码脚本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/616158.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue 点击平滑到指定位置并绑定页面滑动效果

1.html元素 写出对应的数据块&#xff08;注意添加ref) 用于获取元素位置 <template><div class"index-page" ><div class"top-head" ref"index"><img src"logo.png" style"height: 40px;margin-right: 2…

《解锁数字化劳动合同签约:构建高效的电子合同签约平台》

随着数字化转型的推进&#xff0c;传统的纸质劳动合同签约方式已经无法满足现代企业对于效率和便捷性的需求。电子劳动合同签约平台应运而生&#xff0c;为企业和员工提供了一种更加高效、便捷的合同签署方式。本文将介绍电子劳动合同签约平台的业务架构&#xff0c;探讨其如何…

地图涟漪效果

参考API echarts图表集 useEcharts.js import { onBeforeUnmount, onDeactivated } from "vue"; // import * as echarts from "echarts";/*** description 使用 Echarts (只是为了添加图表响应式)* param {Element} myChart Echarts实例 (必传)* param …

python代码学习案例-用turtle库绘制爱心图形效果

Python爱心代码&#xff0c;我们可以使用多种方法&#xff0c;包括使用turtle库来绘制图形&#xff0c;或者使用字符打印来在控制台中显示爱心。 首先&#xff0c;确保你已经安装了Python&#xff0c;并且你的环境支持turtle库&#xff08;它通常是Python标准库的一部分&#…

Coursera吴恩达深度学习专项课程01: Neural Networks and Deep Learning 学习笔记 Week 01

Week 01 of Neural Networks and Deep Learning Course Certificate 本文是学习 https://www.coursera.org/learn/neural-networks-deep-learning 这门课的笔记 Course Intro 文章目录 Week 01 of Neural Networks and Deep Learning[0] Welcome to the Deep Learning Spec…

Ansible常用变量【上】

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 在Ansible中会用到很多的变量&#xff0c;Ansible常用变量包括以下几种&#xff1a; 1. 自定义变量——在playbook中用户自定义…

基于遗传优化的双BP神经网络金融序列预测算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于遗传优化的双BP神经网络金融序列预测算法matlab仿真&#xff0c;采用的双BP神经网络结构如下&#xff1a; 2.测试软件版本以及运行结果展示 MATLAB2022A版本…

用户登录后端:登录密码解密后用PasswordEncoder验证密码是否正确

前置知识: 前端登录加密看用户登录 PasswordEncoder加密看PasswordEncoder详解 项目中因为要判断用户登录密码是否正确&#xff0c;通过输入错误次数锁住用户 1.后端配置rsa私钥 #密码加密传输&#xff0c;前端公钥加密&#xff0c;后端私钥解密 rsa:private_key: xxxx2. 读…

HCIP_BGP综合实验

一&#xff1a;实验拓扑&#xff1a; 二&#xff1a;实验要求&#xff1a; 1、AS1中存在两个环回&#xff0c;一个地址为192.168.1.0/24&#xff0c;该地址不能在任何协议中宣告; AS3中存在两个环回一个地址为192.168.2.0/24&#xff0c;该地址不能在任何协议中宣告&am…

JAVA课程设计

一&#xff1a;Java连接mysql数据库 1.1点击进入mysql jar包下载官网 MySQL :: MySQL Community Downloads 将下载好的压缩包进行解压 解压之后下图就是连接数据库所用到的jar包&#xff1a; 将jar包复制到IDEA所用的项目下&#xff0c;放置jar包的目录为lib&#xff0c;需要…

医院如何做好漏费管理?什么是控费系统?控费系统现在成熟吗?

在中国深厚的人情土壤之中&#xff0c;某些医院里的医技科室&#xff0c;宛如隐秘的灰色地带&#xff0c;悄然滋生着利用职务之便谋取私利的暗流。这些科室的医务人员&#xff0c;以低于医院明文规定的收费标准&#xff0c;私下里为熟识的患者提供检查服务&#xff0c;仿佛形成…

IM是什么意思?

IM&#xff08;即时通讯&#xff09;作为现代通讯领域的重要且普遍应用&#xff0c;已成为人们日常生活和工作中不可或缺的通信方式。随着科技的不断发展和互联网的普及&#xff0c;IM工具通过实时信息传递&#xff0c;将沟通变得更加迅速、便捷、高效。 IM的诞生极大地改变了…

探索全画面塑料焊接透光率检测仪的科技魅力

在精密工业和科研领域中&#xff0c;对材料的光学性能有着严格的要求。全画面塑料焊接透光率检测仪是一种先进的设备&#xff0c;它能够精确测量塑料焊接接头的透光率&#xff0c;确保焊接质量符合高标准。本文将详细介绍这一设备的特点、工作原理以及它在实际应用中的重要性。…

未授权访问:JBoss未授权访问漏洞

目录 1、漏洞原理  2、环境搭建 3、未授权访问 4、利用jboss.deployment getshell 防御手段 今天继续学习各种未授权访问的知识和相关的实操实验&#xff0c;一共有好多篇&#xff0c;内容主要是参考先知社区的一位大佬的关于未授权访问的好文章&#xff0c;还有其他大佬…

ppt转pdf的java实现

一、实现方式 java采用jacob包的功能&#xff0c;把ppt演示文稿转换为pdf。 支持文件格式&#xff1a;pptx,ppt 二、事先准备 1、依赖于office&#xff0c;需安装office办公软件 2、需要下载一个jacob-1.20-x64.dll的文件&#xff0c;放到java的bin目录下。 文件可以网上搜…

【DevOps】Linux 安全:iptables 组成、命令及应用场景详解

导读&#xff1a;全面掌握 iptables&#xff1a;从基础到实践 在 Linux 系统中&#xff0c;iptables 是一个非常强大的工具&#xff0c;它不仅是系统管理员用来构建和管理网络防火墙的首选工具&#xff0c;而且也是一个功能丰富的网络流量处理系统。无论是进行包过滤、监控网络…

二叉树进阶 --- 上

目录 1. 二叉搜索树的概念及结构 1.1. 二叉搜索树的概念 1.2. 二叉搜索树的结构样例 2. 二叉搜索树的实现 2.1. insert 的非递归实现 2.2. find 的非递归实现 2.3. erase 的非递归实现 2.3.1. 第一种情况&#xff1a;所删除的节点的左孩子为空 2.3.1.1. 错误的代码 2…

【工具篇】-什么是.NET

“.NET"&#xff1a;.NET Core是由Microsoft开发&#xff0c;目前在.NET Foundation(一个非营利的开源组织)下进行管理。.NET Core是用C#和C编写的&#xff0c;并采用MIT协议作为开源协议。 简单来说&#xff1a;就是开发框架。 .NET 又称 .NET 平台或 .NET 框架&#xf…

Container exited with a non-zero exit code 1

最近遇到运行yarn pi的时候遇到如下问题。 很明显是container出错了&#xff0c;但是错误没有提示的很清楚。然后去看nodemanager日志也是如此。这时候笔者第一个想到要去看container的执行日志。container具体的日志目录位置是通过YARN的配置文件&#xff08;如yarn-site.xml&…

JavaSE——集合框架一(1/7)-集合体系概述(集合体系结构,Collection集合体系)、Collection的常用方法(介绍,实例演示,代码)

目录 集合体系概述 集合体系结构 Collection集合体系 Collection的常用方法 介绍 实例演示 完整代码 集合体系概述 集合体系结构 集合是一种容器&#xff0c;用来装数据的&#xff0c;类似于数组&#xff0c;但集合的大小可变&#xff0c;开发中也非常常用。 为了满足…