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\n']
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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM