天天看點

ffmpy3與ffmpeg的簡單使用

作者:音視訊流媒體技術

安裝

python ffmpy3與ffmpeg的安裝

https://blog.csdn.net/qq_40962368/article/details/90748852

ffmpy3的介紹:

ffmpy3 - ffmpy3 0.2.3 documentation

ffmpy3是一個用于FFmpeg的Python包裝器,最初是從ffmpy項目派生出來的。它根據提供的參數及其各自的選項編譯FFmpeg指令行,并使用Python的子程序執行它。

ffmpy3類似于FFmpeg使用的指令行方法。它可以讀取任意數量的輸入“檔案”(正常檔案、管道、網絡流、抓取裝置等),并寫入任意數量的輸出“檔案”。有關FFmpeg指令行選項和參數如何工作的詳細資訊,請參閱FFmpeg文檔。

ffmpy3支援FFmpeg的管道協定。這意味着可以将輸入資料傳遞到stdin并從stdout獲得輸出資料。

目前,ffmpy3已經為ffmpeg和ffprobe指令提供了包裝器,但是應該可以用它運作其他ffmpeg工具(例如ffserver)。

FFmpeg的簡單使用

一、格式轉換

最簡單的用法例子是将媒體從一種格式轉換為另一種格式(在本例中是從MP4轉換為MPEG傳輸流),同時保留所有其他屬性:

from ffmpy3 import FFmpeg
ff = FFmpeg(inputs={'test.mp4': None},
            outputs={'output.ts': None})
print(ff.cmd)
ff.run()           
ffmpy3與ffmpeg的簡單使用

二、轉碼

如果同時我們想用不同的解碼器重新編碼視訊和音頻,我們必須指定額外的輸出選項:

下面的例子:将音頻編碼為mp2格式,将視訊編碼為mpeg2video模式

from ffmpy3 import FFmpeg
# 這裡a就是指audio,v就是指video
ff = FFmpeg(inputs={'test.mp4': None},
            outputs={'output.ts': '-c:a mp2 -c:v mpeg2video'})
print(ff.cmd)
ff.run()           
ffmpeg -i test.mp4 -c:a mp2 -c:v mpeg2video output.ts
 
 
 
Input #0, ogg, from 'test.mp4':
 
Stream #0:1: Video: theora, yuv420p, 320x176, 25 fps, 25 tbr, 25 tbn, 25 tbc
 
Stream #0:2: Audio: vorbis, 48000 Hz, stereo, fltp, 160 kb/s
 
 
 
Stream mapping:
 
Stream #0:1 -> #0:0 (theora (native) -> mpeg2video (native))
 
Stream #0:2 -> #0:1 (vorbis (native) -> mp2 (native))
 
 
 
Output #0, mpegts, to 'output.ts':
 
Stream #0:0: Video: mpeg2video (Main), yuv420p, 320x176, q=2-31, 200 kb/s, 25 fps, 90k tbn, 25 tbc
 
Stream #0:1: Audio: mp2, 48000 Hz, stereo, s16, 384 kb/s           

相關學習資料推薦,點選下方連結免費報名,先碼住不迷路~】

【免費分享】音視訊學習資料包、大廠面試題、技術視訊和學習路線圖,資料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以點選加群免費領取~

ffmpy3與ffmpeg的簡單使用

三、多路分解

一個更複雜的使用示例是将MPEG傳輸流解複用為單獨的基本(音頻和視訊)流,并将它們儲存在儲存編解碼器的MP4容器中(注意這裡如何使用清單作為選項):

實作的效果就是音頻與視訊分離,音頻放入了audio.mp4檔案,視訊在video.mp4檔案

from ffmpy3 import FFmpeg
ff = FFmpeg(inputs={'input.ts': None},
            outputs={'video.mp4': ['-map', '0:0', '-c:a', 'copy', '-f', 'mp4'],
                     'audio.mp4': ['-map', '0:1', '-c:a', 'copy', '-f', 'mp4']})
print(ff.cmd)
ff.run()           
ffmpy3與ffmpeg的簡單使用
ffmpeg -i input.ts -map 0:0 -c:a copy -f mp4 video.mp4 -map 0:1 -c:a copy -f mp4 audio.mp4
 
 
 
Output #1, mp4, to 'audio.mp4':
 
Stream #1:0: Audio: mp2 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 384 kb/s
 
 
 
Output #0, mp4, to 'video.mp4':
 
Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 320x176 [SAR 1:1 DAR 20:11], q=-1--1, 25 fps, 12800 tbn, 25 tbc           

注意:不能混合選項的表達式格式,也就是說,不能有包含空格字元串的清單,除非不含有清單,将指令行作為一個整體字元串,即:['-map', '0:0', '-c:a', 'copy', '-f', 'mp4'] 或 '-map 0:0 -c:a copy -f mp4'

四、多路複用

将多路視訊和音頻重新編碼回MPEG傳輸流,即音頻與視訊的合成:

from ffmpy3 import FFmpeg
ff = FFmpeg(inputs={'video.mp4': None, 'audio.mp4': None},
            outputs={'output.ts': '-c:v h264 -c:a ac3'})
print(ff.cmd)
ff.run()           
Stream mapping:
 
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
 
Stream #1:0 -> #0:1 (mp3 (mp3float) -> ac3 (native))           

在某些情況下,必須保留輸入和輸出的順序(例如使用FFmpeg -map選項時)。在這些情況下,使用正常Python字典将不起作用,因為它不能保持順序。相反,使用OrderedDict。例如,我們希望将一個視訊和兩個音頻流多路複用到一個MPEG傳輸流中,使用不同的編解碼器對兩個音頻流進行重新編碼。這裡,我們使用OrderedDict來儲存輸入的順序,以便它們比對輸出選項中的流的順序:

