Python---批量去视频的片头和片尾

news/2025/10/24 15:51:29/文章来源:https://www.cnblogs.com/e0yu/p/19163604

在需要对视频进行批量处理的时候,常见的就是批量去视频的片头和片尾:

具体代码示例:

import os
import re
import time
import subprocess
from decimal import Decimal
from multiprocessing import Poolpath = r'E:\FYZ2025\deleteAD\原视频'  # 原文件夹路径
new_path = r'E:\FYZ2025\deleteAD\新视频'  # 新文件夹路径
if not os.path.exists(new_path):os.mkdir(new_path)
else:pass# 获取视频的 duration 时长 长 宽
def get_video_length(file):process = subprocess.Popen(['ffmpeg', '-i', file],stdout=subprocess.PIPE,stderr=subprocess.STDOUT)stdout, stderr = process.communicate()# print(stdout)pattern_duration = re.compile(r"Duration:\s(\d+?):(\d+?):(\d+\.\d+?),")pattern_size = re.compile(r",\s(\d{3,4})x(\d{3,4})[\s or ,]")matches = re.search(pattern_duration, stdout.decode('utf-8'))size = re.search(pattern_size, stdout.decode('utf-8'))if size:size = size.groups()# print(size)if matches:matches = matches.groups()# print(matches)hours = Decimal(matches[0])minutes = Decimal(matches[1])seconds = Decimal(matches[2])  # 处理为十进制,避免小数点报错total = 0total += 60 * 60 * hourstotal += 60 * minutestotal += secondswidth = size[0]height = size[1]return {'total': total, 'width': width, 'height': height}def cutVideo(startPoint, file, endPoint, newFile):command = ['ffmpeg', '-ss', startPoint, '-i', file, '-acodec', 'copy', '-vcodec','copy', '-t', endPoint, newFile]subprocess.call(command)def millisecToAssFormat(t):  # 取时间,单位秒s = t % 60m = t // 60if t < 3600:h = 00else:h = t // 3600m = t // 60 - h * 60return '%02d:%02d:%02d' % (h, m, s)def main(dict):file = dict['file']  # 文件名piantou = dict['piantou']  # 片头时长pianwei = dict['pianwei']  # 片尾时长videoInfo = get_video_length(file)  # 视频信息# print(videoInfo)if videoInfo:duration = videoInfo.get('total')  # 时长 秒startPoint = piantou  # 剪掉片头时间,从原文件此处开始播放startPoint = millisecToAssFormat(startPoint)endPoint = duration - piantou - pianwei  # 剪掉片头片尾时间和,结果等于新文件总时长endPoint = millisecToAssFormat(endPoint)new_File = new_path + file.replace(path, '')  # 创建生成的文件路径+文件名# print(new_File, endPoint)
        cutVideo(startPoint, file, endPoint, new_File)if __name__ == '__main__':# main()timt0 = time.time()file = [os.path.join(path, file) for file in os.listdir(path)]a = input('输入片头时长:')  # 片头时长b = input('输入片尾时长:')  # 片尾时长piantou = [int(a)] * len(file)  # 片头时长列表pianwei = [int(b)] * len(file)  # 片尾时长列表dict_list = []  # main函数参数列表for x in range(len(file)):dict = {'file': file[x],'piantou': piantou[x],'pianwei': pianwei[x]}  # main函数参数,文件路径,片头片尾时长
        dict_list.append(dict)print('\n规则:去除片头%s秒片尾%s秒,开始。\n' % (a, b))pool = Pool()pool.map(main, dict_list)pool.close()pool.join()time1 = time.time() - timt0print('\n结束,处理%d个视频文件,共用时%.4f秒。\n' % (len(file), time1))input('回车键退出')

这个代码是基础的代码,片头和片尾的时长是秒。

但是我实际使用过程中,浮点的小数秒。

经过豆包AI的优化:

import os
import re
import time
import subprocess
from decimal import Decimal
from multiprocessing import Pool
from typing import List, Dict# 配置路径(建议用os.path.join统一处理路径分隔符)
path = r'C:\2025电商美工\原视频'
new_path = r'C:\2025电商美工\新视频'
os.makedirs(new_path, exist_ok=True)  # 简化文件夹创建逻辑# 支持的视频格式(可根据需求扩展)
SUPPORTED_FORMATS = ('.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv')# 验证ffmpeg是否可用
def check_ffmpeg() -> bool:try:subprocess.run(['ffmpeg', '-version'], capture_output=True, check=True)return Trueexcept (subprocess.CalledProcessError, FileNotFoundError):print("错误:未找到ffmpeg!请先安装并配置环境变量(参考之前的指导)")return False# 获取视频信息(优化正则+错误处理)
def get_video_length(file: str) -> Dict[str, Decimal | str] | None:try:process = subprocess.Popen(['ffmpeg', '-i', file],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,encoding='utf-8',  # 直接指定编码,避免手动decodeerrors='ignore'    # 忽略编码错误
        )stdout, _ = process.communicate(timeout=30)  # 设置超时,避免卡死except Exception as e:print(f"获取视频信息失败:{file},错误:{str(e)}")return None# 优化正则:放宽匹配条件,适应不同ffmpeg版本pattern_duration = re.compile(r"Duration:\s*(\d+):(\d+):(\d+\.\d+)", re.IGNORECASE)pattern_size = re.compile(r"(\d{3,4})x(\d{3,4})", re.IGNORECASE)duration_match = pattern_duration.search(stdout)size_match = pattern_size.search(stdout)if not (duration_match and size_match):print(f"无法提取视频信息:{file}(可能不是支持的视频格式)")return None# 解析时长hours = Decimal(duration_match.group(1))minutes = Decimal(duration_match.group(2))seconds = Decimal(duration_match.group(3))total_seconds = hours * 3600 + minutes * 60 + seconds# 解析分辨率width, height = size_match.groups()return {'total': total_seconds,'width': width,'height': height}# 裁剪视频(优化命令+错误处理)
def cutVideo(startPoint: str, file: str, endPoint: str, newFile: str) -> None:# 确保输出目录存在(处理子文件夹场景)output_dir = os.path.dirname(newFile)os.makedirs(output_dir, exist_ok=True)command = ['ffmpeg', '-ss', startPoint, '-i', file,'-acodec', 'copy', '-vcodec', 'copy','-t', endPoint, '-y',  # -y:覆盖已存在的输出文件
        newFile]try:# 捕获ffmpeg输出,便于调试result = subprocess.run(command, capture_output=True, encoding='utf-8', errors='ignore', timeout=300)if result.returncode != 0:print(f"裁剪失败:{file},错误信息:{result.stderr[:500]}")  # 只打印前500字符else:print(f"裁剪成功:{newFile}")except Exception as e:print(f"裁剪异常:{file},错误:{str(e)}")# 时间格式转换(支持小数秒,保留3位精度)
