Mediamtx+Python读取webrtc流

news2025/5/14 14:14:11

一、功能思路:

1、我采用ffmpeg -re -stream_loop -1 -i xcc.mp4 -c:v libx264 -profile:v baseline -x264opts "bframes=0:repeat_headers=1" -b:v 1500k -preset fast -f flv rtmp://127.0.0.1:1835/stream/111推流到mediamtx的rtmp上
2、通过mediamtx自带的转流,我将可以直接把推过来的流以webrtc方式访问http://127.0.0.1:8889/stream/111
3、由于我确认http://127.0.0.1:8889/stream/111能够播放出视频,所以我现在想采用python的方式读取http://127.0.0.1:8889/stream/111/whep的流,来实现保存流的每帧图像

涉及到的工具有:

  • 开源视频流服务器—>mediamtx
  • 本地推流rtmp工具—>ffmpeg+lal
  • 编写代码读取webrtc流工具—>PyCharm
    在这里插入图片描述

二、代码编写实现:

import asyncio
import json
from aiortc import RTCPeerConnection, RTCSessionDescription, VideoStreamTrack
import aiohttp
import cv2
import numpy as np

class DummyVideoTrack(VideoStreamTrack):
    """创建一个虚拟的视频轨道,以防止 WebRTC 报错"""
    def __init__(self):
        super().__init__()

    async def recv(self):
        # 生成一个黑色帧,防止 WebRTC 报错
        width, height = 640, 480
        frame = np.zeros((height, width, 3), dtype=np.uint8)
        return frame

class VideoReceiver:
    def __init__(self):
        self.frame = None

    async def consume_track(self, track):
        while True:
            try:
                frame = await track.recv()
                img = frame.to_ndarray(format="bgr24")
                cv2.imshow("Video", img)
                cv2.waitKey(1)
            except Exception as e:
                print("处理帧错误:", e)
                break

async def send_ice_candidate(candidate, ice_url):
    async with aiohttp.ClientSession() as session:
        async with session.post(
            ice_url,
            data=json.dumps({"candidate": candidate}),
            headers={"Content-Type": "application/json"}
        ) as response:
            if response.status != 200:
                print(f"发送 ICE candidate 错误: {response.status}")

async def run():
    pc = RTCPeerConnection()
    receiver = VideoReceiver()

    # 添加一个虚拟的视频轨道,防止 WebRTC 报错
    pc.addTrack(DummyVideoTrack())


    # 处理接收到的媒体轨道
    def on_track(track):
        print(f"接收到 {track.kind} 轨道")
        if track.kind == "video":
            asyncio.create_task(receiver.consume_track(track))

    pc.add_listener("track", on_track)

    # 监听 ICE 连接状态变化
    def on_ice_connection_state_change():
        print(f"ICE 连接状态: {pc.iceConnectionState}")

    pc.on("iceconnectionstatechange", on_ice_connection_state_change)

    # 监听 ICE Candidate
    def on_ice_candidate(candidate):
        if candidate:
            print(f"新 ICE candidate: {candidate}")
            asyncio.create_task(send_ice_candidate(candidate, ice_url))

    pc.on("icecandidate", on_ice_candidate)

    # 创建 SDP Offer
    offer = await pc.createOffer()
    await pc.setLocalDescription(offer)

    # 发送 Offer 到 WHEP 端点
    whep_url = "http://127.0.0.1:8889/stream/111/whep"
    headers = {"Content-Type": "application/sdp"}

    async with aiohttp.ClientSession() as session:
        async with session.post(
                whep_url,
                data=pc.localDescription.sdp,
                headers=headers
        ) as response:
            if response.status != 201:
                raise Exception(f"服务器返回错误: {response.status}")

            answer_sdp = await response.text()
            answer = RTCSessionDescription(sdp=answer_sdp, type="answer")
            await pc.setRemoteDescription(answer)

            if "Location" in response.headers:
                ice_url = "http://127.0.0.1:8889" + response.headers["Location"]
                print("ICE 协商 URL:", ice_url)

        try:
            while True:
                await asyncio.sleep(1)
        except KeyboardInterrupt:
            pass
        finally:
            await pc.close()

if __name__ == "__main__":
    asyncio.run(run())

三、效果展示:

  • 浏览器可以直接播放webrtc的扩展地址,然后最上层就是代码cv2读取每帧显示出来的画面
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2298231.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每日一题——矩阵最长递增路径

矩阵最长递增路径问题 题目描述数据范围:进阶要求:示例示例 1示例 2 题解思路算法步骤:代码实现代码解释复杂度分析总结 题目描述 给定一个 n 行 m 列的矩阵 matrix,矩阵内所有数均为非负整数。你需要在矩阵中找到一条最长路径&a…

【CLIP系列】4:目标检测(ViLD、GLIP)

目录 1 ViLD2 GLIP2.1 前言2.2 损失计算2.3 模型框架 1 ViLD OPEN-VOCABULARY OBJECT DETECTION VIA VISION AND LANGUAGE KNOWLEDGE DISTILLATION 从标题就能看出来,作者是把CLIP模型当成一个Teacher,去蒸馏他自己的网络,从而能Zero Shot去…

Cesium for Unity Linux版本

Cesium for Unity 直装不支持Linux 参照官方开发流程一些操作命令issues 宝藏最后运行图 参照官方开发流程 https://github.com/CesiumGS/cesium-unity/blob/main/Documentation~/developer-setup.md 系统已经安装过dotnet和cmake xuefeixuefei:~$ dotnet --version 9.0.102 …

关于 IoT DC3 中驱动(Driver)的理解

在开源IoT DC3物联网系统中,驱动(Driver)扮演着至关重要的角色,它充当了软件系统与物理设备之间的桥梁。驱动的主要功能是依据特定的通信协议连接到设备,并根据设备模板中配置的位号信息进行数据采集和指令控制。不同的…

EasyRTC嵌入式WebRTC视频通话SDK支持Web浏览器、Linux、ARM、Android、iOS

随着互联网技术的飞速发展,实时通信(RTC)已经成为现代应用中不可或缺的一部分。无论是视频会议、在线教育、远程医疗,还是社交娱乐,实时通信技术都在其中扮演着重要角色。 然而,WebRTC技术在PC和移动端的支…

数据库脚本MySQL8转MySQL5

由于生产服务器版本上部署的是MySQL5,而开发手里的脚本代码是MySQL8。所以只能降版本了… 升级版本与降级版本脚本转换逻辑一样 MySQL5与MySQL8版本SQL脚本区别 大多数无需调整、主要是字符集与排序规则 MySQL5与MySQL8版本SQL字符集与排序规则 主要操作&…

【PGCCC】commit_delay 对性能的提升:PostgreSQL 基准测试

通过禁用参数可以来调整事务工作负载synchronous_commit。该措施有惊人效果。但在操作系统崩溃期间丢失已提交事务的可能性使其成为许多应用程序无法启动的因素。因此我决定写下来。 WAL 刷新是事务数据库工作负载的瓶颈 为了确保已提交的事务不会丢失,PostgreSQL…

AI大模型随机初始化权重并打印网络结构方法(以Deepseekv3为例,单机可跑)

背景 当前大模型的权重加载和调用,主要是通过在HuggingFace官网下载并使用transformer的库来加以实现;其中大模型的权重文件较大(部分>100GB),若只是快速研究网络结构和数据流变化,则无需下载权重。本文…

Ollama+WebUI+DeepSeek部署自己的本地大模型

前言 使用AI几乎成为互联网工作者必备技能了,DeepSeek的出现把AI再次推向高潮,在本文中,我们将带领大家借助 Ollama、WebUI 和 deepseek 这三个工具,成功搭建属于自己的本地大模型环境。Ollama 作为一款轻量级的大模型运行工具&a…

(篇六)基于PyDracula搭建一个深度学习的软件之新版本ultralytics-8.3.28调试

ultralytics-8.3.28版本debug记录 1传入文件 代码太多不粘贴在这里了,完整代码写在了篇三 def open_src_file(self):config_file config/fold.jsonconfig json.load(open(config_file, r, encodingutf-8))open_fold config[open_fold]if not os.path.exists(op…

NLP Word Embeddings

Word representation One-hot形式 在上一周介绍RNN类模型时,使用了One-hot向量来表示单词的方式。它的缺点是将每个单词视为独立的,算法很难学习到单词之间的关系。 比如下面的例子,即使语言模型已经知道orange juice是常用组合词&#xf…

使用HX搭建UNI-APP云开发项目(适合新手小白与想学云开发的宝子)

什么是uni-app云开发 uni-app云开发是uni-app提供的一套后端服务,它可以帮助开发者快速搭建起一个完整的后端服务,包括数据库、云函数、存储等。开发者只需要关注前端页面的开发,后端服务由uni-app云开发提供。 uni-app云开发的优势: 快速搭建后端服务:uni-app云开发提供了…

sql:时间盲注和boolen盲注

关于时间盲注&#xff0c;boolen盲注的后面几个获取表、列、具体数据的函数补全 时间盲注方法 import time import requests# 获取数据库名 def inject_database(url):dataname for i in range(1, 20):low 32high 128mid (low high) // 2while low < high:payload &q…

【STM32】ADC|多通道ADC采集

本次实现的是ADC实现数字信号与模拟信号的转化&#xff0c;数字信号时不连续的&#xff0c;模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法&#xff0c;使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时&#xff0c;0~ 3.3v(模拟信…

arcgis for js实现层叠立体效果

在 Web 开发中&#xff0c;利用 ArcGIS for JS 实现一些炫酷的地图效果能够极大地提升用户体验。本文将详细介绍如何使用 ArcGIS for JS 实现层叠立体效果&#xff0c;并展示最终的效果图。 效果图 实现思路 要实现层叠立体效果&#xff0c;关键在于获取边界图形的坐标&#xf…

多模态本地部署和ollama部署Llama-Vision实现视觉问答

文章目录 一、模型介绍二、预期用途1. 视觉问答(VQA)与视觉推理2. 文档视觉问答(DocVQA)3. 图像字幕4. 图像-文本检索5. 视觉接地 三、本地部署1. 下载模型2. 模型大小3. 运行代码 四、ollama部署1. 安装ollama2. 安装 Llama 3.2 Vision 模型3. 运行 Llama 3.2-Vision 五、效果…

【DeepSeek】deepseek可视化部署

目录 1 -> 前文 2 -> 部署可视化界面 1 -> 前文 【DeepSeek】DeepSeek概述 | 本地部署deepseek 通过前文可以将deepseek部署到本地使用&#xff0c;可是每次都需要winR输入cmd调出命令行进入到命令模式&#xff0c;输入命令ollama run deepseek-r1:latest。体验很…

【Git版本控制器】:第一弹——Git初识,Git安装,创建本地仓库,初始化本地仓库,配置config用户名,邮箱信息

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ 相关笔记&#xff1a; https://blog.csdn.net/dj…

Fabric.js、leaferjs、pixi.js 库的对比分析

文章目录 一、引言二、参与对比的 canvas 库简介三、性能对比四、易用性对比五、功能特性对比六、综合评价与使用建议七、总结 在前端开发中&#xff0c;canvas 库为实现丰富的图形效果和交互功能提供了强大的支持。本文将对 Fabric.js、leaferjs 和 pixi.js 这三个常见的 canv…

JVM——堆的回收:引用计数发和可达性分析法、五种对象引用

目录 引用计数法和可达性分析法 引用计数法&#xff1a; 可达性分析算法&#xff1a; 五种对象引用 软引用&#xff1a; 弱引用&#xff1a; 引用计数法和可达性分析法 引用计数法&#xff1a; 引用计数法会为每个对象维护一个引用计数器&#xff0c;当对象被引用时加1&…