from ffmpy3 import FFmpeg
from collections import OrderedDict
inputs = OrderedDict([('video.mp4', None), ('audio_1.mp3', None), ('audio_2.mp3', None)])
outputs = {'output.ts': '-map 0 -c:v h264 -map 1 -c:a:0 ac3 -map 2 -c:a:1 mp2'}
ff = FFmpeg(inputs=inputs, outputs=outputs)
print(ff.cmd)
ff.run()           

簡化輸出後的結果為:

ffmpeg -i video.mp4 -i audio_1.mp3 -i audio_2.mp3 -map 0 -c:v h264 -map 1 -c:a:0 ac3 -map 2 -c:a:1 mp2 output.ts
 
 
 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video.mp4':
 
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 320x176 [SAR 1:1 DAR 20:11], 241 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
 
 
 
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from 'audio_1.mp3':
 
Stream #1:0(und): Audio: mp3 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 384 kb/s (default)
 
 
 
Input #2, mov,mp4,m4a,3gp,3g2,mj2, from 'audio_2.mp3':
 
Stream #2:0(und): Audio: mp3 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 384 kb/s (default)
 
 
 
Stream mapping:
 
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
 
Stream #1:0 -> #0:1 (mp3 (mp3float) -> ac3 (native))
 
Stream #2:0 -> #0:2 (mp3 (mp3float) -> mp2 (native))
 
 
 
Output #0, mpegts, to 'output.ts':
 
Stream #0:0(und): Video: h264 (libx264), yuv420p(progressive), 320x176 [SAR 1:1 DAR 20:11], q=-1--1, 25 fps, 90k tbn, 25 tbc (default)
 
Stream #0:1(und): Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s (default)
 
Stream #0:2(und): Audio: mp2, 48000 Hz, stereo, s16, 384 kb/s (default)           

五、使用管道協定

ffmpy3可以從STDIN(standard input)讀取輸入,并将輸出寫入STDOUT(standard output)。這可以通過使用FFmpeg管道協定來實作。下面的示例從包含RGB格式原始視訊幀的檔案中讀取資料,并通過STDIN将其傳遞給ffmpy3;ffmpy3将用H.264編碼原始幀資料,并将其打包到一個MP4容器中,将輸出傳遞給STDOUT(注意,必須使用子程序将STDOUT重定向到管道中。管道為stdout值,否則輸出将丢失):

from ffmpy3 import FFmpeg
import subprocess
ff = FFmpeg(inputs={'pipe:0': '-f rawvideo -pix_fmt rgb24 -s:v 640x480'},
            outputs={'pipe:1': '-c:v h264 -f mp4'})
print(ff.cmd)
stdout, stderr = ff.run(input_data=open('rawvideo', 'rb').read(), stdout=subprocess.PIPE)           

六、異步執行

在某些情況下,您可能不希望運作FFmpeg并阻塞等待結果,或者在應用程式中引入多線程。在這種情況下,使用asyncio進行異步執行是可能的。

也可以在不使用多線程或阻塞的情況下處理FFmpeg輸出。

七、複雜指令行

FFmpeg指令行選項可能非常複雜,比如在使用過濾時。是以,了解使用ffmpy3建構指令行的一些規則非常重要。如果一個選項包含引号,則必須在沒有引号的選項清單中作為單獨的項指定。但是,如果選項使用一個字元串,則必須将被引用的選項的引号儲存在字元串中:

from ffmpy3 import FFmpeg
ff = FFmpeg(inputs={'input.ts': None},
            outputs={'output.ts': ['-vf', 'adif=0:-1:0, scale=iw/2:-1']})
print(ff.cmd)
ff = FFmpeg(inputs={'input.ts': None},
            outputs={'output.ts': '-vf "adif=0:-1:0, scale=iw/2:-1"'})
print(ff.cmd)           
ffmpeg -i input.ts -vf "adif=0:-1:0, scale=iw/2:-1" output.ts
ffmpeg -i input.ts -vf "adif=0:-1:0, scale=iw/2:-1" output.ts
 
Process finished with exit code 0           

一個更複雜的例子是指令行,它将時間碼燒錄成視訊:

ffmpeg -i input.ts -vf "drawtext=fontfile=/Library/Fonts/Verdana.ttf: timecode='09\:57\:00\:00': r=25: x=(w-tw)/2: y=h-(2*lh): fontcolor=white: box=1: boxcolor=0x00000000@1" -an output.ts           

在ffmpy3中可以表示為:

from ffmpy3 import FFmpeg
ff = FFmpeg(inputs={'input.ts': None},
            outputs={'output.ts': ['-vf', "drawtext=fontfile=/Library/Fonts/Verdana.ttf: timecode='09\:57\:00\:00': r=25: x=(w-tw)/2: y=h-(2*lh): fontcolor=white: box=1: boxcolor=0x00000000@1", '-an']})
print(ff.cmd)           

相同的指令行可以編譯通過傳遞輸出選項作為一個字元串,同時保留引号:

from ffmpy3 import FFmpeg
ff = FFmpeg(inputs={'input.ts': None},
            outputs={'output.ts': "-vf \"drawtext=fontfile=/Library/Fonts/Verdana.ttf: timecode='09\:57\:00\:00': r=25: x=(w-tw)/2: y=h-(2*lh): fontcolor=white: box=1: boxcolor=0x00000000@1\" -an"})
print(ff.cmd)           

原文 ffmpy3與ffmpeg的簡單使用_Jumping boy的部落格-CSDN部落格