需求:


运营有若干批次的视频。有上千个,视频文件,有mp4格式的,有ts格式的

现在有需要去掉视频文件片头和片尾的批量操作需求。

比如

文件夹A下面的视频去掉片尾10秒

文件夹B下面的视频去掉片头6秒,去掉片尾60秒

文件夹C下面的视频去掉片头15秒

而每个文件夹下面视频存在时间长度不一样的情况

而且一个周末必须搞定(MMP,周五下班时找我求助)

嗯~~

开始我的研究


首先想到的是网上搜索视频处理模块

网上搜到的大多都是ffmpeg工具。就准备从它切入

网上搜索了解了大概的用法之后,下下载下来测试

免费开源的软件

登录官网下载

http://ffmpeg.org/download.html
下载win10版本软件

64位和32位的版本都下载了,好在不用安装。解压即用

可以看到32位和64位的

因为可以再命令行对视频操作。可以使用python调用它。前提是你先命令行执行没问题才可以

解压后把文件夹重命名了下。让cmd里面显示的路径短一点。好看

bin目录下有3个工具

其中ffmpeg就可以对视频截取操作

想着3个工具肯定都有自己的用处,就去搜索了下ffprobe,搜索到它可以取元数据信息等

把一个视频拷贝过去

视频的一些信息可以看下

使用ffprobe操作下视频。可以看到视频元数据信息,时长正式我需要的

想着把它输出为json格式的最好。正好搜到了一些可用的参数

参考链接https://blog.csdn.net/u012040869/article/details/70224964

使用如下,其中的时长是duration这个key

E:\tools\ffmpeg-win64\bin>ffprobe -v quiet -print_format json -show_format 1.mp4
{
"format": {
"filename": "1.mp4",
"nb_streams": 2,
"nb_programs": 0,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime / MOV",
"start_time": "0.000000",
"duration": "965.810600",
"size": "26227952",
"bit_rate": "217251",
"probe_score": 100,
"tags": {
"major_brand": "mp42",
"minor_version": "1",
"compatible_brands": "M4V mp42isom",
"creation_time": "2017-08-28T05:07:05.000000Z"
}
}
} E:\tools\ffmpeg-win64\bin>

  

使用python调用此工具,输出为json格式,然后获取时长的简单测试

import subprocess,json
pname='e:\\tools\\ffmpeg-win32\\bin\\ffprobe.exe -v quiet -print_format json -show_format "1.MP4"'
result=subprocess.Popen(pname,shell=False,stdout=subprocess.PIPE).stdout
list_std=result.readlines()
print(list_std)
print('list--------------------')
str_tmp=''
for item in list_std:
str_tmp+=bytes.decode(item.strip())
json_data=json.loads(str_tmp)
print('json_data---------------')
print(json_data)
dura_time = json_data['format']['duration']
print(dura_time)

  

运行如下

接下来是使用ffmpeg工具对视频切割,看看能否满足要求

视频时长是965秒,那么切掉最后10秒,命令行测试下

参数解释下

-i接文件名,指的是输入文件名

-ss是视频的起始位置,这里是0的话,就表示从低0秒开始截取

-t是持续时间。

-codec copy 表示将拷贝所有的流,而不会对它们重新编码,(也可以写为-c copy,测试过一样。仅仅剪切,不转码)不加这个参数CPU会急剧飙升。100%占用率,而且视频不是很快的截取完毕

更多参数请参考https://blog.csdn.net/stone_wzf/article/details/45378759

或者搜索ffmpeg参数

E:\tools\ffmpeg-win64\bin>ffmpeg  -i 1.mp4 -ss 0 -t 955 -codec copy cut.mp4
ffmpeg version N-91378-g3f953379e1 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 7.3.0 (GCC)
configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-bzlib --enable-fontconfig --enable-gnutls --enabl
e-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-
libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-l
ibtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --en
able-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-l
ibvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enabl
e-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth
libavutil 56. 18.102 / 56. 18.102
libavcodec 58. 20.104 / 58. 20.104
libavformat 58. 17.101 / 58. 17.101
libavdevice 58. 4.101 / 58. 4.101
libavfilter 7. 25.100 / 7. 25.100
libswscale 5. 2.100 / 5. 2.100
libswresample 3. 2.100 / 3. 2.100
libpostproc 55. 2.100 / 55. 2.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '1.mp4':
Metadata:
major_brand : mp42
minor_version : 1
compatible_brands: M4V mp42isom
creation_time : 2017-08-28T05:07:05.000000Z
Duration: 00:16:05.81, start: 0.000000, bitrate: 217 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x768 [SAR 1:1 DAR 5:3], 161 kb/s,
15 fps, 15 tbr, 15k tbn, 30 tbc (default)
Metadata:
creation_time : 2017-08-28T05:07:05.000000Z
handler_name : Video Media Handler
encoder : AVC Coding
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 22050 Hz, stereo, fltp, 54 kb/s (default)
Metadata:
creation_time : 2017-08-28T05:07:05.000000Z
handler_name : Sound Media Handler
Output #0, mp4, to 'cut.mp4':
Metadata:
major_brand : mp42
minor_version : 1
compatible_brands: M4V mp42isom
encoder : Lavf58.17.101
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x768 [SAR 1:1 DAR 5:3], q=2-31, 16
1 kb/s, 15 fps, 15 tbr, 15k tbn, 15k tbc (default)
Metadata:
creation_time : 2017-08-28T05:07:05.000000Z
handler_name : Video Media Handler
encoder : AVC Coding
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 22050 Hz, stereo, fltp, 54 kb/s (default)
Metadata:
creation_time : 2017-08-28T05:07:05.000000Z
handler_name : Sound Media Handler
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame=14325 fps=0.0 q=-1.0 Lsize= 25506kB time=00:15:54.99 bitrate= 218.8kbits/s speed=8.98e+003x
video:18721kB audio:6388kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.579203% E:\tools\ffmpeg-win64\bin>

  

切割出来的视频文件

使用mediainfo打开这2个文件,导出json信息。

使用比较工具比较下元数据信息

差别不是很大

接下来写python脚本批量操作,有些模块用不到。之前别的脚本拷贝过来的。

这里使用pycharm执行。需要手动对每个文件夹操作,pycharm实际是调用成功ffmpeg之后,就退出了。ffmpeg作为子进程还在运行

底层系统进程里可以看到实际是ffmpeg运行呢、一个目录有30个视频。可能会同时有30个ffmpeg进程在运行。后期再优化吧。看看能不能串行或者并行10个左右

因为如果100个视频文件在同一个目录。那么此脚本会同时启动100个ffmpeg子进程,普通磁盘读写太慢,影响效率

下面的文件是用双引号引起来的"%s",是因为之前遇到视频文件名带空格。导致传入文件名时,参数个数增加了,导致报错

import os,subprocess,json,re,locale,sys
import xlwt,time,shutil #定义个列表存放每个文件路径,便于后期操作
file_list=[]
#源文件目录
dir_path='E:\\0630\\3'
#输出截取之后的文件目录
put_path='E:\\0630\\33\\'
#创建个方法,统计每个文件路径,并追加列表中。用到了递归,列表中的是每个文件的绝对路径
def get_all_file(dir_path):
for file in os.listdir(dir_path):
# print(file)
filepath=os.path.join(dir_path,file)
# print(filepath)
if os.path.isdir(filepath):
get_all_file(filepath)
else:
file_list.append(filepath)
return file_list file_list=get_all_file(dir_path)
print(file_list) #设置从什么时间开始截取,单位是秒
start_time=10
#设置去掉多久的无用时长(比如片头去掉10秒,片尾去掉15秒,总共去掉25秒)
cut_time=25 #定义方法,传入文件和截取的时间信息,输出路径。对每个文件操作
def cut_media_time(file,start_time,cut_time,put_path):
#获取文件元数据,输出为json,这里把命令写好。总之为了获取时长
pname='e:\\tools\\ffmpeg-win32\\bin\\ffprobe.exe -v quiet -print_format json -show_format "%s"'%(file)
#调用执行命令
result=subprocess.Popen(pname,shell=False,stdout=subprocess.PIPE).stdout
list_std=result.readlines()
str_tmp=''
for item in list_std:
str_tmp+=bytes.decode(item.strip())
json_data=json.loads(str_tmp)
# print(json_data)
#获取时长,格式是str
dura_time = json_data['format']['duration']
print(dura_time)
print(type(dura_time))
#因为时长精确到毫秒,是str格式,转成float类型
dura_time_float=float(dura_time)
print(type(dura_time_float))
print('------')
# dura_time=int(dura_time)
#也转成float类型
cut_time=float(cut_time)
print(type(cut_time))
#float类型的数据计算
end_time=dura_time_float-cut_time
print('end_time-------')
print(type(end_time))
#获取文件名,去掉路径
filename=os.path.split(file)[1]
#根据输出目录组合成输出的绝对路径文件名
put_file_path=os.path.join(put_path,filename)
#ffmpeg的字符串切割命令字符串
pfile='E:\\tools\\ffmpeg-win32\\bin\\ffmpeg.exe -i "%s" -ss %s -t %s -codec copy "%s"'%(file,start_time,end_time,put_file_path)
#执行切割操作
subprocess.Popen(pfile)
#对列表中的文件批量执行
for file in file_list:
cut_media_time(file,start_time,cut_time,put_path)

  

