欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Python+OpenCV制作屏幕錄制工具

 更新時(shí)間:2022年04月22日 12:20:58   作者:程序員小二  
這篇文章主要介紹了如何利用Python?OpenCV實(shí)現(xiàn)屏幕錄制工具的制作,文中的示例代碼講解詳細(xì),對(duì)我們的學(xué)習(xí)和工作有一定的價(jià)值,感興趣的可以學(xué)習(xí)一下

最近有在使用屏幕錄制軟件錄制桌面,在用的過(guò)程中突發(fā)奇想,使用python能不能做屏幕錄制工具,也鍛煉下自己的動(dòng)手能力。接下準(zhǔn)備寫(xiě)使用python如何做屏幕錄制工具的系列文章:

錄制屏幕制作視頻

錄制音頻

合成視頻,音頻

基于pyqt5制作可視化窗口

大概上述四個(gè)部分,希望自己能夠盡快完善,接下來(lái)開(kāi)始使用python制作屏幕錄制部分。

應(yīng)用平臺(tái)

  • windows 10
  • python 3.7

屏幕錄制部分

屏幕錄制可以簡(jiǎn)單地理解為將屏幕快照以動(dòng)圖的形式播放,這里我選用PIL下的ImageGrab來(lái)截取屏幕畫(huà)面,首先

pip install Pillow

之后需要將截取到的快照數(shù)組合成為視頻,使用cv2模塊

pip install opencv-python

ImageGrab類(lèi)不能直接存儲(chǔ)為視頻,使用numpy模塊進(jìn)行數(shù)組化,再通過(guò)cv2.COLOR_BGR2RGB轉(zhuǎn)換為cv2色彩通道。

pip install numpy

屏幕錄制主要代碼:

import?numpy?as?np
from?PIL?import?ImageGrab
import?cv2

im?=?ImageGrab.grab()
width,?high?=?im.size??#?獲取屏幕的寬和高
fourcc?=?cv2.VideoWriter_fourcc(*'I420')??#?設(shè)置視頻編碼格式
fps?=?15??#?設(shè)置幀率
video?=?cv2.VideoWriter('test.avi',?fourcc,?fps,?(width,?high))
while?True:??#?開(kāi)始錄制
????im?=?ImageGrab.grab()
????im_cv?=?cv2.cvtColor(np.array(im),?cv2.COLOR_BGR2RGB)
????#?圖像寫(xiě)入
????video.write(im_cv)
????if?xx:??#?當(dāng)某某條件滿(mǎn)足中斷循環(huán)
????????break
video.release()??#?釋放緩存,持久化視頻

測(cè)試運(yùn)行可以保存屏幕快照為視頻,但操作起來(lái)不優(yōu)雅,也不利于后續(xù)的操作。

封裝成類(lèi),繼承線(xiàn)程父類(lèi),方便使用鍵盤(pán)來(lái)控制視頻錄制的結(jié)束。

from?threading?import?Thread

class?ScreenshotVideo(Thread):

????def?__init__(self):
?????"""初始化參數(shù)"""
????????super().__init__()

詳細(xì)代碼將在文末給出。

計(jì)算視頻最優(yōu)fps及使用numpy計(jì)算中間幀數(shù)組

實(shí)際操作中視頻錄制在不同電腦中會(huì)出現(xiàn)不一樣的幀率,導(dǎo)致視頻播放或快或慢,需要根據(jù)不同的電腦計(jì)算出相應(yīng)的最優(yōu)fps值。

def?video_best_fps(self,?path):
????"""獲取電腦錄制視頻的最優(yōu)幀率"""
????video?=?cv2.VideoCapture(path)??#?讀取視頻
????fps?=?video.get(cv2.CAP_PROP_FPS)??#?獲取當(dāng)前視頻的幀率
????count?=?video.get(cv2.CAP_PROP_FRAME_COUNT)??#?獲取視頻幀數(shù),即該視頻有多少幅畫(huà)面
????self.best_fps?=?int(fps?*?((int(count)?/?fps)?/?self.spend_time))???#?計(jì)算播放時(shí)間與錄制時(shí)間對(duì)比得到最優(yōu)幀率
????video.release()

