網站首頁 編程語言 正文
最近有在使用屏幕錄制軟件錄制桌面,在用的過程中突發奇想,使用python能不能做屏幕錄制工具,也鍛煉下自己的動手能力。
接下準備寫使用python如何做屏幕錄制工具的系列文章:
錄制屏幕制作視頻
錄制音頻
合成視頻,音頻
基于pyqt5制作可視化窗口
大概上述四個部分,希望自己能夠盡快完善,前兩篇文章分享了利用opencv制作了屏幕錄制部分,利用PyAudio錄制音頻,本篇文章分享如何使用ffmpeg將同時錄制的屏幕錄像和音頻合成為有聲音的屏幕錄像。
應用平臺
- windows 10
- python 3.7
- ffmpeg
音視頻合成
在python合成音視頻有很多第三方包,操作方法各有不同,有簡易的也有稍微復雜的,
起初也有想過使用moviepy
中文文檔,其在使用門檻上確實比ffmpeg
要小很多,在翻查相關資料后,目前要考慮的事是合并音視頻為一個有聲音的視頻,而且ffmpeg具有錄制視頻的功能,效果比使用cv2+ImageGrab
方式要好,所以采用ffmpeg
作為合成工具,ffmpeg.exe下載路徑,使用手冊 。
python下使用ffmpeg,可以直接調用命令行工具,也可以使用封裝的第三包。
pip install ffmpeg-python
使用參數與ffmpeg
一致,不同處在于,在使用完后需要鍵入終止條件以結束ffmpeg的運行。
將cv2的屏幕錄制改成ffmpeg錄制
import ffmpeg # 屏幕錄制畫面大小 width = 1920 height = 1080 # 錄制幀率,在cv2錄制中,發現幀率比較固定且偏小,主要原因為ImageGrab間隔時間稍長 # 這里可以調整的稍微大一點,當然越大對固件性能越好,推薦在15~60之間(含) fps = 30 # 錄制畫面是否包含鼠標,0:不包含,1:包含 # 錄制方式為gdigrab模式,包含鼠標在錄制過程會看到鼠標頻閃的現象,可自行搜索模塊插件解決 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路徑,如不設置,會搜尋環境變量下的ffmpeg # 可直接下載ffmpeg.exe到工程文件目錄下 ffmpeg_path = 'ffmpeg.exe' process.run_async(cmd=ffmpeg_path, pipe_stdin=True, pipe_stdout=False, pipe_stderr=False) # 自定義延時函數 delay() # 傳入中斷參數,在調用之前,盡量在之前有足夠的延時 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窗口的實現。
看到這里可能會想到,有音頻錄制,視頻錄制,音視頻合成,但是不好讓音視頻分開錄制,導致音視頻不同步,看起來也別扭,下面就來實現將兩者同時錄制同時結束。
可沿用錄制屏幕制作視頻(推薦用本篇下方的代碼),錄制音頻 兩篇里的代碼,將關于鍵盤監聽部分注釋掉,避免沖突。
from threading import Thread from pynput import keyboard from Audio_record import AudioRecord from Screenshot_record import Screenshot def hotkey(): """熱鍵監聽""" with keyboard.Listener(on_press=on_press) as listener: listener.join() def on_press(key): try: video.terminate() if key.char == 't': # t鍵,錄制結束,保存音視頻 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')
利用三組線程,當該代碼運行時就會監聽鍵盤按鍵,同時錄制音頻、視頻,當按下t鍵結束錄制,保存音視頻。
總結
通過音視頻分線程錄制,保證兩個文件的時長一致且同步的情況,在這過程中學習了如何在python中調用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
原文鏈接:https://blog.csdn.net/weixin_46281427/article/details/124228056
相關推薦
- 2023-12-13 SpringMVC——訪問action報404錯誤詳解
- 2022-09-25 注解@Autowired如何自動裝配
- 2022-02-10 C語言之初識指針_C 語言
- 2023-05-26 Pycharm直接使用遠程服務器代碼并調試的解決方法_python
- 2021-09-09 Linux下NTP服務器配置詳細過程_Linux
- 2022-12-01 django第一個項目127.0.0.1:8000不能訪問的解決方案詳析_python
- 2022-01-10 微信小程序報錯 Cannot read property ‘forceUpdate‘ of u
- 2022-10-17 C++右值引用與move和forward函數的使用詳解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支