另外路径必须是\\2个斜线。一个斜线会报如下错误

"PermissionError: [WinError 5] Access is denied".

  

因为太仓促,就临时用pycharm帮他们处理了下

使用ssd的速度会比sata硬盘速度快了不止10倍。因为几十个ffmpeg同时随机读写磁盘。ssd效率比sata高多了

后期改造计划


1、把执行改成并行10个,或者串行的

2、加入异常处理

3、打成exe程序交付给运营执行(简单打成exe测试了。把文件名写死了简单测试。执行没问题。中文文件名也没问题,就是执行窗口有部分乱码。暂时不影响)

其它参考


python有moviepy模块。貌似能满足要求。但是因为时间仓促缘故没仔细研究测试
涉及用法

from moviepy.editor import *
#在t = 50s和t = 60s之间选择子剪辑
video = VideoFileClip("my.mp4").subclip(50,60)

  

下面windows软件可能满足要求,操作太多了点

http://www.leawo.cn/space-758990-do-thread-id-37655.html

淘宝有此类软件,但是询问店主,说支持mp4,但是不支持ts格式的视频
https://item.taobao.com/item.htm?spm=a230r.1.14.20.6d386e8fA51UHY&id=563703965309&ns=1&abbucket=14#detail

其它补充


ffmpeg -i ./plutopr.mp4 -vcodec copy -acodec copy -ss 00:00:10 -to 00:00:15 ./cutout1.mp4 -y

-ss time_off set the start time offset 设置从视频的哪个时间点开始截取,上文从视频的第10s开始截取
-to 截到视频的哪个时间点结束。上文到视频的第15s结束。截出的视频共5s.
-t 表示截取多长的时间,如上文-to 换位-t则是截取从视频的第10s开始,截取15s时长的视频。即截出来的视频共15s.

注意的地方是:
如果将-ss放在-i ./plutopr.mp4后面则-to的作用就没了,跟-t一样的效果了,变成了截取多长视频。一定要注意-ss的位置。

参数解析
-vcodec copy表示使用跟原视频一样的视频编解码器。
-acodec copy表示使用跟原视频一样的音频编解码器。

-i 表示源视频文件
-y 表示如果输出文件已存在则覆盖。

ffmpeg工具本身功能非常强大,转码、剪切、截图、视频合成等

https://www.cnblogs.com/gmapapi/archive/2013/01/18/2866405.html

Python调用ffpmeg和ffprobe处理视频文件的更多相关文章

  1. python调用mediainfo工具批量提取视频信息

    写了2个脚本,分别是v1版本和v2版本 都是python调用mediainfo工具提取视频元数据信息 v1版本是使用pycharm中测试运行的,指定了视频路径 v2版本是最终交付给运营运行的,会把v2 ...

  2. centos8平台用ffprobe获取视频文件信息(ffmpeg4.2.2)

    一,ffprobe的作用 ffprobe是强大的视频分析工具, 用于从多媒体流中获取相关信息或查看文件格式信息, 并以可读的方式打印 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https:// ...

  3. java调用本地播放器播放视频文件。调用本地播放器不能播放指定文件的说明。

    public class OpenExe extends HttpServlet { //打开本地播放器并播放视频 public static void openExe(String file) { ...

  4. python爬虫:抓取下载视频文件,合并ts文件为完整视频

    1.获取m3u8文件 2.代码 """@author :Eric-chen@contact :sygcrjgx@163.com@time :2019/6/16 15:32 ...

  5. 简单实现python调用c#dll动态链接库

    在python调用c#dll库时要先安装库clr,即安装pythonnet,参考文章:https://www.cnblogs.com/kevin-Y/p/10235125.html(为在python中 ...

  6. python调用c/c++时传递结构体参数

    背景:使用python调用linux的动态库SO文件,并调用里边的c函数,向里边传递结构体参数.直接上代码 //test1.c # include <stdio.h> # include ...

  7. python实现调用摄像头或打开视频文件

    目录: (一)调用摄像头或打开视频文件代码实现 (二)说明和补充 (一)调用摄像头或打开视频文件代码实现 1 # -*- coding=GBK -*- 2 import cv2 as cv 3 4 5 ...

  8. 用Python和FFmpeg查找大码率的视频文件

    用Python和FFmpeg查找大码率的视频文件 本文使用Python2.7, 这个工作分两步 遍历目录下的视频文件 用ffprobe获取是视频文件的码率信息 用ffprobe 获取json格式的视频 ...

  9. Python调用7zip命令实现文件批量解压

    Python调用7zip命令实现文件批量解压 1.输入压缩文件所在的路径 2.可以在代码中修改解压到的文件路径和所需要解压的类型,列入,解压文件夹下面所有的mp4格式的文件 3.cmd 指的就是Pyt ...

随机推荐

  1. JAVA中字符串比较equals()和equalsIgnoreCase()的区别

    1.使用equals( )方法比较两个字符串是否相等(区分大小写) 2.使用equalsIgnoreCase( )方法比较两个字符串是否相等(不区分大小写) boolean equalsIgnoreC ...

  2. P1340 兽径管理

    传送门 思路: 题目要求每次连边都要输出最小生成树的边权和.如果在线直接套用最小生成树模板肯定会超时,考虑离线处理.记录每一插入边的时间,在所有边都插入完成后排序一遍就可以求最小生成树(按照插入时间的 ...

  3. 浅谈String中的==和对象中引用对象类型的==

    @Test public void test02() { StringBuffer sb = new StringBuffer(); sb.append('a'); sb.append(11); Sy ...

  4. TestMap

    public class TestMap { public static void main(String[] args) { Map map=new HashMap(); //在此映射中关联指定值与 ...

  5. js设置、读取、删除cookie

    设置cookie: function setCookie(oJson , time){ var data = new Date( new Date().getTime() + time*24*60*6 ...

  6. 函数式语言简介(functional language)

    1.什么是函数式语言?        是一种非冯·诺伊曼式的程序设计语言.函数式语言主要成分是原始函数.定义函数和函数型.这种语言具有较强的组织数据结构的能力,可以把某一数据结构(如数组)作为单一值处 ...

  7. 【转】前端的BFC、IFC、GFC和FFC

    什么是BFC.IFC.GFC和FFC CSS2.1中只有BFC和IFC, CSS3中才有GFC和FFC. FC的全称是:Formatting Contexts,是W3C CSS2.1规范中的一个概念. ...

  8. Web 安全漏洞之 XSS 攻击

    什么是 XSS 攻击 XSS(Cross-Site Scripting)又称跨站脚本,XSS的重点不在于跨站点,而是在于脚本的执行.XSS是一种经常出现在 Web 应用程序中的计算机安全漏洞,是由于 ...

  9. FileWriter向文件中写入内容

    1.创建fileWriter对象 2.写入文件信息 3.关闭流 必须关闭流,否则将不能写入文件中 /** * * @author Administrator * 文件写入对象的使用 * */ publ ...

  10. vmware 安装 centos7 记录笔记

    1, 安装centos 7, 到阿里云镜像下载centos 7 1.虚拟机的创建: 打开安装好的VMware (如果大家安装的VMware是英文版的也没关系,对号入座即可),选择“文件--->新 ...