最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python結(jié)合ffmpeg 實(shí)現(xiàn)單線程和多線程推流

 更新時(shí)間:2025年06月17日 10:21:19   作者:浪浪山小白兔  
本文主要介紹了Python結(jié)合ffmpeg 實(shí)現(xiàn)單線程和多線程推流,將通過兩個(gè)不同的實(shí)現(xiàn)方式,即單線程推流和多線程推流,來展示如何利用?cv2(OpenCV)和?subprocess?等庫將視頻幀推送到指定的 RTMP 地址,感興趣的可以了解一下

一、引言

在本文中,我們將詳細(xì)介紹如何使用 Python 進(jìn)行視頻的推流操作。我們將通過兩個(gè)不同的實(shí)現(xiàn)方式,即單線程推流和多線程推流,來展示如何利用 cv2(OpenCV)和 subprocess 等庫將視頻幀推送到指定的 RTMP 地址。這兩種方式都涉及到從攝像頭讀取視頻幀,以及使用 ffmpeg 命令行工具將視頻幀進(jìn)行編碼和推流的過程。

二、單線程推流

以下是單線程推流的代碼:

import cv2 as cv
import subprocess as sp


def push_stream():
    # 視頻讀取對象
    cap = cv.VideoCapture(0) 
    fps = int(cap.get(cv.CAP_PROP_FPS))
    w = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
    h = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))
    ret, frame = cap.read()
    # 推流地址
    rtmpUrl = "rtmp://192.168.3.33:1935/live/"
    # 推流參數(shù)
    command = ['ffmpeg',
              '-y',
              '-f', 'rawvideo',
              '-vcodec','rawvideo',
              '-pix_fmt', 'bgr24',
              '-s', "{}x{}".format(w, h),
              '-r', str(fps),
              '-i', '-',
              '-c:v', 'libx264',
              '-pix_fmt', 'yuv420p',
              '-preset', 'ultrafast',
              '-f', 'flv', 
              rtmpUrl]
    # 創(chuàng)建、管理子進(jìn)程
    pipe = sp.Popen(command, stdin=sp.PIPE, bufsize=10 ** 8)
    # 循環(huán)讀取
    while cap.isOpened():
        # 讀取一幀
        ret, frame = cap.read()
        if frame is None:
            print('read frame err!')
            continue
        # 顯示一幀
        cv.imshow("frame", frame)
        # 按鍵退出
        if cv.waitKey(1) & 0xFF == ord('q'):
            break
        # 讀取尺寸、推流
        # img=cv.resize(frame,size)
        pipe.stdin.write(frame) 
    # 關(guān)閉窗口
    cv.destroyAllWindows()
    # 停止讀取
    cap.release()

在這個(gè)單線程的實(shí)現(xiàn)中,我們執(zhí)行以下步驟:

初始化視頻讀取對象

  • 使用 cv2.VideoCapture(0) 來打開默認(rèn)的攝像頭設(shè)備。
  • 獲取攝像頭的幀率 fps、寬度 w 和高度 h 等參數(shù)。

設(shè)置推流地址和參數(shù)

  • 定義 rtmpUrl 作為推流的目標(biāo)地址。
  • 構(gòu)造 ffmpeg 的命令列表 command,該列表包含了一系列的參數(shù),如 -y 表示覆蓋輸出文件、-f rawvideo 表示輸入格式為原始視頻等。
  • 使用 sp.Popen 創(chuàng)建一個(gè)子進(jìn)程,將 ffmpeg 命令作為子進(jìn)程運(yùn)行,并且將其輸入管道 stdin 連接到我們的程序。

循環(huán)讀取和推流

  • 在一個(gè) while 循環(huán)中,不斷讀取攝像頭的幀。
  • 若讀取失敗,打印錯(cuò)誤信息并繼續(xù)。
  • 使用 cv2.imshow 顯示當(dāng)前幀,同時(shí)監(jiān)聽 q 鍵,按下 q 鍵時(shí)退出程序。
  • 將讀取到的幀通過管道發(fā)送給 ffmpeg 進(jìn)行推流。

三、多線程推流

以下是多線程推流的代碼:

import queue
import threading
import cv2 as cv
import subprocess as sp


