python调用ffmpeg命令行工具便捷操作视频示例实现过程


Posted in Python onNovember 01, 2021

文 | 李晓飞

来源:Python 技术「ID: pythonall」

最近有了一个新任务,需要将赛事视频,拆分成两分钟以内的小段,用于发布到短视频平台上。

本以为是个一次性的工作,结果赛事视频数据巨大,视频文件长短不一,完全没法手工处理,于是 Python 又一次拯救了我。

还等什么,开始干吧!

最重要的事

无论做什么事情,都要去分析一下最重要的是什么,然后集中精力攻克,再继续找最重要的事。

对我们这个任务来说,不算是个大项目,不过呢,还是要找最重要的事开始,步步为营,最终将整个问题解决了。

整体来来看,我们需要从一个目录中读取视频文件,然后,对每个视频文件进行裁剪,最后将处理好的文件保存好。

在这个过程中,最重要的是什么呢?我觉得,是视频裁剪,如果不能方便的裁剪视频,其他的一切工作都是白费的,是吧。

裁剪视频

现在短视频很流行,有很多视频编辑软件,功能丰富,而我们需要的只是裁剪功能,而且需要用编程的方式调用,那么最合适的莫过于 ffmpeg[1] 了。

ffmpeg 是一个命令行工具,功能强大,可以编程调用。

从 ffmpeg 官网上下载对应操作系统的版本,我下的是 Windows 版[2]。

下载后解压到一个目录,然后将目录下的 bin,配置到环境变量里。然后打开一个命令行,输入:

> ffmpeg -version
ffmpeg version 2021-10-07-git-b6aeee2d8b-full_build- ...

测试一下,能显示出版本信息,说明配置好了。

现在读一下文档,发现拆分视频文件的命令是:

ffmpeg -i [filename] -ss [starttime] -t [length] -c copy [newfilename]

]

i 为需要裁剪的文件

ss 为裁剪开始时间

t 为裁剪结束时间或者长度

c 为裁剪好的文件存放

好了,用 Python 写一个调用:

import subprocess as sp
 
def cut_video(filename, outfile, start, length=90):
    cmd = "ffmpeg -i %s -ss %d -t %d -c copy %s" % (filename, start, length, outfile)
    p = sp.Popen(cmd, shell=True)
    p.wait()
    return
  • 定义了一个函数,通过参数传入 ffmpeg 需要的信息
  • 将裁剪命令写成一个字符串模板,将参数替换到其中
  • subprocessPopen 执行命令,其中参数 shell=True 表示将命令作为一个整体执行
  • p.wait() 很重要,因为裁剪需要一会儿,而且是另起进程执行的,所以需要等执行完成再做后续工作,否则可能找不到裁剪好的文件

这样视频裁剪工作就完成了,然后再看看什么是最重要的。

计算分段

视频裁剪时,需要一些参数,特别是开始时间,如何确定呢?如果这件事做不好,裁剪工作就很麻烦。

所以看看如何计算裁剪分段。

我需要将视频裁剪成一分半的小段,那么将需要知道目标视频文件的时间长度。

获取视频长度

如何获得长度呢?ffmpeg 提供了另一个命令 —— ffprobe

找了一下,可以合成一个命令来获取:

> ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 -i a.flv
 
920.667

命令比较复杂哈,可以先不用管其他参数,只要将要分析的视频文件传入就好了。命令的结果是显示一行视频文件的长度。

于是可以编写一个函数:

import subprocess as sp
 
def get_video_duration(filename):
    cmd = "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 -i %s" % filename
    p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE)
    p.wait()
    strout, strerr = p.communicate() # 去掉最后的回车
    ret = strout.decode("utf-8").split("\n")[0]
    return ret
  • 函数只有一个参数,就是视频文件路径
  • 合成命令语句,将视频文件路径替换进去
  • subprocess 来执行,注意这里需要设置一下命令执行后的输出
  • wait 等待命令执行完成
  • 通过 communicate 提取输出结果
  • 从结果中提取视频文件的长度,返回

分段

得到了视频长度,确定好每个分段的长度,就可以计算出需要多少分段了。

代码很简单:

import math
duration = math.floor(float(get_video_duration(filename)))
part = math.ceil(duration / length)

注意,计算分段时,需要进行向上取整,即用 ceil,以包含最后的一点尾巴。

得到了需要的分段数,用一个循环就可以计算出每一段的起始时间了。

获取文件

因为处理的文件很多,所以需要自动获取需要处理的文件。

方法很简单,也很常用,一般可以用 os.walk 递归获取文件,还可以自己写,具体根据实际情况。

for fname in os.listdir(dir):
    fname = os.path.join(dir, os.path.join(dir, fname))
    basenames = os.path.basename(fname).split('.')
    mainname = basenames[0].split("_")[0]
    ...

提供视频文件所在的目录,通过 os.listdir 获取目录中的文件,然后,合成文件的绝对路径,因为调用裁剪命令时需要绝对路径比较方便。

获取文件名,是为了在后续对裁剪好的文件进行命名。

代码集成

现在每个部分都写好了,可以将代码集成起来了:

def main(dir):
    outdir = os.path.join(dir, "output")
    if not os.path.exists(outdir):
        os.mkdir(outdir)
 
    for fname in os.listdir(dir):
        fname = os.path.join(dir, os.path.join(dir, fname))
        if os.path.isfile(fname):
            split_video(fname, outdir)
  • main 方法是集成后的方法
  • 先创建一个裁剪好的存储目录,放在视频文件目录中的 output 目录里
  • 通过 listdir 获取到文件后,对每个文件进行处理,其中判断了一下是否为文件
  • 调用 split_video 方法开始对一个视频文件进行裁剪

总结

总体而言,这是个很简单的应用,核心功能就是调用了一个 ffmpeg 命令。

相对于技术,更重要的是如何对一个项目进行分析和分解,以及从什么地方开始。

这里的方式起始时,不断地找最重要地事情,以最重要的事情为线索不断地推进,最终以自下而上地方式解决整个问题。

期望这篇文章对你有所启发,比心。

参考资料

[1]

ffmpeg: http://ffmpeg.org/

[2]

ffmpeg Window 版下载: https://www.3water.com/softs/145521.html

以上就是python调用ffmpeg命令行工具便捷操作视频示例实现过程的详细内容,更多关于python调用命令行工具操作视频的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python实现简单状态框架的方法
Mar 19 Python
python结合shell查询google关键词排名的实现代码
Feb 27 Python
python之Socket网络编程详解
Sep 29 Python
解决python使用open打开文件中文乱码的问题
Dec 29 Python
在python下读取并展示raw格式的图片实例
Jan 24 Python
我喜欢你 抖音表白程序python版
Apr 07 Python
Python对HTML转义字符进行反转义的实现方法
Apr 28 Python
Python常见数据类型转换操作示例
May 08 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
Mar 10 Python
python实现输入三角形边长自动作图求面积案例
Apr 12 Python
pytorch 查看cuda 版本方式
Jun 23 Python
python实现手机推送 代码也就10行左右
Apr 12 Python
Python字典的基础操作
Nov 01 #Python
Python集合的基础操作
Nov 01 #Python
python基础之类属性和实例属性
python基础之类方法和静态方法
Python Matplotlib绘制条形图的全过程
python基础之模块的导入
python基础之文件操作
You might like
PHP中数组的三种排序方法分享
2012/05/07 PHP
PHP中使用memcache存储session的三种配置方法
2014/04/05 PHP
php框架CodeIgniter使用redis的方法分析
2018/04/13 PHP
laravel + vue实现的数据统计绘图(今天、7天、30天数据)
2018/07/31 PHP
Laravel多域名下字段验证的方法
2019/04/04 PHP
JSON为什么那样红为什么要用json(另有洞天)
2012/12/26 Javascript
jsp js鼠标移动到指定区域显示选项卡离开时隐藏示例
2013/06/14 Javascript
js的image onload事件使用遇到的问题
2014/07/15 Javascript
js获取checkbox值的方法
2015/01/28 Javascript
javascript模拟C#格式化字符串
2015/08/26 Javascript
javascript的列表切换【实现代码】
2016/05/03 Javascript
[原创]Javascript 实现广告后加载 可加载百度谷歌联盟广告
2016/05/11 Javascript
输入框点击时边框变色效果的实现方法
2016/12/26 Javascript
vue使用keep-alive实现数据缓存不刷新
2017/10/21 Javascript
详解设置Webstorm 利用babel将ES6自动转码成ES5
2017/12/20 Javascript
ajax请求+vue.js渲染+页面加载的示例
2018/02/11 Javascript
详解webpack-dev-server的简单使用
2018/04/02 Javascript
axios封装,使用拦截器统一处理接口,超详细的教程(推荐)
2019/05/02 Javascript
layUI的验证码功能及校验实例
2019/10/25 Javascript
JS表格的动态操作完整示例
2020/01/13 Javascript
Node.js中出现未捕获异常的处理方法
2020/06/29 Javascript
[07:40]DOTA2每周TOP10 精彩击杀集锦vol.4
2014/06/25 DOTA
用virtualenv建立多个Python独立虚拟开发环境
2017/07/06 Python
Python面向对象基础入门之设置对象属性
2018/12/11 Python
python 猴子补丁(monkey patch)
2019/06/26 Python
解决Python paramiko 模块远程执行ssh 命令 nohup 不生效的问题
2020/07/14 Python
python使用ctypes库调用DLL动态链接库
2020/10/22 Python
个人自我鉴定怎么写
2013/10/28 职场文书
尽职尽责村干部自我鉴定
2014/01/23 职场文书
学历公证书范本
2014/04/09 职场文书
拒绝黄毒毒宣传标语
2014/06/26 职场文书
学党史心得体会
2014/09/05 职场文书
后备干部推荐材料
2014/12/24 职场文书
2015新学期校长寄语(3篇)
2015/03/25 职场文书
总结一下关于在Java8中使用stream流踩过的一些坑
2021/06/24 Java/Android
Python之基础函数案例详解
2021/08/30 Python