zoukankan      html  css  js  c++  java
  • python+ffmpeg切割视频

    什么是ffmpeg

    1.1 简介

    FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。

    FFmpeg提供了强大的命令行工具,非常方便用户使用以及二次开发。

    官方网站:http://ffmpeg.org/

    1.2 组件

    FFmpeg项目由以下几部分组成:

    1.FFmpeg视频文件转换命令行工具,也支持经过实时电视卡抓取和编码成视频文件;

    2.ffserver基于HTTP、RTSP用于实时广播的多媒体服务器.也支持时间平移;

    3.ffplay用 SDL和FFmpeg库开发的一个简单的媒体播放器;

    4.libavcodec一个包含了所有FFmpeg音视频编解码器的库。为了保证最优性能和高可复用性,大多数编解码器从头开发的;

    5.libavformat一个包含了所有的普通音视格式的解析器和产生器的库。

    安装

    下载免编译版本:xxxx-static.tar.gz 版本中包含static是免编译版本,

    免编译版本下载地址:https://johnvansickle.com/ffmpeg/

    安装步骤如下:

     1 $ cd /home/john
     2 $ wget https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-64bit-static.tar.xz
     3 $ wget https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-64bit-static.tar.xz.md5
     4 $ md5sum -c ffmpeg-git-64bit-static.tar.xz.md5
     5 ffmpeg-git-64bit-static.tar.xz: OK
     6 $ xz -d ffmpeg-git-64bit-static.tar.xz
     7 $ tar -cvf ffmpeg-git-64bit-static.tar
     8 $ ls ffmpeg-git-20180203-64bit-static
     9 ffmpeg  ffmpeg-10bit  ffprobe  GPLv3.txt  manpages  model  qt-faststart  readme.txt
    10 $ pwd
    11 /home/john
    12 
    13 $ ./ffmpeg-git-20180203-64bit-static/ffmpeg
    14 ffmpeg version N-89948-ge3d946b3f4-static https://johnvansickle.com/ffmpeg/  Copyright (c) 2000-2018 the FFmpeg developers
    15   built with gcc 6.4.0 (Debian 6.4.0-11) 20171206
    16 (snipped output to save space)

     常用的集合选项

    –y表示覆盖输出文件;
    
    –i表示输入文件;
    -t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持
    -ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持

    其他更加详细以及高级用法参考

    https://wuyuans.com/2011/11/ffmpeg-syntax

    剪切视频

      ./ffmpeg -ss 00:00:06 -t 00:00:12 -i input.mp4 -vcodec copy -acodec copy output.mp4

    批量处理视频

    由于视频很大,我想切割成一个一个小的视频文件保存起来

    脚本如下

     1 #!/usr/local/src/Python-2.7.15/python
     2 import string
     3 
     4 import os 
     5 import time
     6 import re
     7 import math
     8 import sys
     9 from optparse import OptionParser
    10 
    11 print "Test by zzz start..."
    12 parser = OptionParser()
    13 parser.add_option("-i", "--input", dest="input",action="store_true",help="input x y for each file by user")
    14 parser.add_option("-q", "--quality", dest="q",action="store",help="input xvid q arg",default="24")
    15 parser.add_option("-v", "--vcodec", dest="vcodec",action="store",help="input video codec",default="x264")
    16 parser.add_option("-n", "--noaudio", dest="an",action="store_true",help="no audio")
    17 parser.add_option("-p", "--preset", dest="preset",action="store",help="",default="")
    18 parser.add_option("-m", "--maxWidth", dest="maxWidth",action="store",help="input max width for output video",default="")
    19 parser.add_option("-f", "--fileType", dest="fileType",action="store",help="",default="mp4")
    20 parser.add_option("-o", "--ogg", dest="ogg",action="store_true",help="user ogg instead of aac",default="")
    21 parser.add_option("-3", "--mp3", dest="mp3",action="store_true",help="user mp3 instead of aac",default="")
    22 parser.add_option("-1", "--pad", dest="pad",action="store_true",help="pad to 16:9",default="")
    23 parser.add_option("-s", "--src", dest="srcD",action="store",help="source dir",default="/usr/local/src/test/videoin")
    24 parser.add_option("-t", "--target", dest="targetD",action="store",help="target dir",default="/usr/local/src/test/videoout")
    25 parser.add_option("-w", "--workdir", dest="workdir",action="store",help="work dir",default="/usr/local/src/test/video")
    26 parser.add_option("-e", "--split", dest="split",action="store_true",help="split to multiple file with size")
    27 parser.add_option("-d", "--splitsize", dest="splitsize",action="store",help="split to multiple file with size",default="2")#Minutes
    28 parser.add_option("-j", "--prefix", dest="prefix",action="store",help="target file name prefix",default="")
    29 
    30 (options, args) = parser.parse_args()
    31 
    32 if options.srcD==None or options.srcD[0:1]=='-':
    33     print 'srcD Err, quit'
    34     exit() 
    35 if options.targetD==None or options.targetD[0:1]=='-':
    36     print 'targetD Err, quit'
    37     exit() 
    38 if options.fileType==None or options.fileType[0:1]=='-':
    39     print 'fileType Err, quit'
    40     exit() 
    41 if options.workdir==None or options.workdir[0:1]=='-':
    42     print 'workdir Err, quit'
    43     exit() 
    44     
    45 #获取视频文件的名字
    46 for root,dirs,files in os.walk(options.srcD): 
    47     for name in files:
    48         name= name.replace('[','''[''')#??????[????
    49         newname =name[0: name.rindex('.')]      
    50         print "Test newname: " + newname
    51         print "Test name: " + name
    52 
    53         
    54         
    55 #??
    56         cmd ='cd '+options.workdir+';mkdir -p ffm;  rm -f ffm/ffm.txt ; sh -c "(/usr/local/src/ffmpeg-git-20181015-64bit-static/ffmpeg -i '+options.srcD+'/' +name+ ' >& ffm/ffm.txt)"; grep Duration ffm/ffm.txt'
    57         #ffmpeg -i  xxx.mp4  能够得到视频文件的时间信息
    58         print cmd
    59         (si, so, se) = os.popen3(cmd)
    60         t=so.readlines()  ##['  Duration: 00:26:52.92, start: 0.000000, bitrate: 248 kb/s
    ']
    61         print t 
    62         reg='''Duration:s(d+):(d+):([d.]+)'''
    63         duration=0#second
    64         for line in t:
    65             result = re.compile(reg).findall(line)##result=[('00', '26', '52.92')]
    66             for c in result:
    67                 print 'split file to',options.splitsize,'minutes, Duration:',c[0],c[1],c[2]
    68                 duration = int(c[0])*3600 + int(c[1])*60+float(c[2])##获取视频全部时间s
    69                 nameLength=int(math.log(int(duration / (int(options.splitsize)*60)) )/math.log(10)) + 1
    70                 print nameLength
    71                 for i in range(int(duration / (int(options.splitsize)*60)) + 1):##获取总计能够截取几份
    72                     print i
    73                     _t = ''
    74                     if duration>int(options.splitsize)*60*(i+1): ##当总时间数大于截取时间数时的取值
    75                         _t = str(int(options.splitsize)*60)
    76                     else:
    77                         _t = str(duration-int(options.splitsize)*60*i)
    78                         ##当总时间数小于截取时间数时的取值也就是最后一段视频
    79                     cmd ='sh -c "' + "cd "+options.workdir+";touch ffm/output.log;(/usr/local/src/ffmpeg-git-20181015-64bit-static/ffmpeg -y -i "+options.srcD+"/"+name+" -codec: copy -ss "+str(i*int(options.splitsize)*60)+" -t "+_t+" "+options.targetD+"/"+options.prefix+newname+'_'+string.replace(('%'+str(nameLength)+'s')%str(i),' ','0')+"."+options.fileType + ' >& ffm/output.log)"'
    80                     print cmd
    81                     (si, so, se) = os.popen3(cmd)
    82                     for line in se.readlines() :#????
    83                         print line
    View Code

    最后截取视频如下,每个视频两分钟:

    [root@localhost videoout]# ls -l
    total 47620
    -rw-r--r--. 1 root root 6626325 Oct 27 16:11 02_xxx.ev4_00.mp4
    -rw-r--r--. 1 root root 2551943 Oct 27 16:11 02_xxx.ev4_01.mp4
    -rw-r--r--. 1 root root 3904819 Oct 27 16:11 02_xxx.ev4_02.mp4
    -rw-r--r--. 1 root root 3380509 Oct 27 16:11 02_xxx.ev4_03.mp4
    -rw-r--r--. 1 root root 3223771 Oct 27 16:11 02_xxx.ev4_04.mp4
    -rw-r--r--. 1 root root 3004679 Oct 27 16:11 02_xxx.ev4_05.mp4
    -rw-r--r--. 1 root root 3550070 Oct 27 16:11 02_xxx.ev4_06.mp4
    -rw-r--r--. 1 root root 3362422 Oct 27 16:11 02_xxx.ev4_07.mp4
    -rw-r--r--. 1 root root 3365144 Oct 27 16:11 02_xxx.ev4_08.mp4
    -rw-r--r--. 1 root root 3301078 Oct 27 16:11 02_xxx.ev4_09.mp4
    -rw-r--r--. 1 root root 3485420 Oct 27 16:11 02_xxx.ev4_10.mp4
    -rw-r--r--. 1 root root 3468156 Oct 27 16:11 02_xxx.ev4_11.mp4
    -rw-r--r--. 1 root root 3588643 Oct 27 16:11 02_xxx.ev4_12.mp4
    -rw-r--r--. 1 root root 1922392 Oct 27 16:11 02_xxx.ev4_13.mp4

    常见的一些问题:

    -ss 放在-i前后的问题

    https://wuyuans.com/2012/04/ffmpeg-split

    一些其他用法:

    参考:http://blog.51cto.com/yuanhuan/1246370

    https://www.jianshu.com/p/2975f4efd808

     补充,由于py2.7以及py3以上popen已经废弃,使用subprocess来替代,这里改写了下脚本

     1 #!/usr/local/src/Python-2.7.15/python
     2 import string
     3 
     4 import os 
     5 import time
     6 import re
     7 import math
     8 import sys
     9 from optparse import OptionParser
    10 import subprocess
    11 print "Test by gongjia start..."
    12 
    13 
    14 parser = OptionParser()
    15 parser.add_option("-i", "--input", dest="input",action="store_true",help="input x y for each file by user")
    16 parser.add_option("-q", "--quality", dest="q",action="store",help="input xvid q arg",default="24")
    17 parser.add_option("-v", "--vcodec", dest="vcodec",action="store",help="input video codec",default="x264")
    18 parser.add_option("-n", "--noaudio", dest="an",action="store_true",help="no audio")
    19 parser.add_option("-p", "--preset", dest="preset",action="store",help="",default="")
    20 parser.add_option("-m", "--maxWidth", dest="maxWidth",action="store",help="input max width for output video",default="")
    21 parser.add_option("-f", "--fileType", dest="fileType",action="store",help="",default="mp4")
    22 parser.add_option("-o", "--ogg", dest="ogg",action="store_true",help="user ogg instead of aac",default="")
    23 parser.add_option("-3", "--mp3", dest="mp3",action="store_true",help="user mp3 instead of aac",default="")
    24 parser.add_option("-1", "--pad", dest="pad",action="store_true",help="pad to 16:9",default="")
    25 parser.add_option("-s", "--src", dest="srcD",action="store",help="source dir",default="/usr/local/src/test/videoin")
    26 parser.add_option("-t", "--target", dest="targetD",action="store",help="target dir",default="/usr/local/src/test/videoout")
    27 parser.add_option("-w", "--workdir", dest="workdir",action="store",help="work dir",default="/usr/local/src/test/video")
    28 parser.add_option("-e", "--split", dest="split",action="store_true",help="split to multiple file with size")
    29 parser.add_option("-d", "--splitsize", dest="splitsize",action="store",help="split to multiple file with size",default="2")#Minutes
    30 parser.add_option("-j", "--prefix", dest="prefix",action="store",help="target file name prefix",default="")
    31 
    32 (options, args) = parser.parse_args()
    33 
    34 if options.srcD==None or options.srcD[0:1]=='-':
    35     print 'srcD Err, quit'
    36     exit() 
    37 if options.targetD==None or options.targetD[0:1]=='-':
    38     print 'targetD Err, quit'
    39     exit() 
    40 if options.fileType==None or options.fileType[0:1]=='-':
    41     print 'fileType Err, quit'
    42     exit() 
    43 if options.workdir==None or options.workdir[0:1]=='-':
    44     print 'workdir Err, quit'
    45     exit() 
    46     
    47 #??videoin????
    48 for root,dirs,files in os.walk(options.srcD): 
    49     for name in files:
    50         name= name.replace('[','''[''')#??????[????
    51         newname =name[0: name.rindex('.')]      
    52         print "Test newname: " + newname
    53         print "Test name: " + name
    54         os.chdir(options.workdir)
    55         cmd ='mkdir -p ffm;rm -f ffm/ffm.txt;/usr/local/src/ffmpeg-git-20181015-64bit-static/ffmpeg -i '+options.srcD+'/' +name+ ' >& ffm/ffm.txt;pwd'
    56         cmd1=['grep','Duration','ffm/ffm.txt']
    57         for i in cmd.split(';'):
    58             print i
    59             time.sleep(3)
    60             t1=subprocess.Popen(i,shell=True)
    61         obj=subprocess.Popen(cmd1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    62         (s1,s2)=obj.communicate()
    63         print s1
    64         reg='''Duration:s(d+):(d+):([d.]+)'''
    65         result = re.compile(reg).findall(s1)
    66         print result
    67         for c in result:
    68             print 'split file to',options.splitsize,'minutes, Duration:',c[0],c[1],c[2]
    69             duration = int(c[0])*3600 + int(c[1])*60+float(c[2])##????????s
    70             nameLength=int(math.log(int(duration / (int(options.splitsize)*60)) )/math.log(10)) + 1
    71             print nameLength
    72             for i in range(int(duration / (int(options.splitsize)*60)) + 1):##??????????
    73                 print i
    74                 if duration>int(options.splitsize)*60*(i+1):
    75                     _t = str(int(options.splitsize)*60)
    76                 else:
    77                     _t = str(duration-int(options.splitsize)*60*i)
    78                 os.chdir(options.workdir)
    79                 cmd = "touch ffm/output.log;/usr/local/src/ffmpeg-git-20181015-64bit-static/ffmpeg -y -i "+options.srcD+"/"+name+" -codec: copy -ss "+str(i*int(options.splitsize)*60)+" -t "+_t+" "+options.targetD+"/"+options.prefix+newname+'_'+string.replace(('%'+str(nameLength)+'s')%str(i),' ','0')+"."+options.fileType + ' >& ffm/output.log'
    80                 for i in cmd.split(';'):
    81                     print i
    82                     time.sleep(2)
    83                     t1=subprocess.Popen(i,shell=True)
    84                     print t1
    85                     
    86 time.sleep(3)
    View Code
  • 相关阅读:
    基本算法 st
    winServer服务器设置多用户同时远程访问!
    类的实例化顺序
    基于layui的数据列表展示数据中template的作用。使得日期等数据符合预期进行展示
    基于layui的laydate,在加载后台数据时laydate.render()不起作用。
    微信企业号两种常用搜索加载方式
    Docker搭建私有仓库registry
    第7章 Dockerfile详解
    第6章 docker数据管理
    第5章 Docker的四种网络模式
  • 原文地址:https://www.cnblogs.com/Dicky-Zhang/p/9867391.html
Copyright © 2011-2022 走看看