class Live(object):
    def __init__(self):
        self.frame_queue = queue.Queue()
        self.command = ""
        # 自行設(shè)置
        self.rtmpUrl = ""
        self.camera_path = ""

    def read_frame(self):
        print("開啟推流")
        cap = cv.VideoCapture(self.camera_path)

        # Get video information
        fps = int(cap.get(cv.CAP_PROP_FPS))
        width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
        height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))

        # ffmpeg command
        self.command = ['ffmpeg',
                       '-y',
                       '-f', 'rawvideo',
                       '-vcodec','rawvideo',
                       '-pix_fmt', 'bgr24',
                       '-s', "{}x{}".format(width, height),
                       '-r', str(fps),
                       '-i', '-',
                       '-c:v', 'libx264',
                       '-pix_fmt', 'yuv420p',
                       '-preset', 'ultrafast',
                       '-f', 'flv', 
                       self.rtmpUrl]

        # read webcamera
        while(cap.isOpened()):
            ret, frame = cap.read()
            if not ret:
                print("Opening camera is failed")
                break

            # put frame into queue
            self.frame_queue.put(frame)

    def push_frame(self):
        # 防止多線程時(shí) command 未被設(shè)置
        while True:
            if len(self.command) > 0:
                # 管道配置
                p = sp.Popen(self.command, stdin=sp.PIPE)
                break

        while True:
            if self.frame_queue.empty()!= True:
                frame = self.frame_queue.get()
                # process frame
                # 你處理圖片的代碼
                # write to pipe
                p.stdin.write(frame.tostring())

    def run(self):
        threads = [
            threading.Thread(target=Live.read_frame, args=(self,)),
            threading.Thread(target=Live.push_frame, args=(self,))
        ]
        [thread.setDaemon(True) for thread in threads]
        [thread.start() for thread in threads]

在這個(gè)多線程的實(shí)現(xiàn)中,我們使用了 threading 和 queue 庫:

類的初始化

  • 創(chuàng)建一個(gè) Live 類,在 __init__ 方法中初始化幀隊(duì)列 frame_queue、commandrtmpUrl 和 camera_path 等變量。

讀取幀的線程方法

  • read_frame 方法中,使用 cv2.VideoCapture(self.camera_path) 打開攝像頭。
  • 獲取攝像頭的參數(shù),并構(gòu)造 ffmpeg 命令。
  • 不斷從攝像頭讀取幀,并將幀放入隊(duì)列 frame_queue 中。

推流的線程方法

  • push_frame 方法中,等待 command 被設(shè)置,然后使用 sp.Popen 啟動(dòng) ffmpeg 子進(jìn)程。
  • 從幀隊(duì)列中取出幀,并將其寫入 ffmpeg 的輸入管道進(jìn)行推流。

啟動(dòng)線程

  • run 方法創(chuàng)建并啟動(dòng)兩個(gè)線程,一個(gè)用于讀取幀,一個(gè)用于推流,并且將它們設(shè)置為守護(hù)線程。

四、代碼解釋和注意事項(xiàng)

單線程推流:

  • 這種方式相對簡單,適合初學(xué)者理解。但由于是單線程操作,在處理復(fù)雜任務(wù)時(shí)可能會(huì)導(dǎo)致性能瓶頸,特別是在同時(shí)進(jìn)行視頻顯示、讀取和推流的情況下,可能會(huì)出現(xiàn)卡頓現(xiàn)象。

多線程推流:

  • 利用多線程可以將不同的任務(wù)分配給不同的線程,提高性能。
  • frame_queue 是一個(gè)線程安全的隊(duì)列,用于在兩個(gè)線程之間傳遞幀數(shù)據(jù),避免了數(shù)據(jù)競爭問題。
  • setDaemon(True) 使得線程在主線程結(jié)束時(shí)自動(dòng)終止,防止程序無法正常退出。

五、總結(jié)

通過上述代碼和解釋,我們可以看到如何使用 Python 進(jìn)行單線程和多線程的視頻推流操作。單線程代碼簡單明了,但性能可能受限;多線程代碼可以更好地處理高負(fù)載,但也需要注意線程安全和資源管理等問題。在實(shí)際應(yīng)用中,我們可以根據(jù)具體的需求和硬件性能來選擇合適的推流方式。同時(shí),我們可以進(jìn)一步優(yōu)化代碼,例如添加異常處理、優(yōu)化幀處理邏輯等,以提高程序的穩(wěn)定性和性能。

