Python使用ffmpeg合成視頻、音頻的實現(xiàn)方法
最近有在使用屏幕錄制軟件錄制桌面,在用的過程中突發(fā)奇想,使用python能不能做屏幕錄制工具,也鍛煉下自己的動手能力。
接下準備寫使用python如何做屏幕錄制工具的系列文章:
大概上述四個部分,希望自己能夠盡快完善,前兩篇文章分享了利用opencv制作了屏幕錄制部分,利用PyAudio錄制音頻,本篇文章分享如何使用ffmpeg將同時錄制的屏幕錄像和音頻合成為有聲音的屏幕錄像。
應用平臺
- windows 10
- python 3.7
- ffmpeg
音視頻合成
在python合成音視頻有很多第三方包,操作方法各有不同,有簡易的也有稍微復雜的,
起初也有想過使用moviepy中文文檔,其在使用門檻上確實比ffmpeg要小很多,在翻查相關資料后,目前要考慮的事是合并音視頻為一個有聲音的視頻,而且ffmpeg具有錄制視頻的功能,效果比使用cv2+ImageGrab方式要好,所以采用ffmpeg作為合成工具,ffmpeg.exe下載路徑,使用手冊 。
python下使用ffmpeg,可以直接調(diào)用命令行工具,也可以使用封裝的第三包。
pip install ffmpeg-python
使用參數(shù)與ffmpeg一致,不同處在于,在使用完后需要鍵入終止條件以結(jié)束ffmpeg的運行。
將cv2的屏幕錄制改成ffmpeg錄制
import ffmpeg
# 屏幕錄制畫面大小
width = 1920
height = 1080
# 錄制幀率,在cv2錄制中,發(fā)現(xiàn)幀率比較固定且偏小,主要原因為ImageGrab間隔時間稍長
# 這里可以調(diào)整的稍微大一點,當然越大對固件性能越好,推薦在15~60之間(含)
fps = 30
# 錄制畫面是否包含鼠標,0:不包含,1:包含
# 錄制方式為gdigrab模式,包含鼠標在錄制過程會看到鼠標頻閃的現(xiàn)象,可自行搜索模塊插件解決
draw_mouse = 0
# 屏幕畫面錄制偏移距離
offset_x = 0
offset_y = 0
# 文件名稱
filename = 'test.mp4'
# 錄制桌面
process = (
ffmpeg.output(
ffmpeg.input(
filename='desktop', format='gdigrab', framerate=fps, offset_x=offset_x, offset_y=offset_y,
draw_mouse=draw_mouse, s=f'{width}x{height}'),
filename=filename, pix_fmt='yuv420p'
).overwrite_output()
)
# cmd: ffmpeg路徑,如不設置,會搜尋環(huán)境變量下的ffmpeg
# 可直接下載ffmpeg.exe到工程文件目錄下
ffmpeg_path = 'ffmpeg.exe'
process.run_async(cmd=ffmpeg_path, pipe_stdin=True, pipe_stdout=False, pipe_stderr=False)
# 自定義延時函數(shù)
delay()
# 傳入中斷參數(shù),在調(diào)用之前,盡量在之前有足夠的延時
process.communicate(str.encode("q"))
process.terminate()合成音視頻
# 傳入的視頻路徑
video_path = 'mp4_test.mp4'
# 傳入的音頻路徑
audio_path = 'mp3_test.mp3'
# 生成的視頻名稱,不要和上述的路徑一致
output_path = 'mixer.mp4'
process = (
ffmpeg.output(
ffmpeg.input(filename=video_path),
ffmpeg.input(filename=audio_path),
filename=output_path, vcodec='copy', acodec='aac', strict='experimental', pix_fmt='yuv420p'
).overwrite_output()
ffmpeg_path = 'ffmpeg.exe'
process.run_async(cmd=ffmpeg_path, pipe_stdin=True, pipe_stdout=False, pipe_stderr=False)
time.sleep(1)
process.communicate(str.encode("q"))
process.terminate()
ps: 上述方法也可以封裝到類中,方便pyqt5窗口的實現(xiàn)。
看到這里可能會想到,有音頻錄制,視頻錄制,音視頻合成,但是不好讓音視頻分開錄制,導致音視頻不同步,看起來也別扭,下面就來實現(xiàn)將兩者同時錄制同時結(jié)束。
可沿用錄制屏幕制作視頻(推薦用本篇下方的代碼),錄制音頻 兩篇里的代碼,將關于鍵盤監(jiān)聽部分注釋掉,避免沖突。
from threading import Thread
from pynput import keyboard
from Audio_record import AudioRecord
from Screenshot_record import Screenshot
def hotkey():
"""熱鍵監(jiān)聽"""
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
def on_press(key):
try:
video.terminate()
if key.char == 't': # t鍵,錄制結(jié)束,保存音視頻
audio.stop_flag = True
elif key.char == 'k': # k鍵,錄制中止,刪除文件
audio.kill = True
video.unlink('test.mp4')
except Exception as e:
print(e)
key_thread = Thread(target=hotkey, daemon=True)
audio = AudioRecord()
video = Screenshot()
key_thread.start()
audio.run(filename='test.mp3')
video.record('test.mp4')利用三組線程,當該代碼運行時就會監(jiān)聽鍵盤按鍵,同時錄制音頻、視頻,當按下t鍵結(jié)束錄制,保存音視頻。
總結(jié)
通過音視頻分線程錄制,保證兩個文件的時長一致且同步的情況,在這過程中學習了如何在python中調(diào)用ffmpeg模塊,對此進行音視頻合并,完成視頻合成。
遠處的峰亦不能遮擋看到山后的風景。
于二零二二年四月十七日作
ffmpeg錄屏源代碼:
"""
Screenshot_record.py 使用ffmpeg錄制屏幕
from pathlib import Path
import ffmpeg
class Screenshot:
def __init__(self, width=1920, height=1080, fps=15):
self.width = width
self.height = height
self.fps = fps
self.process = None
self.ffmpeg_path = file_path('ffmpeg.exe')
def __call__(self, width, height, fps=None):
self.fps = fps if fps else self.fps
@staticmethod
def unlink(filename):
Path(filename).unlink()
def record(self, filename, offset_x=0, offset_y=0, draw_mouse=0):
self.process = (
ffmpeg.output(
ffmpeg.input(
filename='desktop', format='gdigrab', framerate=self.fps, offset_x=offset_x, offset_y=offset_y,
draw_mouse=draw_mouse, s=f'{self.width}x{self.height}'),
filename=filename, pix_fmt='yuv420p'
).overwrite_output()
)
self.ffmpeg_async()
def compose_audio(self, video_path, audio_path, output_path):
ffmpeg.input(filename=video_path),
ffmpeg.input(filename=audio_path),
filename=output_path, vcodec='copy', acodec='aac', strict='experimental', pix_fmt='yuv420p'
def ffmpeg_async(self):
self.process = self.process.run_async(cmd=self.ffmpeg_path, pipe_stdin=True, pipe_stdout=False,
pipe_stderr=False)
def terminate(self):
if self.process is not None:
self.process.communicate(str.encode("q"))
self.process.terminate()
self.process = None到此這篇關于Python使用ffmpeg合成視頻、音頻的文章就介紹到這了,更多相關python ffmpeg合成視頻音頻內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python capitalize()函數(shù)的用法詳解
在Python中,capitalize()將字符串的第一個字符轉(zhuǎn)換為大寫字母,并將所有其他字符(如果有的話)轉(zhuǎn)換為小寫,本文就將給大家介紹一下Python capitalize()函數(shù)的使用方法,感興趣的朋友跟著小編一起來看看吧2023-07-07
用Python代碼自動生成文獻的IEEE引用格式的實現(xiàn)
這篇文章主要介紹了用Python代碼自動生成文獻的IEEE引用格式的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03
python 百度aip實現(xiàn)文字識別的實現(xiàn)示例
百度aip將圖片或掃描件中的文字識別成可編輯的文本,本文主要介紹了python 百度aip實現(xiàn)文字識別,具有一定的參考價值,感興趣的可以了解一下2021-08-08
Python的ORM框架中SQLAlchemy庫的查詢操作的教程
這篇文章主要介紹了Python的ORM框架中SQLAlchemy庫的查詢操作的教程,SQLAlchemy用來操作數(shù)據(jù)庫十分方便,需要的朋友可以參考下2015-04-04
Python3編碼問題 Unicode utf-8 bytes互轉(zhuǎn)方法
今天小編就為大家分享一篇Python3編碼問題 Unicode utf-8 bytes互轉(zhuǎn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10