def secToFFmpegFormat(t: float) -> str:if t < 0:return "00:00:00.000"hours = int(t // 3600)minutes = int((t % 3600) // 60)seconds = t % 60return f"{hours:02d}:{minutes:02d}:{seconds:06.3f}"  # 格式:hh:mm:ss.sss# 输入验证函数
def get_valid_duration(prompt: str) -> float | None:while True:user_input = input(prompt).strip()try:duration = float(user_input)if duration >= 0:return durationelse:print("错误:时长不能为负数,请重新输入!")except ValueError:print("错误:请输入有效的数字(支持小数,如2.5)!")# 主处理函数
def main(task: Dict[str, str | float]) -> None:file = task['file']piantou = task['piantou']pianwei = task['pianwei']# 获取视频信息videoInfo = get_video_length(file)if not videoInfo:returnduration = videoInfo['total']  # Decimal类型total_cut = piantou + pianwei  # float类型# 关键修改:统一数据类型为Decimal,避免运算错误total_cut_decimal = Decimal(str(total_cut))  # 先转字符串再转Decimal,保证精度# 验证裁剪时长是否合理if total_cut_decimal >= duration:print(f"跳过:{file}(片头+片尾时长{total_cut:.1f}秒 ≥ 视频总时长{duration:.1f}秒)")return# 计算裁剪参数startPoint = secToFFmpegFormat(piantou)endPoint_seconds = duration - total_cut_decimal  # Decimal类型运算endPoint = secToFFmpegFormat(float(endPoint_seconds))  # 转为float适配时间格式函数# 生成输出路径(优化路径拼接逻辑)relative_path = os.path.relpath(file, path)new_File = os.path.join(new_path, relative_path)# 执行裁剪
    cutVideo(startPoint, file, endPoint, new_File)# 递归获取所有支持的视频文件
def get_all_video_files(folder: str) -> List[str]:video_files = []for root, _, files in os.walk(folder):for file in files:if file.lower().endswith(SUPPORTED_FORMATS):video_files.append(os.path.join(root, file))return video_filesif __name__ == '__main__':# 检查ffmpeg可用性if not check_ffmpeg():input("按回车键退出...")exit(1)# 获取所有视频文件video_files = get_all_video_files(path)if not video_files:print(f"未在{path}找到支持的视频文件(支持格式:{SUPPORTED_FORMATS})")input("按回车键退出...")exit(0)print(f"共找到{len(video_files)}个视频文件,准备处理...")# 获取用户输入的时长(带验证)piantou_duration = get_valid_duration("输入片头时长(秒,支持小数):")pianwei_duration = get_valid_duration("输入片尾时长(秒,支持小数):")if piantou_duration is None or pianwei_duration is None:exit(1)# 构建任务列表dict_list = [{'file': file,'piantou': piantou_duration,'pianwei': pianwei_duration}for file in video_files]# 多进程处理(限制进程数为CPU核心数的一半,避免资源占用过高)print(f"\n规则:去除片头{piantou_duration}秒、片尾{pianwei_duration}秒,开始处理...\n")timt0 = time.time()with Pool(processes=os.cpu_count() // 2) as pool:  # 优雅的进程池管理
        pool.map(main, dict_list)# 输出统计信息time1 = time.time() - timt0print(f"\n处理完成!共处理{len(video_files)}个视频文件,总耗时{time1:.4f}秒。")input("按回车键退出...")

简直了YYDS!

打完收工! 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux下的拼音输入法 (1)

我用的是Debian 12 KDE. 国内互联网厂的拼音输入法装了都不能用:可以理解,这哪有做游戏等挣钱啊。 用了半年的sunpinyin,会用程序往用户词典里加词 (在系列2里贴代码)。 今天折腾了一通输入法,把KDE搞坏了,Ctrl…

Docker镜像与容器:轻松理解与实战 - 实践

Docker镜像与容器:轻松理解与实战 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

从数据孤岛到智能洞察:构建面向未来的 Operation intelligence 体系

在数字世界持续运转的过程中,系统每时每刻都在产生海量的数据。我们把这些数据统称为 Operation Data(运营数据)。它不仅记录着系统的运行状态,更蕴藏着驱动业务增长、保障系统稳定、防范安全风险的关键线索。更重…

2025年低合金钢铸件厂家权威推荐榜单:水泵类铸件/矿山机械铸件/阀门类铸件源头厂家精选。

在竞争激烈的制造业中,一家位于镇江、深耕行业二十余年的铸钢企业,以每年超8000吨的产量和远销海外的实力,正赢得全球工业客户的广泛认可。 在当今制造业蓬勃发展的时代,低合金钢铸件因其优异的机械性能和成本效益…

oracle sql格式化

1、实用的 SQL*Plus 格式化脚本-- format.sql - SQL*Plus 格式化脚本 SET ECHO OFF SET FEEDBACK ON SET VERIFY OFF SET HEADING ON SET PAGESIZE 50 SET LINESIZE 200 SET TRIMSPOOL ON SET TAB OFF SET NULL "…

鸿蒙NEXT开发浅进阶到精通14:鸿蒙制作项目中遇到的需求问题及解决笔记05

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

oracle 数据字典应用

1、可以通过v$fixed_table 或dictionary来得到oracle中所有的数据字典 2、v$databaseSQL> select name,created,log_mode,open_mode from v$database;NAME CREATED LOG_MODE OPEN_…

devtoolset-11 工具集

目录如何安装与使用总结devtoolset-11 是 Red Hat 为 Red Hat Enterprise Linux (RHEL) 及其社区版本 CentOS 等系统提供的一套开发工具集,主要用于在不升级整个系统的情况下,获得并使用更新的编译器及开发工具。 下…

2025 长沙美食餐厅最新推荐排行榜权威发布:红记领衔榜单,协会测评认证湘味品质指南 长沙海鲜店/火锅店/小吃店/长沙宵夜推荐

引言 长沙餐饮市场的烟火气背后,是消费者对品质与地道风味的更高追求。为破解市场同质化、食品安全隐忧等问题,本次榜单由湖南省餐饮行业协会联合美团点评共同打造,参考《餐饮服务食品安全量化分级及示范店评定规范…

基于RNN循环神经网络的锂电池剩余寿命预测Matlab实现 - 教程

基于RNN循环神经网络的锂电池剩余寿命预测Matlab实现 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Conso…

2025年热门的异形工业铝型材,工业铝型材推荐TOP品牌厂家

2025年热门的异形工业铝型材,工业铝型材推荐TOP品牌厂家随着工业4.0时代的深入发展,异形工业铝型材因其轻量化、高强度、耐腐蚀和可回收等优异特性,正成为智能制造、新能源、轨道交通等高端领域的关键材料。2025年,…

day19-API+functioncalling任务回顾+langchain快速入门

虚拟环境创建 创建虚拟环境语法:conda create -n <环境名称> [选项]。 示例:创建一个名为myenv且指定Python版本为3.8的虚拟环境,命令为conda create -n myenv python=3.10。激活虚拟环境激活:使用命令conda…

在nginx中实现回源日志的功能

本文分享自天翼云开发者社区《在nginx中实现回源日志的功能》.作者:尹****聪 nginx中已经提供了访问日志的功能,主要对客户端的访问状态等进行记录,比如响应给客户端的状态码,请求uri,请求协议等。而对于回源(或者…

实用指南:web核心—HTTP

实用指南:web核心—HTTPpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &q…

杂题记录 3

P5979 [PA 2014] Druzyny 小清新题。暴力转移是简单的,$f_i \leftarrow f_j,j-i\in[\max_{k=i+1}^j c_k,\min_{k=i+1}^j d_k] $,关于 \(\max\) 和偏序的限制不难往 cdq 优化 dp 的方向想。 然后考虑 \([l,mid]\) 向 …

2025年北京工程造价咨询公司权威推荐榜单:工程预算造价/造价咨询甲级/全过程工程咨询源头公司精选

面对北京超过620家的造价咨询企业,六成公司年收入低于5000万元的行业现状,如何精准筛选成为业主的共同挑战。 北京市住建委《2024工程造价咨询统计公报》显示,全市在册工程造价咨询企业超620家,其中甲级资质占比不…

USB 扩展网卡全方位指南:从选购到使用

在无线网络普及的当下,有线网络凭借更稳定的传输速率和更低的延迟,仍是游戏、直播、大型文件传输等场景的首选。而 USB 扩展网卡(又称 USB 千兆网卡、USB 转以太网适配器),则成为解决设备缺少网口、网口损坏或需扩…

2025年评价高的甜酒酿,醪糟甜酒酿推荐TOP品牌厂家

2025年评价高的甜酒酿,醪糟甜酒酿推荐TOP品牌厂家甜酒酿市场概览甜酒酿,又称醪糟、酒酿,是中国传统发酵米制食品,具有悠久的历史和丰富的营养价值。随着健康饮食理念的普及,2025年甜酒酿市场呈现出快速增长态势,消…

基于日志排查邮件投递失败的全过程

在维护邮件系统(如 Postfix、Exim、Sendmail 等)的过程中,邮件投递失败是再常见不过的问题。要有效定位和解决问题,必须从收到的退信或错误提示出发,一步步追踪邮件的完整投递链路和后台日志记录,准确找出失败原…

2025年口碑好的养生托玛琳床垫,保健托玛琳床垫厂家最新推荐排行榜

2025年口碑好的养生托玛琳床垫,保健托玛琳床垫厂家最新推荐排行榜随着人们对健康睡眠需求的不断提升,养生托玛琳床垫凭借其独特的保健功效成为市场新宠。托玛琳(电气石)是一种天然矿物质,能释放负离子和远红外线,…