到此這篇關(guān)于Python結(jié)合ffmpeg 實(shí)現(xiàn)單線程和多線程推流的文章就介紹到這了,更多相關(guān)Python ffmpeg 單線程和多線程推流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python的閉包和裝飾器你真的了解嗎

    Python的閉包和裝飾器你真的了解嗎

    這篇文章主要為大家詳細(xì)介紹了Python的閉包和裝飾器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • 零基礎(chǔ)也能輕松上手的Python自動(dòng)化辦公實(shí)戰(zhàn)教學(xué)(新手必看)

    零基礎(chǔ)也能輕松上手的Python自動(dòng)化辦公實(shí)戰(zhàn)教學(xué)(新手必看)

    這篇文章為Python零基礎(chǔ)用戶提供了3個(gè)實(shí)用的自動(dòng)化辦公項(xiàng)目,幫助解決重復(fù)性工作問題,特別適合被重復(fù)性辦公工作困擾的職場人士和想提升效率的零基礎(chǔ)用戶,希望對大家有所幫助
    2026-06-06
  • Python鍵盤輸入轉(zhuǎn)換為列表的實(shí)例

    Python鍵盤輸入轉(zhuǎn)換為列表的實(shí)例

    今天小編就為大家分享一篇Python鍵盤輸入轉(zhuǎn)換為列表的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Python爬蟲使用瀏覽器cookies:browsercookie過程解析

    Python爬蟲使用瀏覽器cookies:browsercookie過程解析

    這篇文章主要介紹了Python爬蟲使用瀏覽器cookies:browsercookie,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • pytorch中的dataset用法詳解

    pytorch中的dataset用法詳解

    這篇文章主要介紹了pytorch的dataset用法詳解,當(dāng)我們繼承了一個(gè)?Dataset類之后,我們需要重寫?len?方法,該方法提供了dataset的大小;?getitem?方法,?該方法支持從?0?到?len(self)的索引,下面來看看附有代碼的講解吧,希望對你的學(xué)習(xí)或者工作有所幫助
    2022-01-01
  • python數(shù)據(jù)挖掘需要學(xué)的內(nèi)容

    python數(shù)據(jù)挖掘需要學(xué)的內(nèi)容

    在本篇文章中我們給大家整理了關(guān)于python數(shù)據(jù)挖掘需要學(xué)什么的知識點(diǎn)指南,有興趣的朋友們跟著參考下。
    2019-06-06
  • Python實(shí)現(xiàn)遍歷目錄的方法【測試可用】

    Python實(shí)現(xiàn)遍歷目錄的方法【測試可用】

    這篇文章主要介紹了Python實(shí)現(xiàn)遍歷目錄的方法,涉及Python針對目錄與文件的遍歷、判斷、讀取相關(guān)操作技巧,需要的朋友可以參考下
    2017-03-03
  • Python中Numpy包的安裝與使用方法簡明教程

    Python中Numpy包的安裝與使用方法簡明教程

    這篇文章主要介紹了Python中Numpy包的安裝與使用方法,結(jié)合簡單實(shí)例形式分析了Python使用pip命令在線與離線whl包安裝,以及使用numpy打印隨機(jī)數(shù)矩陣的操作技巧,需要的朋友可以參考下
    2018-07-07
  • Python如何import文件夾下的文件(實(shí)現(xiàn)方法)

    Python如何import文件夾下的文件(實(shí)現(xiàn)方法)

    下面小編就為大家?guī)硪黄狿ython如何import文件夾下的文件(實(shí)現(xiàn)方法)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01
  • Python實(shí)現(xiàn)數(shù)值積分方式

    Python實(shí)現(xiàn)數(shù)值積分方式

    今天小編就為大家分享一篇Python實(shí)現(xiàn)數(shù)值積分方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11

最新評論

永胜县| 广德县| 雅安市| 宣威市| 岑巩县| 文水县| 驻马店市| 太湖县| 刚察县| 浙江省| 海城市| 南阳市| 湘阴县| 吉水县| 色达县| 巴楚县| 扎囊县| 易门县| 巫山县| 株洲市| 金阳县| 济宁市| 唐河县| 虹口区| 运城市| 白水县| 吴堡县| 新郑市| 长治县| 旬阳县| 盱眙县| 曲麻莱县| 康定县| 汤阴县| 称多县| 微山县| 商洛市| 公主岭市| 犍为县| 奇台县| 通州市|