使用py-ffmpeg批量合成视频的脚本

我有一个小米摄像头,用它录出来的视频全部都是3s一段3s一段的。其中有几个小时的视频我需要保存,当初直接把摄像头的卡文件导出来重命名掉了,那时候没有注意,之后想剪辑/发送给别人的时候发现疯了:

1.剪辑的话,py导入特别卡

2.发送的话,打包发完打开对面是一脸懵

但是我已经重命名了文件,要是把对象再插回摄像头用自带软件导出也太折腾了。思来想去一番后,我觉得先合成,再剪辑/发送

但是问题又来了,最开始我使用格式工厂合并,但是发现格式工厂默认会对全部文件搞一次重新编码,这就把我的电脑搞得特别卡,总共几个小时1w多个文件编码了几个小时都好不了

左思右想后,还是决定自己用py整一个(因为我好像没有在格式工厂里面找到相关的功能可以禁用掉自动编码)

我决定使用FFmpeg进行操作,FFmpeg需要在官网上下载,这里需要根据各自的os选择

然后要将这个添加到工作路径中,你可以

1.把这个添加到系统变量里面(我由于没有大量的使用需求,加上希望换一个电脑也可以用,就选择下面一个方案)

2.使用 subprocess.run 指定 ffmpeg 的路径

就像这样:

# 使用 subprocess.run 指定 ffmpeg 的路径,并将输出重定向到日志文件with open(log_file, "w") as log:result = subprocess.run([ffmpeg_path] + command.split(), stdout=log, stderr=log)

这个path应该是ffmpeg.exe结尾的路径,具体可以在ffmpeg的包里面一个bin文件夹下看到、

接下来是实际操作部分:

FFmpeg 命令的格式我就不说了,毕竟也是查来了,里面两个关键的点:

1.需要提供一个带有文件路径的txt文件

可以这样生成(一定要加utf8,要不然可能会以gbk的形式生成,导致FFmpeg 识别不了中文字符)

    with open("file_list.txt", "w",encoding="utf-8") as f:for file in video_files:f.write(f"file '{file}'\n")

2.以copy模式构造ffmpeg命令

    command = f"-f concat -safe 0 -i file_list.txt -c copy {output_file}"

源代码:

import os
import subprocess
import send2trash
import timedef merge_videos_in_directory(input_dir, output_file, ffmpeg_path):start_time = time.time()  # 记录开始时间print("脚本开始运行时间:", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time)))"""使用 FFmpeg 从指定目录合并所有视频文件,保留原画质,并将原文件移动到回收站。"""video_files = [os.path.join(input_dir, file) for file in os.listdir(input_dir)if file.endswith(('.mp4', '.avi', '.mov', '.mkv'))]video_files.sort()if not video_files:print("没有找到视频文件。")returnwith open("file_list.txt", "w",encoding="utf-8") as f:for file in video_files:f.write(f"file '{file}'\n")# 构造FFmpeg 命令command = f"-f concat -safe 0 -i file_list.txt -c copy {output_file}"log_file = "ffmpeg_log.txt"  # 日志文件路径try:# 使用 subprocess.run 指定 ffmpeg 的路径,并将输出重定向到日志文件with open(log_file, "w") as log:result = subprocess.run([ffmpeg_path] + command.split(), stdout=log, stderr=log)if result.returncode != 0:print(f"FFmpeg 命令执行失败,详情请查看日志文件:{log_file}")returnelse:print("FFmpeg 命令执行成功,日志已保存到:", log_file)except Exception as e:print(f"运行 FFmpeg 时发生错误: {e}")returnsend2trash.send2trash("file_list.txt")end_time = time.time()  # 记录结束时间elapsed_time = end_time - start_time  # 计算总耗时hours, rem = divmod(elapsed_time, 3600)minutes, seconds = divmod(rem, 60)print("脚本结束运行时间:", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time)))print("总耗时:{:0>2}:{:0>2}:{:05.2f}".format(int(hours), int(minutes), seconds))send2trash.send2trash(input_dir)input_directory = r"你的一堆视频文件的路径"
output_video = "你的输出文件名.mkv" 
ffmpeg_path = r"ffmpeg.exe的ffmpeg程序路径"merge_videos_in_directory(input_directory, output_video, ffmpeg_path)

