讲师中心 微信公众号

工具推荐

视频效率加速
AniShort
AniShort

AI短剧协同制作平台

立刻MV
立刻MV

低成本歌曲 MV、视频生成

剧云
剧云

中文短剧剧本制作平台

Laper
Laper

剧本策划到成片协作

使用 aiortc 实现桌面实时屏幕流媒体传输(基于 MSS 屏幕捕获)

夏敏同学_7727

夏敏同学_7727

发布时间:2026-02-12 12:23:17

|

1109人浏览过

|

来源于php中文网

原创

使用 aiortc 实现桌面实时屏幕流媒体传输(基于 MSS 屏幕捕获)

本文详解如何用 aiortc 替代静态视频文件,结合 mss 库实现低延迟、高帧率的本地桌面实时 webrtc 流媒体推流,涵盖自定义 videostreamtrack、线程安全帧队列、时间戳同步等关键实践。

在基于 aiortc 的 WebRTC 服务中,MediaPlayer 仅适用于预录制的音视频文件(如 video.mp4),无法满足实时屏幕共享需求。要将用户当前桌面画面作为实时视频源推送到浏览器客户端,必须实现一个符合 aiortc 接口规范的自定义 VideoStreamTrack,并集成高效、轻量的屏幕捕获方案。mss 是 Python 中性能优异的纯 Python 屏幕捕获库,支持跨平台、无依赖、高帧率(可达 30–60 FPS),是理想选择。

以下是一个完整、可运行的 ScreenCapturing 类实现,它继承 VideoStreamTrack,通过后台线程持续抓取屏幕,并利用线程安全队列(queue.Queue)向主线程异步提供帧:

from aiortc import VideoStreamTrack
from av import VideoFrame
import numpy as np
import threading
import asyncio
import queue
import mss

class ScreenCapturing(VideoStreamTrack):
    """
    自定义视频流轨道:实时捕获主显示器画面(monitor[1])
    支持 WebRTC 兼容的 BGR24 格式帧输出与 PTS 时间戳管理。
    """
    def __init__(self) -> None:
        super().__init__()
        self.queue = queue.Queue(maxsize=10)  # 限制缓冲深度,防内存溢出
        self._started = False

    async def recv(self) -> VideoFrame:
        """核心方法:被 aiortc 调用以获取下一帧"""
        # 阻塞等待新帧(超时可选,避免永久挂起)
        try:
            img = self.queue.get(timeout=5.0)
        except queue.Empty:
            # 若长时间无帧,生成黑帧兜底(可选健壮性增强)
            dummy = np.zeros((720, 1280, 3), dtype=np.uint8)
            frame = VideoFrame.from_ndarray(dummy, format="bgr24")
            pts, time_base = await self.next_timestamp()
            frame.pts = pts
            frame.time_base = time_base
            return frame

        # RGBA → RGB(丢弃 Alpha 通道),确保格式兼容
        if img.shape[2] == 4:
            img_rgb = img[:, :, :3]
        else:
            img_rgb = img

        # 创建 VideoFrame 并设置时间戳(必需!否则播放卡顿/不同步)
        frame = VideoFrame.from_ndarray(img_rgb, format="bgr24")
        pts, time_base = await self.next_timestamp()
        frame.pts = pts
        frame.time_base = time_base
        return frame

    def start(self) -> None:
        """启动独立捕获线程(daemon=True 确保主程序退出时自动终止)"""
        if self._started:
            return
        self._started = True
        thread = threading.Thread(target=self._capture_loop, daemon=True)
        thread.start()

    def _capture_loop(self) -> None:
        """后台捕获循环:使用 mss 抓取主屏,转为 ndarray 后入队"""
        with mss.mss() as sct:
            monitor = sct.monitors[1]  # [0] 是虚拟全屏,[1] 是主显示器
            while self._started:
                try:
                    # 高效抓屏(返回 PIL Image,转 ndarray 开销可控)
                    im = sct.grab(monitor)
                    im_np = np.array(im)
                    # 尝试非阻塞入队,满则丢弃旧帧(保证低延迟)
                    try:
                        self.queue.put_nowait(im_np)
                    except queue.Full:
                        # 丢弃最老帧,优先保障实时性
                        try:
                            self.queue.get_nowait()
                            self.queue.put_nowait(im_np)
                        except queue.Empty:
                            pass
                except Exception as e:
                    print(f"[ScreenCapturing] 捕获异常: {e}")
                    break

    def stop(self) -> None:
        """停止捕获(配合 on_shutdown 使用)"""
        self._started = False
        # 清空队列避免残留引用
        while not self.queue.empty():
            try:
                self.queue.get_nowait()
            except queue.Empty:
                break

接下来,在主服务逻辑中替换原有的 create_local_tracks 函数,并确保在 offer 处理流程中正确初始化和启动该轨道:

AI舌诊面诊问诊医疗系统+诊疗商城系统源码
AI舌诊面诊问诊医疗系统+诊疗商城系统源码

AI 舌诊面诊问诊医疗系统 + 诊疗商城系统源码是一套结合 AI 辅助诊断与商品转化的健康类程序,基于浩创云、ThinkPHP(PHP)开发,支持微信服务号与 H5 端,适合做中医舌诊面诊问答、健康建议推送以及配套诊疗商品的运营。

下载
# 替换原 create_local_tracks 函数
async def create_local_tracks():
    track = ScreenCapturing()
    track.start()  # ⚠️ 必须显式调用启动捕获线程
    return track

# 修改 offer 处理函数(关键变更点)
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])
    pc = RTCPeerConnection()
    pcs.add(pc)

    # ✅ 使用实时屏幕轨道替代 MediaPlayer
    video = await create_local_tracks()  # 注意:此处为协程,需 await
    pc.addTrack(video)

    await pc.setRemoteDescription(offer)
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type="application/json",
        text=json.dumps(
            {"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}
        ),
    )

重要注意事项与优化建议:

  • 显示器选择:sct.monitors[1] 对应主显示器;可通过 print(sct.monitors) 查看所有屏幕区域,按需调整索引或指定 {"top": ..., "left": ..., "width": ..., "height": ...}。
  • 性能调优:
    • 降低分辨率(如 monitor.update({"width": 1280, "height": 720}))可显著提升帧率;
    • mss 默认使用 numpy 后端,无需额外配置;
    • 避免在 recv() 中执行耗时操作(如图像缩放、编码),应在捕获线程中预处理。
  • 时间戳(PTS):await self.next_timestamp() 是强制要求——它确保帧按正确时间间隔渲染。忽略会导致浏览器解码器卡顿、音画不同步。
  • 资源清理:在 on_shutdown 中,除关闭 RTCPeerConnection 外,建议调用 track.stop()(若已扩展该接口),防止后台线程残留。
  • 安全性与权限:Windows/macOS/Linux 均需授予 Python 进程屏幕录制权限(如 macOS 的“屏幕录制”隐私设置),否则 mss.grab() 将返回黑屏或报错。

通过以上改造,你的 aiortc 服务即可从“播放录像”升级为“直播桌面”,真正实现 WebRTC 场景下的实时协作、远程支持与教学演示能力。整个方案不依赖 FFmpeg 或 GStreamer,轻量可靠,适合嵌入边缘设备或容器化部署。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

函子Zion

一款支持AI搭建、可视化编辑和多端发布的全栈无代码开发平台。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

超级麦吉

一款通过数字员工协作完成调研、数据分析与文档制作的AI办公平台。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

3420

2023.09.27

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

269

2026.02.03

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3248

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

5429

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3889

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

506

2026.01.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4798

2023.08.10

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

3459

2023.07.26

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

80

2026.11.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn