亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

一、引言

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

二、單線程推流

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

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)建、管理子進程
    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()

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

初始化視頻讀取對象

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

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

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

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

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

三、多線程推流

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

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):
        # 防止多線程時 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]

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

類的初始化

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

讀取幀的線程方法

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

推流的線程方法

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

啟動線程

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

四、代碼解釋和注意事項

單線程推流:

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

多線程推流:

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

五、總結(jié)

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

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

相關(guān)文章

  • python字典如何獲取最大和最小value對應(yīng)的key

    python字典如何獲取最大和最小value對應(yīng)的key

    這篇文章主要介紹了python字典如何獲取最大和最小value對應(yīng)的key問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • python 執(zhí)行文件時額外參數(shù)獲取的實例

    python 執(zhí)行文件時額外參數(shù)獲取的實例

    今天小編就為大家分享一篇python 執(zhí)行文件時額外參數(shù)獲取的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • Python實現(xiàn)csv文件(點表和線表)轉(zhuǎn)換為shapefile文件的方法

    Python實現(xiàn)csv文件(點表和線表)轉(zhuǎn)換為shapefile文件的方法

    這篇文章主要介紹了Python實現(xiàn)csv文件(點表和線表)轉(zhuǎn)換為shapefile文件的方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • 使用Python Flask實現(xiàn)簡易文件上傳功能

    使用Python Flask實現(xiàn)簡易文件上傳功能

    在平時工作中,文件上傳是一項常見的需求,例如將應(yīng)用異常時通過腳本生成的dump文件收集起來進行分析,但實現(xiàn)起來卻可能相當(dāng)復(fù)雜,在本文中,我們將探討如何使用Flask實現(xiàn)文件上傳功能,編寫Dockerfile將應(yīng)用程序通過docker部署,需要的朋友可以參考下
    2024-05-05
  • Pandas庫之DataFrame使用的學(xué)習(xí)筆記

    Pandas庫之DataFrame使用的學(xué)習(xí)筆記

    這篇文章主要介紹了Pandas庫之DataFrame使用的學(xué)習(xí)筆記,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Python利用keras接口實現(xiàn)深度神經(jīng)網(wǎng)絡(luò)回歸

    Python利用keras接口實現(xiàn)深度神經(jīng)網(wǎng)絡(luò)回歸

    這篇文章主要為大家詳細介紹了基于Python語言中TensorFlow的Keras接口,實現(xiàn)深度神經(jīng)網(wǎng)絡(luò)回歸的方法。文中的示例代碼講解詳細,感興趣的可以了解一下
    2023-02-02
  • 給Django Admin添加驗證碼和多次登錄嘗試限制的實現(xiàn)

    給Django Admin添加驗證碼和多次登錄嘗試限制的實現(xiàn)

    這篇文章主要介紹了給Django Admin添加驗證碼和多次登錄嘗試限制的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 通過Python實現(xiàn)電腦定時關(guān)機的兩種方法

    通過Python實現(xiàn)電腦定時關(guān)機的兩種方法

    這篇文章主要介紹了分別利用PyQT5和Tkinter實現(xiàn)電腦的定時關(guān)機小程序,文中的示例代碼講解詳細,對我們學(xué)習(xí)Python有一定的幫助,快跟隨小編一起學(xué)習(xí)一下吧
    2021-12-12
  • Numpy數(shù)組的廣播機制的實現(xiàn)

    Numpy數(shù)組的廣播機制的實現(xiàn)

    這篇文章主要介紹了Numpy數(shù)組的廣播機制的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Python實現(xiàn)快速提取Word表格并轉(zhuǎn)Markdown

    Python實現(xiàn)快速提取Word表格并轉(zhuǎn)Markdown

    這篇文章主要為大家詳細介紹了一套Python零基礎(chǔ)可操作的代碼方案,幫助測試工程師3分鐘內(nèi)完成表格提取與轉(zhuǎn)換,直接對接自動化測試或大模型,需要的小伙伴可以參考下
    2025-04-04

最新評論