需求:
運營有若干批次的視頻。有上千個,視頻文件,有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