最后,先拿几千个文件试了一下,效果很好,几分钟就完成了:

脚本开始运行时间: 2025-03-14 17:43:30
FFmpeg 命令执行成功,日志已保存到: ffmpeg_log.txt
脚本结束运行时间: 2025-03-14 17:48:13
总耗时:00:04:43.12

文件大小也差不多,应该没问题

ps:我最早使用的输出文件名是mp4,然后报错了:

FFmpeg 命令执行失败: ffmpeg version 2025-03-13-git-958c46800e-essentials_build-www.gyan.dev Copyright (c) 2000-2025 the FFmpeg developersbuilt with gcc 14.2.0 (Rev1, Built by MSYS2 project)configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-zlib --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-sdl2 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-dxva2 --enable-d3d11va --enable-d3d12va --enable-ffnvcodec --enable-libvpl --enable-nvdec --enable-nvenc --enable-vaapi --enable-libgme --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvo-amrwbenc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-librubberbandlibavutil      59. 59.100 / 59. 59.100libavcodec     61. 33.102 / 61. 33.102libavformat    61.  9.107 / 61.  9.107libavdevice    61.  4.100 / 61.  4.100libavfilter    10.  9.100 / 10.  9.100libswscale      8. 13.101 /  8. 13.101libswresample   5.  4.100 /  5.  4.100libpostproc    58.  4.100 / 58.  4.100
[aist#0:0/pcm_alaw @ 0000024bcba1cd00] Guessed Channel Layout: mono
Input #0, concat, from 'file_list.txt':Duration: N/A, start: 0.000000, bitrate: 1215 kb/sStream #0:0(und): Audio: pcm_alaw (alaw / 0x77616C61), 8000 Hz, mono, s16, 64 kb/sMetadata:creation_time   : 2022-10-13T03:50:14.000000Zvendor_id       : [0][0][0][0]Stream #0:1(und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, unknown/bt709/unknown), 2304x1296, 1151 kb/s, 20 fps, 20 tbr, 90k tbnMetadata:creation_time   : 2022-10-13T03:50:14.000000Zvendor_id       : [0][0][0][0]
Stream mapping:Stream #0:1 -> #0:0 (copy)Stream #0:0 -> #0:1 (copy)
[mp4 @ 0000024bcb7b2640] Could not find tag for codec pcm_alaw in stream #1, codec not currently supported in container
[out#0/mp4 @ 0000024bcb7b2440] Could not write header (incorrect codec parameters ?): Invalid argument
Conversion failed!

查了一下之后,发现是小米挖的坑:它使用了一个叫做PCM Alaw的编码,这个编码正常是不允许出现在mp4文件里面的。这只能说 小米啊小米 还得是您

所以后面我把输出文件名改为了兼容性更强一点的mkv文件,后面想转mp4的话用格式工厂走一下就好了

pps:

我只测试过全都是我自己那款小米摄像头出来的mp4文件格式,虽然说我在检测文件夹下视频路径的代码里面加了好几个类型,但是不保证会不会多种东西杂在一起又闹出什么不可描述的奇葩事,所以建议转码的时候将相同源的放在一起转,最后再一起合并(是相同源,比如说一个摄像机出来的这种。因为叫mp4的文件未必内部编码都是相同的)

ppps:

如果你不想看到print,全部注释掉就好

pppps:

数据有风险,由于ffmpeg并不是在所有情况下都会报错:

1.比如我的代码之前在一些特定文件名下出错了,但是是直接正常回调(result.returncode甚至是0,不是其他的。)就导致它往下走了删除,我是发现文件大小不对才意识到的。

2.视频文件不能是损坏的或者空文件 如果是那样的话可能会报错:

[mov,mp4,m4a,3gp,3g2,mj2 @ 00000190127b9680] Format mov,mp4,m4a,3gp,3g2,mj2 detected only with low score of 1, misdetection possible!
[mov,mp4,m4a,3gp,3g2,mj2 @ 00000190127b9680] moov atom not found
[concat @ 0000019011b2f7c0] Impossible to open 'F:\record\20221013_045834.mp4'
[in#0/concat @ 0000019011b2f3c0] Error during demuxing: Invalid data found when processing input
[out#0/matroska @ 0000019012445180] video:393957KiB audio:31858KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 0.471186%
frame=81560 fps=13679 q=-1.0 Lsize=  427822KiB time=01:07:58.00 bitrate= 859.4kbits/s speed= 684x    

并且会直接中断,留下目前为止的剩余合并好的文件

所以建议可以把

send2trash.send2trash(input_dir)

删了,检查无误后再手动删除

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

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

相关文章

el-table表格样式设置单元格样式方法 :cell-class-name

需求&#xff1a;是否匹配当天日期决定当天时间高亮显示 效果如图 页面代码 <el-tableref"manpowerTable":key"manpowerForUserHandle.tableKey"class"sysDictInfoTable":data"handle.manpowerTable.data"style"width: 100…

基于express+TS+mysql+sequelize的后端开发环境搭建

步骤一&#xff1a;初始化node环境 npm init -y 步骤二&#xff1a;安装 Express、TypeScript、以及相关类型的定义文件 npm install express npm install --save-dev typescript types/node types/express ts-node nodemon npm install body-parser npm install mysql2 npm in…

蓝耘MaaS平台:阿里QWQ应用拓展与调参实践

摘要&#xff1a;本文深入探讨了蓝耘MaaS平台与阿里QWQ模型的结合&#xff0c;从平台架构、模型特点到应用拓展和调参实践进行了全面分析。蓝耘平台凭借其强大的算力支持、弹性资源调度和全栈服务&#xff0c;为QWQ模型的高效部署提供了理想环境。通过细化语义描述、调整推理参…

2. qt写带有槽的登录界面(c++)

我们在1.Qt写简单的登录界面(c)_c qt 设计一个简单界面-CSDN博客中写了个简单的登录界面&#xff0c;但没有槽&#xff0c;在这里写一个带有槽的界面。 1.代码 代码目录如下&#xff1a; main.cpp的代码如下&#xff1a; #include "MainWindow.h" #include <Qt…

linux - 基础IO之操作与文件描述符全解析:从C语言到系统调用底层实现

目录 1.回顾c语言中所学的文件 2.提炼对文件的理解&#xff08;linux基础io第一阶段的学习&#xff09; a.在操作系统内部&#xff0c;一个进程和一个被打开的文件&#xff0c;他们到后面会变成两种对象之间的指针关系。 b.文件 属性 内容 c.在c语言中,以w的方式打开文件…

【A2DP】深入解读A2DP中通用访问配置文件(GAP)的互操作性要求

目录 一、模式支持要求 1.1 发现模式 1.2 连接模式 1.3 绑定模式 1.4 模式间依赖关系总结 1.5 注意事项 1.6 协议设计深层逻辑 二、安全机制&#xff08;Security Aspects&#xff09; 三、空闲模式操作&#xff08;Idle Mode Procedures&#xff09; 3.1 支持要求 …

python 入门教程 window 10 环境下安装pyenv

python的环境配置方法很多&#xff0c;由于python有两个大版本&#xff0c;很多时候需要切换某个固定的版本才能运行三方包&#xff0c;所以推荐使用pyenv 配置python 环境变量 pyenv 的安装 安装方法&#xff1a; Invoke-WebRequest -UseBasicParsing -Uri "https://r…

【fNIRS可视化学习1】基于NIRS-SPM进行光极可视化并计算通道坐标

一、前言 功能性近红外光谱(fNIRS)是一种无创的脑功能成像技术。在fNIRS研究中&#xff0c;光极的空间定位和通道坐标的计算至关重要。 1.光极可视化 光极可视化的重要性我就不赘述了&#xff0c;它可以直观检查probe设计的合理性&#xff0c;确认光极覆盖目标脑区&#xff0c…

Vue.js 中 class 和 style 绑定的全面解析

目录 引言 6.1 v-bind 指令 介绍 使用方法 6.2 绑定 HTML class 介绍 用法 6.3 绑定内联样式 介绍 用法 6.4 实战&#xff1a;制作消息提示框 介绍 用法 总结 引言 在Vue.js构建用户界面的宏伟蓝图里&#xff0c;样式的动态呈现与交互性的完美融合是吸引用户目光…

【红黑树】—— 我与C++的不解之缘(二十五)

前言 学习了avl树&#xff0c;现在来学习红黑树。 一、什么是红黑树 红黑树是一颗平衡二叉搜索树&#xff0c;它每一个节点增加了一个存储位表示节点的颜色&#xff0c;可以是红色或者黑色。 相比较于AVL树&#xff0c;红黑树也是一个自平衡二叉搜索树&#xff0c;但是它与AVL树…

SFT数据处理部分的思考

SFT数据及处理的业内共识 1&#xff0e;prompt的质量和多样性远重要于数据量级&#xff0c;微调一个 30 b 量级的base model只需要 10 w 量级的数据即可 参考&#xff1a;《LIMA&#xff1a;Less Is More for Alignment》 2&#xff0e;合成数据很重要&#xff01;一般需要通过…

Python(学习一)

做网站有成熟的框架像FLASK、DJANGO、TORNADO&#xff0c;写爬虫有好用到哭的REQUESTS&#xff0c;还有强大到没盆友的SCRAPY 随着NUMPY、SCIPY、MATLOTLIB等众多第三方模块的开发和完善&#xff0c;不仅支持py支持各种数学运算&#xff0c;还可以绘制高质量的2D和3D图像&…

ArcGIS Pro将有文字标注底图切换为无标注底图(在线地图图源)

今天介绍一下在ArcGIS Pro将有标注的地形底图换成无标注的底图。 大家在这项目底图时候会经常调用ArcGIS Pro自带的地形图&#xff0c;但是这个地形图自带是有注记的&#xff0c;如下图。 如何更改&#xff0c;才可以调用无文字注记的呢&#xff1f; 对于一个已经切好图的有注记…

Linux第三次练习

1、创建根目录结构中的所有的普通文件 首先在根目录下面新创建一个test目录&#xff0c;然后将查找到的普通文件新建到test目录下 2、列出所有账号的账号名 3、将/etc/passwd中内容按照冒号隔开的第三个字符从大到小排序后输出所有内容 4、列出/etc/passwd中的第20行-25行内容…

[CISCN 2022 初赛]ezpop(没成功复现)

打开在线环境可以看到&#xff1a; 记得之前做过一个类似的就是有点像照着漏洞去复现。应该可以直接在网上找到链子去打。 www.zip查看路由是 Index/test&#xff0c;然后 post 传参 a&#xff1a; exp&#xff08;参考了别的大神的wp&#xff09;&#xff1a; <?php //…

技术-NBIOT

是什么&#xff1f; 窄带物联网&#xff08;Narrow Band Internet of Things, NB-IoT&#xff09;成为万物互联网络的一个重要分支支持低功耗设备在广域网的蜂窝数据连接&#xff0c;也被叫作低功耗广域网(LPWAN)NB-IoT支持待机时间长、对网络连接要求较高设备的高效连接NB-Io…

Spring @Bean注解使用场景二

bean:最近在写一篇让Successfactors顾问都能搞明白的sso的逻辑的文章&#xff0c;所以一致在研究IAS的saml2.0的协议&#xff0c;希望用代码去解释SP、idp的一些概念&#xff0c;让顾问了解SSO与saml的关系&#xff0c;在github找代码的时候发现一些代码的调用关系很难理解&…

pip install和conda install的区别

这里写目录标题 一、什么是 Python 依赖&#xff08;Python Dependencies&#xff09;&#xff1f;1. 依赖的作用2. 如何管理 Python 依赖3. 依赖管理问题4. 依赖锁定总结 二、使用pip安装包venv隔离环境方法 1&#xff1a;使用 venv&#xff08;推荐&#xff09;创建虚拟环境激…

R语言高效数据处理-自定义EXCEL数据排版

注&#xff1a;以下代码均为实际数据处理中的笔记摘录&#xff0c;所以很零散 1、自定义excel表数据输出格式、布局 在实际数据处理中为了提升效率&#xff0c;将Excel报表交付给需求方时减少手动调整的环节很有必要 #1.1设置表头格式 header_style <- createStyle(font…

Word 小黑第4套

对应大猫41 上下日期是一起变动的&#xff0c;删掉第一个&#xff0c;第二个日期格式&#xff08;文件 -选项 -自定义功能区 -选上开发工具&#xff09; 点开发工具 -属性 选择相应的日期格式&#xff09; 修改标题样式时&#xff0c;标题三只有点标题二时才会显示 右击正文样…