再調(diào)整幀率參數(shù)進(jìn)行錄制視頻就減弱了視頻播放太快或者太慢。也可以給視頻增加幀數(shù)從而延長(zhǎng)播放時(shí)間,這里我采用一種很簡(jiǎn)單的方法增加視頻幀,僅供參考。

from?numba?import?jit

#?使用numpy計(jì)算相鄰兩幀圖像且更接近于后一幀的圖像
#?調(diào)用jit方法加速數(shù)組計(jì)算
@jit(nopython=True)
def?average_n(x,?y):
????"""Numpy計(jì)算趨近值"""
????return?((x?+?y?+?y)?//?3).astype(x.dtype)

該方法僅針對(duì)于設(shè)置的fps比最優(yōu)fps要高時(shí),處理后的視頻觀感,視頻還是較為急促,但是細(xì)節(jié)幀增多,所以播放時(shí)長(zhǎng)會(huì)比未處理前的要長(zhǎng),略有殘影。

使用pynput監(jiān)聽(tīng)鍵盤(pán)按鍵

在視頻錄制中,并不知道視頻何時(shí)結(jié)束,所以用while循環(huán)包裹錄制代碼,但也不可能讓代碼無(wú)休止的運(yùn)行下去,在此使用監(jiān)聽(tīng)鍵盤(pán)模塊來(lái)中斷錄制代碼的運(yùn)行。

from?pynput?import?keyboard??#?pip?install?pynput

def?hotkey(self):
????"""熱鍵監(jiān)聽(tīng)"""
????with?keyboard.Listener(on_press=self.on_press)?as?listener:
????????listener.join()

def?on_press(self,?key):
????try:
????????if?key.char?==?'t':??#?錄屏結(jié)束,保存視頻
????????????self.flag?=?True
????????elif?key.char?==?'k':??#?錄屏中止,刪除文件
????????????self.flag?=?True
????????????self.kill?=?True
????except?Exception?as?e:
????????print(e)

按下鍵盤(pán)“T”鍵時(shí),結(jié)束錄制,保存視頻。“K”鍵則是停止錄制,刪除緩存文件。

如何保存MP4格式視頻

視頻編碼格式應(yīng)該為('a', 'v', 'c', '1'),文件后綴為'.mp4',在錄制前先去https://github.com/cisco/openh264/releases下下載對(duì)應(yīng)平臺(tái)的dll.bz2文件,將壓縮包解壓放在項(xiàng)目文件夾下。再運(yùn)行代碼,成功會(huì)出現(xiàn)一行編碼說(shuō)明:

OpenH264 Video Codec provided by Cisco Systems, Inc.

源碼

本文實(shí)現(xiàn)的源碼如下:

import?time
from?PIL?import?ImageGrab
import?cv2
from?pathlib?import?Path
import?numpy?as?np
from?numba?import?jit
from?pynput?import?keyboard
from?threading?import?Thread


@jit(nopython=True)
def?average_n(x,?y):
????"""Numpy計(jì)算趨近值"""
????return?((x?+?y?+?y)?//?3).astype(x.dtype)


class?ScreenshotVideo(Thread):

????def?__init__(self,?width,?high,?path='',?fps=15):
????????"""初始化參數(shù)"""
????????super().__init__()
????????self.save_file?=?path
????????self.best_fps?=?fps
????????self.fps?=?fps
????????self.width?=?width
????????self.high?=?high
????????self.spend_time?=?1
????????self.flag?=?False
????????self.kill?=?False
????????self.video?=?None

????def?__call__(self,?path):
????????"""重載視頻路徑,便于類(lèi)的二次調(diào)用"""
????????self.save_file?=?Path(path)
????????self.video?=?self.init_videowriter(self.save_file)

????@staticmethod
????def?screenshot():
????????"""靜態(tài)方法,屏幕截圖,并轉(zhuǎn)換為np.array數(shù)組"""
????????return?np.array(ImageGrab.grab())

????@staticmethod
????def?get_fourcc(name):
????????"""視頻編碼字典"""
????????fourcc_maps?=?{'.avi':?'I420',
???????????????????????'.m4v':?'mp4v',
???????????????????????'.mp4':?'avc1',
???????????????????????'.ogv':?'THEO',
???????????????????????'.flv':?'FLV1',
???????????????????????}
????????return?fourcc_maps.get(name)

????def?init_videowriter(self,?path):
????????"""獲取視頻編碼并新建視頻文件"""
????????if?not?path:
????????????raise?Exception('視頻路徑未設(shè)置,請(qǐng)?jiān)O(shè)置\nvideo?=?ScreenshotVideo(fps,width,high)\nvideo?=?video(video_path)')
????????path?=?Path(path)?if?isinstance(path,?str)?else?path
????????fourcc?=?cv2.VideoWriter_fourcc(*self.get_fourcc(path.suffix))
????????return?cv2.VideoWriter(path.as_posix(),?fourcc,?self.fps,?(self.width,?self.high))

????def?video_record_doing(self,?img):
????????"""將BGR數(shù)組轉(zhuǎn)換為RGB數(shù)組"""
????????im_cv?=?cv2.cvtColor(img,?cv2.COLOR_BGR2RGB)
????????self.video.write(im_cv)

????def?video_record_end(self):
????????"""錄制結(jié)束,根據(jù)條件判斷文件是否保存"""
????????self.video.release()
????????cv2.destroyAllWindows()
????????if?self.save_file?and?self.kill:
????????????Path(self.save_file).unlink()

????def?video_best_fps(self,?path):
????????"""獲取電腦錄制視頻的最優(yōu)幀率"""
????????video?=?cv2.VideoCapture(path)
????????fps?=?video.get(cv2.CAP_PROP_FPS)
????????count?=?video.get(cv2.CAP_PROP_FRAME_COUNT)
????????self.best_fps?=?int(fps?*?((int(count)?/?fps)?/?self.spend_time))
????????video.release()

????def?pre_video_record(self):
????????"""預(yù)錄制,以獲取最佳fps值"""
????????self.video?=?self.init_videowriter('test.mp4')
????????start_time?=?time.time()
????????for?_?in?range(10):
????????????im?=?self.screenshot()
????????????self.video_record_doing(im)
????????self.spend_time?=?round(time.time()?-?start_time,?4)
????????self.video_record_end()
????????time.sleep(2)
????????self.video_best_fps('test.mp4')
????????Path('test.mp4').unlink()

????def?insert_frame_array(self,?frame_list):
????????"""Numpy增強(qiáng)截圖信息"""
????????fps_n?=?round(self.fps?/?self.best_fps)
????????if?fps_n?<=?0:
????????????return?frame_list
????????times?=?int(np.log2(fps_n))??#?倍率
????????for?_?in?range(times):
????????????frame_list2?=?map(average_n,?[frame_list[0]]?+?frame_list[:-1],?frame_list)
????????????frame_list?=?[[x,?y]?for?x,?y?in?zip(frame_list2,?frame_list)]
????????????frame_list?=?[j?for?i?in?frame_list?for?j?in?i]
????????return?frame_list

????def?frame2video_run(self):
????????"""使用opencv將連續(xù)型截圖轉(zhuǎn)換為視頻"""
????????self.video?=?self.init_videowriter(self.save_file)
????????start_time?=?time.time()
????????frame_list?=?[]
????????while?True:
????????????frame_list.append(self.screenshot())
????????????if?self.flag:
????????????????break
????????self.spend_time?=?round(time.time()?-?start_time,?4)
????????if?not?self.kill:??#?視頻錄制不被終止將逐幀處理圖像
????????????frame_list?=?self.insert_frame_array(frame_list)
????????????for?im?in?frame_list:
????????????????self.video_record_doing(im)
????????self.video_record_end()

????def?hotkey(self):
????????"""熱鍵監(jiān)聽(tīng)"""
????????with?keyboard.Listener(on_press=self.on_press)?as?listener:
????????????listener.join()

????def?on_press(self,?key):
????????try:
????????????if?key.char?==?'t':??#?錄屏結(jié)束,保存視頻
????????????????self.flag?=?True
????????????elif?key.char?==?'k':??#?錄屏中止,刪除文件
????????????????self.flag?=?True
????????????????self.kill?=?True
????????except?Exception?as?e:
????????????print(e)

????def?run(self):
????????#?運(yùn)行函數(shù)
????????#?設(shè)置守護(hù)線(xiàn)程
????????Thread(target=self.hotkey,?daemon=True).start()
????????#?運(yùn)行截圖函數(shù)
????????self.frame2video_run()


screen?=?ImageGrab.grab()
width,?high?=?screen.size
video?=?ScreenshotVideo(width,?high,?fps=60)
video.pre_video_record()??#?預(yù)錄制獲取最優(yōu)fps
video('test1.mp4')
video.run()

總結(jié)

本文目前使用了opencv和相關(guān)模塊對(duì)屏幕進(jìn)行錄制并轉(zhuǎn)換為視頻保存,學(xué)習(xí)將多個(gè)函數(shù)封裝為類(lèi),方便后續(xù)功能開(kāi)發(fā)。學(xué)習(xí)的道路是無(wú)止境的,大膽的邁步走吧!

以上就是基于Python+OpenCV制作屏幕錄制工具的詳細(xì)內(nèi)容,更多關(guān)于Python OpenCV屏幕錄制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決Pycharm 包已經(jīng)下載,但是運(yùn)行代碼提示找不到模塊的問(wèn)題

    解決Pycharm 包已經(jīng)下載,但是運(yùn)行代碼提示找不到模塊的問(wèn)題

    今天小編就為大家分享一篇解決Pycharm 包已經(jīng)下載,但是運(yùn)行代碼提示找不到模塊的問(wèn)題。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-08-08
  • 5分鐘教會(huì)你用Docker部署一個(gè)Python應(yīng)用

    5分鐘教會(huì)你用Docker部署一個(gè)Python應(yīng)用

    Docker是一個(gè)開(kāi)源項(xiàng)目,為開(kāi)發(fā)人員和系統(tǒng)管理員提供了一個(gè)開(kāi)放平臺(tái),可以將應(yīng)用程序構(gòu)建、打包為一個(gè)輕量級(jí)容器,并在任何地方運(yùn)行,下面這篇文章主要給大家介紹了關(guān)于如何通過(guò)5分鐘教會(huì)你用Docker部署一個(gè)Python應(yīng)用,需要的朋友可以參考下
    2022-06-06
  • python協(xié)程之動(dòng)態(tài)添加任務(wù)的方法

    python協(xié)程之動(dòng)態(tài)添加任務(wù)的方法

    今天小編就為大家分享一篇python協(xié)程之動(dòng)態(tài)添加任務(wù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • Python Excel處理庫(kù)openpyxl使用詳解

    Python Excel處理庫(kù)openpyxl使用詳解

    openpyxl是一個(gè)第三方庫(kù),可以處理xlsx格式的Excel文件。這篇文章主要介紹了Python Excel處理庫(kù)openpyxl使用詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-05-05
  • Python中使用logging和traceback模塊記錄日志和跟蹤異常

    Python中使用logging和traceback模塊記錄日志和跟蹤異常

    今天小編就為大家分享一篇關(guān)于Python中使用logging和traceback模塊記錄日志和跟蹤異常,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • python使用原始套接字發(fā)送二層包(鏈路層幀)的方法

    python使用原始套接字發(fā)送二層包(鏈路層幀)的方法

    今天小編就為大家分享一篇python使用原始套接字發(fā)送二層包(鏈路層幀)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • Python識(shí)別二維碼的兩種方法詳解

    Python識(shí)別二維碼的兩種方法詳解

    在學(xué)習(xí)Python處理二維碼的過(guò)程中,我們看到的大多是“用python生成酷炫二維碼”、“用Python制作動(dòng)圖二維碼”之類(lèi)的文章。而關(guān)于使用Python批量識(shí)別二維碼的教程,并不多見(jiàn)。本文就為大家總結(jié)了Python識(shí)別二維碼的兩種方法,感興趣的可以學(xué)習(xí)一下
    2022-06-06
  • python去除空格,tab制表符和\n換行符的小技巧分享

    python去除空格,tab制表符和\n換行符的小技巧分享

    這篇文章主要介紹了python去除空格,tab制表符和\n換行符的小技巧,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Python的OptionParser模塊示例教程

    Python的OptionParser模塊示例教程

    這篇文章主要介紹了Python的OptionParser模塊教程,本文通過(guò)示例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01
  • python3音樂(lè)播放器簡(jiǎn)單實(shí)現(xiàn)代碼

    python3音樂(lè)播放器簡(jiǎn)單實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了python3音樂(lè)播放器簡(jiǎn)單實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06

最新評(píng)論