实现p2p的webrtc-srs版本

news2025/6/10 6:08:12

1. 基本知识

1.1 webrtc

一、WebRTC的本质:实时通信的“网络协议栈”类比
将WebRTC类比为Linux网络协议栈极具洞察力,二者在架构设计和功能定位上高度相似:

  1. 分层协议栈架构

    • Linux网络协议栈:从底层物理层到应用层(如TCP/IP、UDP),负责数据的封装、传输、路由及解析,是操作系统网络能力的核心。
    • WebRTC协议栈
      • 传输层:基于UDP实现自定义数据通道(DataChannel)音视频流传输,内置RTCPeerConnection处理连接建立、NAT穿越(STUN/TURN)和带宽管理。
      • 媒体处理层:集成音视频编解码模块(VP8/VP9/H.264、Opus)、前向纠错(FEC)降噪算法等,实现低延迟媒体流的实时处理。
      • 应用层接口:通过浏览器API(如getUserMediaRTCPeerConnection)暴露功能,类似Linux通过Socket接口供应用调用。
  2. 原生性与系统整合

    • Linux协议栈是操作系统内核的原生组件,WebRTC则是浏览器内核的原生模块(如Chrome的Blink引擎),直接调用操作系统的硬件接口(摄像头、麦克风、网络驱动),避免中间层性能损耗。

二、浏览器中的WebRTC:API接口的技术全景
WebRTC在浏览器中的实现,本质是将协议栈能力通过标准化API开放给开发者,其核心接口体系包括:

  1. 媒体采集与设备控制
  • getUserMedia:直接调用设备传感器,获取音视频流,支持参数配置(如分辨率、帧率、摄像头方向)。
    navigator.mediaDevices.getUserMedia({ video: { facingMode: "user" }, audio: true })  
    
  • MediaRecorder:基于WebRTC流实现客户端录制(如录制会议内容)。
  1. 点对点连接建立
  • RTCPeerConnection:核心接口,负责创建连接、交换SDP信令、管理ICE候选(网络地址),并通过addTrack/ontrack处理媒体流传输。
  • 信令解耦设计:浏览器仅处理媒体通道,信令通道需开发者自建(如WebSocket),这种分离模式与Linux协议栈“内核处理传输,用户态处理应用逻辑”的设计一致。

1.2 sfu模式

SFU模式(Selective Forwarding Unit)深度解析:架构、原理与应用场景

一、SFU模式的核心定义与定位
SFU(选择性转发单元)是流媒体服务器的一种转发模式,其核心功能是接收多个客户端的媒体流,根据订阅关系选择性地将流转发给其他客户端,而非对媒体流进行解码、混流或重新编码。

  • 类比说明
    • 若将媒体流视为“快递包裹”,SFU相当于快递分拣中心
      • 包裹(原始流)到达分拣中心后,仅根据收件地址(订阅关系)重新分拣投递,不拆包(不解码)、不合并包裹(不混流)。
      • 优势在于低延迟、低计算消耗,适合实时性要求高的场景(如互动直播、视频会议)。

二、SFU的技术架构与工作流程
1. 核心组件与网络模型
在这里插入图片描述

(典型SFU架构示意图:客户端A/B/C发布流至SFU,SFU根据订阅关系将流转发给订阅者)

  • 关键角色

    • 发布者(Publisher):客户端向SFU发送媒体流(如摄像头采集的视频流)。
    • 订阅者(Subscriber):客户端向SFU请求订阅特定流,接收转发的流数据。
    • SFU服务器
      • 维护流路由表(记录每个流的发布者与订阅者列表)。
      • 通过传输层协议(如UDP、WebRTC DataChannel)接收和转发流数据,不涉及媒体层处理。
  • 数据流向

    1. 发布者通过RTMP/WebRTC等协议将流推至SFU。
    2. SFU解析流元数据(如流ID),存储到路由表。
    3. 订阅者向SFU请求订阅某个流ID。
    4. SFU根据路由表,将该流的数据包复制并转发给所有订阅者。

2. 与MCU模式的本质区别

维度SFU模式MCU模式(Multipoint Control Unit)
媒体处理不解码、不混流,仅转发原始数据包解码所有流,混合成单一流(如将多路视频合成画中画)
延迟极低(仅网络传输延迟+转发处理时间)高(需解码、混流、重新编码,引入处理延迟)
带宽消耗发布者推1路流,订阅者接收N路流(总带宽≈发布带宽×N)发布者推N路流,服务器混流后推1路流(总带宽≈发布带宽×N + 混流带宽)
计算资源几乎无媒体处理消耗,适合高并发需大量CPU/GPU资源,并发量受限
典型场景实时互动直播、多人视频会议(如Zoom)低并发、需要画面合成的场景(如传统视频会议)

三、SFU模式的技术优势与适用场景
1. 核心优势

  • 低延迟特性

    • 无解码-编码环节,延迟通常控制在100ms-500ms级别,满足实时互动需求(如连麦、弹幕互动)。
    • 对比:传统CDN直播延迟约2-3秒,MCU模式延迟约500ms-1秒。
  • 高扩展性与低资源消耗

    • 服务器仅负责转发,单台SFU可支持数万路流并发转发(取决于网络带宽)。
    • 节省计算资源,适合构建大规模实时通信系统(如在线教育平台、电商直播)。
  • 灵活性与兼容性

    • 支持多协议接入(WebRTC、RTMP、SRT等),通过转协议网关实现跨终端互通(如浏览器WebRTC流转发给RTMP推流的手机端)。
    • 支持动态路由:可根据订阅者网络质量动态选择转发策略(如丢弃高延迟订阅者的流,或启用FEC增强可靠性)。

2. 典型应用场景

  • 实时互动直播

    • 场景:主播与观众连麦、多人PK直播。
    • 实现:主播推流至SFU,观众订阅主播流;连麦者推流至SFU,SFU将连麦者流转发给主播和其他观众。
    • 案例:Twitch的低延迟直播、B站“直播连麦”功能。
  • 视频会议系统

    • 场景:百人以上的远程会议,需支持动态加入/退出。
    • 实现:每个参会者发布自己的流至SFU,根据会议布局(如“发言人模式”),SFU将主讲人流转发给所有参会者。
    • 案例:Zoom的“分组讨论”功能基于SFU实现动态流转发。
  • 物联网与实时监控

    • 场景:多个摄像头实时回传画面至监控中心,支持多用户实时查看。
    • 实现:摄像头通过RTSP推流至SFU,监控客户端订阅指定摄像头流,SFU按需转发。

2 srs流媒体服务器

2.1 SFU转发单位

  1. 流接收与注册
    • 协议适配:支持 WebRTC 协议,接收客户端(发布者)通过 WebRTC 推来的音视频流 ,也可处理 RTMP 等其他协议转 WebRTC 后的流,通过如/rtc/v1/publish/接口逻辑,解析流的元数据(如流 ID、编码格式、分辨率等) 。
    • 流注册:将接收的流信息(流 ID、发布者标识等)记录到内部“流路由表”,建立“流 - 发布者”映射关系,为后续转发做准备 。
  2. 订阅与转发决策
    • 订阅请求处理:当其他客户端(订阅者)通过/rtc/v1/play或 WebRTC 协议发起订阅请求时,SRS 依据请求中的流 ID,查询“流路由表”,确定对应的发布者流 。
    • 转发策略
      • 选择性转发:作为 SFU,不解码、不混流原始媒体流(或仅做轻量级处理,如适配编码格式),直接复制流数据,根据订阅关系转发给订阅者 。比如多人会议场景,把发言人的单路流,转发给所有参会订阅者,实现“一对多”高效分发 。
      • 智能适配:结合客户端网络状况(如带宽、延迟)、终端能力(支持编码格式),动态调整转发的流参数。若订阅者网络差,可转发低分辨率、低码率流;若终端不支持 VP8 编码,转换为 H.264 再转发 。
  3. 媒体传输与优化
    • 传输协议:基于 UDP 传输媒体数据包(WebRTC 常用方式),利用其低延迟特性;也适配 TCP,应对复杂网络环境 。
    • 网络优化
      • NAT 穿透:配合 STUN/TURN 服务器,或通过配置candidate(候选地址),解决客户端处于 NAT 环境下的互联互通问题,让流顺利收发 。
      • 拥塞控制:支持 NACK(丢包重传)、TWCC(传输带宽估计与拥塞控制反馈),检测到丢包时重传关键数据,根据网络带宽动态调整发送码率,保障流传输稳定 。
      • FEC(前向纠错):添加冗余数据,订阅者收到数据后,可通过冗余数据恢复丢失的数据包,降低重传依赖,减少延迟 。
  4. 管理与协同
    • 控制台管理:提供 srs 1985 控制台(对应 URL 可查看),可视化展示 SRS 服务状态、流信息、客户端连接情况,方便运维人员监控流转发状态、排查问题 。
    • 信令协同:与信令服务器(如signal1989 )配合,通过/sig/v1/rtc等接口,处理房间创建、加入、流订阅/取消等信令逻辑,协同完成“发布 - 订阅”全流程 。比如信令通知 SRS 有新订阅者加入,SRS 即刻启动对应流的转发 。
  5. 协议转换与兼容(可选拓展):除纯 WebRTC 流转发,还支持协议转换。如把 WebRTC 流转为 RTMP/FLV ,供不支持 WebRTC 的终端(如老旧播放器通过 srs_player.html 播放)使用;也能将 RTMP 流转为 WebRTC 流输出,打通不同协议终端的实时通信 。

2.2 信令服务器

信令的本质:
信令服务器核心职责是 处理设备 / 客户端之间的 “协商逻辑”,比如 WebRTC 里的 SDP 交换(协商编解码、媒体能力)、房间管理(加入 / 退出、流订阅关系)、ICE 候选交换(网络地址协商)等,让终端知道 “和谁连、怎么连、发什么流” 。
SRS 对信令的支持方式:

  • SRS 可通过 集成简易信令逻辑 或 对接独立信令服务器,辅助流媒体业务:
    内置轻量信令功能:
    支持 WHIP(WebRTC HTTP 推流协议 )、WHEP(WebRTC HTTP 拉流协议 )等,可在协议层面处理部分 “推流 - 拉流” 的信令交互(如 SDP 协商、流标识绑定 )。
    例如,客户端通过 WHIP 协议向 SRS 推流时,SRS 会解析请求里的 SDP 信息,完成媒体能力协商,这一步涉及 “信令式” 的交互,但仅围绕流媒体传输本身,并非完整的 “房间管理、多终端协同” 信令逻辑。
  • 对接独立信令服务器:
    实际复杂场景(如多人会议)中,SRS 通常搭配 独立信令服务器(如开源的 Janus 信令模块、或业务自定义的信令服务 )。
    信令服务器负责处理 “房间创建、用户加入 / 退出、流订阅关系同步” 等高层逻辑,再将 “谁需要推流、谁需要拉流” 的指令告知 SRS,由 SRS 执行实际的媒体转发。

2.3 综合示例

背景设定

  • 信令服务器:负责房间管理、状态同步,提供 join/publish/subscribe 等信令接口。
  • SRS(SFU):负责媒体流转发,提供 publish(推流)和 play(拉流)的媒体接口。
  • 用户角色
    • CWR:先加入房间的用户,发布自己的流。
    • CZ:后加入房间的用户,订阅 CWR 的流,同时发布自己的流让 CWR 订阅。

流程拆解(Step by Step)

1. CWR 加入房间(join 信令)

  • CWR 操作
    调用信令服务器的 join 接口,参数:roomId=1001userId=CWR

    // CWR 发送给信令服务器的 join 请求
    {
      "action": "join",
      "roomId": "1001",
      "userId": "CWR"
    }
    
  • 信令服务器逻辑

    1. 检查房间 1001 是否存在,若不存在则创建。
    2. 记录 CWR 为房间 1001 的参与者,维护“房间 - 参与者列表”:{"1001": ["CWR"]}
    3. 返回房间当前状态给 CWR:
      // 信令服务器返回给 CWR 的响应
      {
        "code": 0,
        "roomId": "1001",
        "participants": ["CWR"], // 目前只有自己
        "streams": [] // 暂时没有流发布
      }
      

2. CWR 发布流(publish 信令 + SRS 推流)

  • CWR 操作

    1. 调用信令服务器的 publish 接口,告知“要发布流”:
      {
        "action": "publish",
        "roomId": "1001",
        "userId": "CWR",
        "streamId": "CWR_stream" // 自定义流标识
      }
      
    2. 通过 WebRTC 协议,将本地摄像头/麦克风采集的流,推送到 SRS 的 publish 地址(如 webrtc://srs.server/1001/CWR_stream )。
  • 信令服务器逻辑

    1. 记录“CWR 发布了流 CWR_stream”,更新房间流列表:{"1001": {"streams": ["CWR_stream"]}}
    2. 向房间内所有参与者(目前只有 CWR 自己)推送流发布事件
      {
        "action": "stream_published",
        "roomId": "1001",
        "userId": "CWR",
        "streamId": "CWR_stream",
        "streamUrl": "webrtc://srs.server/1001/CWR_stream" // SRS 流地址
      }
      
  • SRS(SFU)逻辑

    1. 接收 CWR 推来的 WebRTC 流,解析流元数据(编码、分辨率等)。
    2. 建立“流标识(CWR_stream)- 发布者(CWR)”的映射,等待订阅者。

3. CZ 加入房间(join 信令)

  • CZ 操作
    调用信令服务器的 join 接口,参数:roomId=1001userId=CZ

    {
      "action": "join",
      "roomId": "1001",
      "userId": "CZ"
    }
    
  • 信令服务器逻辑

    1. 检查房间 1001 已存在,将 CZ 加入参与者列表:{"1001": ["CWR", "CZ"]}
    2. 返回房间当前状态给 CZ,包含已存在的参与者和流
      {
        "code": 0,
        "roomId": "1001",
        "participants": ["CWR", "CZ"],
        "streams": [
          {
            "userId": "CWR",
            "streamId": "CWR_stream",
            "streamUrl": "webrtc://srs.server/1001/CWR_stream"
          }
        ]
      }
      
    3. 向房间内其他参与者(CWR) 推送新成员加入事件
      {
        "action": "participant_joined",
        "roomId": "1001",
        "userId": "CZ"
      }
      

4. CZ 订阅 CWR 的流(subscribe 信令 + SRS 拉流)

  • CZ 操作
    从信令服务器返回的 streams 中,拿到 CWR 的流地址 webrtc://srs.server/1001/CWR_stream,调用信令服务器的 subscribe 接口(或直接通过 WebRTC 发起 play 请求 ):

    {
      "action": "subscribe",
      "roomId": "1001",
      "userId": "CZ",
      "streamUrl": "webrtc://srs.server/1001/CWR_stream"
    }
    
  • 信令服务器逻辑
    记录“CZ 订阅了 CWR 的流”,并通知 SRS 处理转发。

  • SRS(SFU)逻辑

    1. 收到 CZ 的 play 请求(对应 webrtc://srs.server/1001/CWR_stream )。
    2. 找到 CWR 发布的流,直接转发给 CZ(不解码、不混流,仅做网络优化 )。

5. CZ 发布自己的流(publish 信令 + SRS 推流)

  • CZ 操作

    1. 调用信令服务器的 publish 接口,告知“要发布流”:
      {
        "action": "publish",
        "roomId": "1001",
        "userId": "CZ",
        "streamId": "CZ_stream"
      }
      
    2. 通过 WebRTC 协议,将本地流推送到 SRS 的 publish 地址(如 webrtc://srs.server/1001/CZ_stream )。
  • 信令服务器逻辑

    1. 记录“CZ 发布了流 CZ_stream”,更新房间流列表。
    2. 向房间内所有参与者(CWR、CZ) 推送流发布事件
      {
        "action": "stream_published",
        "roomId": "1001",
        "userId": "CZ",
        "streamId": "CZ_stream",
        "streamUrl": "webrtc://srs.server/1001/CZ_stream"
      }
      
  • SRS(SFU)逻辑
    接收 CZ 推来的流,建立“流标识(CZ_stream)- 发布者(CZ)”的映射,等待订阅者(如 CWR 会触发订阅 )。

6. CWR 订阅 CZ 的流(自动触发或信令驱动)

  • CWR 操作
    收到信令服务器推送的“CZ 发布流”事件后,自动调用 subscribe 接口(或直接 play ),订阅 webrtc://srs.server/1001/CZ_stream

  • SRS(SFU)逻辑
    将 CZ 的流转发给 CWR,此时 CWR 和 CZ 实现双向音视频互通(CWR 看/听 CZ,CZ 看/听 CWR )。

关键协同总结

角色核心动作数据/信令流向作用
CWR(发布者)joinpublish → 推流到 SRS信令服务器 ←→ CWR;SRS ← CWR(媒体流)初始化房间、发布本地流
CZ(订阅者)join → 订阅 CWR 流 → publish → 推流信令服务器 ←→ CZ;SRS ←→ CZ(媒体流)加入房间、订阅他人流、发布自己流
信令服务器管理房间、同步状态、转发事件信令服务器 ←→ CWR/CZ指挥“谁连谁、什么时候连”,不碰媒体数据
SRS(SFU)接收流、转发流(publish/play 接口)SRS ← 发布者(媒体流);SRS → 订阅者只负责“搬流媒体数据”,依赖信令调度

3 实战

3.1 srs 流媒体服务器分析

运行命令:./objs/srs -c ./conf/rtc.conf

# WebRTC streaming config for SRS.
# @see full.conf for detail config.

listen              1935;
max_connections     1000;
daemon              off;
srs_log_tank        console;

http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
}

http_api {
    enabled         on;
    listen          1985;
}
stats {
    network         0;
}
rtc_server {
    enabled on;
    listen 8000; # UDP port
    # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate
    candidate $CANDIDATE;
}

vhost __defaultVhost__ {
    rtc {
        enabled     on;
        # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtmp-to-rtc
        rtmp_to_rtc off;
        # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtc-to-rtmp
        rtc_to_rtmp off;
    }
    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
    }
}

整体功能概述
该配置文件实现了一个基础的WebRTC流媒体服务,主要包含以下核心功能:

  • RTMP协议支持(端口1935)
  • HTTP文件服务(端口8080)
  • HTTP API管理接口(端口1985)
  • WebRTC服务(UDP端口8000)
  • HTTP-FLV直播流输出

核心配置项解析

  1. 基础服务配置
listen              1935;
max_connections     1000;
daemon              off;
srs_log_tank        console;
  • listen 1935:启用RTMP协议监听,用于接收传统RTMP推流
  • max_connections 1000:限制最大客户端连接数为1000
  • daemon off:不以守护进程方式运行,便于调试
  • srs_log_tank console:日志输出到控制台
  1. HTTP服务配置
http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
}
  • 启用HTTP文件服务,端口8080
  • 静态文件目录指向./objs/nginx/html,可用于存放播放器页面等静态资源
  1. HTTP API配置
http_api {
    enabled         on;
    listen          1985;
}
  • 启用HTTP管理API,端口1985
  • 通过该API可以查询服务器状态、流信息等,支持RESTful风格

RESTful 不是 “强制标准”,而是一套让 API 更简洁、规范的设计风格,核心通过 “资源 URI + HTTP 方法” 定义接口,让系统交互清晰、易维护。像你之前提到的 SRS 的 HTTP API,若遵循 RESTful 设计,就能用GET /api/streams查列表、POST /api/streams创建流,比自定义复杂参数的接口好理解得多~

HTTPAPI:
HTTP API 虽然不直接参与媒体流的传输(由 SFU 模块负责),但它为 WebRTC 服务提供了 控制平面 的能力:
动态配置 WebRTC 参数:通过 HTTP API 修改 rtc_server 的配置(如端口、候选地址),无需重启服务。
监控 WebRTC 连接质量:实时查看 WebRTC 客户端的连接数、丢包率、带宽使用情况。
管理 WebRTC 房间 / 会话:结合业务逻辑,通过 HTTP API 创建 / 销毁 WebRTC 会话(如多人会议房间)

  1. WebRTC核心配置
rtc_server {
    enabled on;
    listen 8000; # UDP port
    candidate $CANDIDATE;
}
  • enabled on:启用WebRTC服务
  • listen 8000:使用UDP端口8000进行WebRTC数据传输(UDP更适合低延迟实时通信)
  • candidate $CANDIDATE:配置ICE候选地址,$CANDIDATE通常会在启动时被替换为服务器的公网IP或域名,用于NAT穿透
  1. 虚拟主机配置
vhost __defaultVhost__ {
    rtc {
        enabled     on;
        rtmp_to_rtc off;
        rtc_to_rtmp off;
    }
    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
    }
}
  • WebRTC相关配置

    • rtc.enabled on:在默认虚拟主机上启用WebRTC功能
    • rtmp_to_rtc off:关闭RTMP到WebRTC的转换(不将RTMP流转换为WebRTC流)
    • rtc_to_rtmp off:关闭WebRTC到RTMP的转换(不将WebRTC流转换为RTMP流)
  • HTTP-FLV配置

    • http_remux.enabled on:启用HTTP-FLV流输出
    • mount [vhost]/[app]/[stream].flv:定义HTTP-FLV流的访问路径格式,例如:http://server:8080/live/stream.flv

3.2 信令服务器分析

SRS 中第三方库的信令服务器是一个用 Go 语言开发的组件,位于 SRS 的3rdparty/signaling目录下,默认监听 1989 端口。它在 SRS 的 WebRTC 功能中扮演着重要角色,主要负责以下任务:

  • 房间管理:处理与房间相关的操作,包括创建房间、加入房间、离开房间等。例如,当用户想要加入一个特定的视频通话房间时,信令服务器会对该请求进行处理,确保用户能够正确地加入到指定房间。
  • 用户信息管理:负责管理参与 WebRTC 会话的用户信息,如用户的昵称、状态等。它可以跟踪房间内的用户列表,当有新用户加入或现有用户离开时,及时更新相关信息并通知其他用户。
  • 信令交互:作为客户端之间信令消息的中转站,处理 WebRTC 客户端之间的信令交互,包括协商媒体能力、交换会话描述协议(SDP)信息、处理 ICE(Interactive Connectivity Establishment)候选等。比如,在多人视频通话中,信令服务器会将一个用户的媒体流信息转发给其他用户,使得各方能够建立起正确的媒体连接。
cd ~/git/srs/trunk/3rdparty/signaling && make && ./objs/signaling

3.3 http-static

#运行命令
cd ~/git/srs/trunk/3rdparty/httpx-static && make &&
./objs/httpx-static -http 80 -https 443 -ssk server.key -ssc server.crt \
    -proxy http://127.0.0.1:1989/sig -proxy http://127.0.0.1:1985/rtc \
    -proxy http://127.0.0.1:8080/

httpx-static 是一个基于 C++ 开发的高性能 HTTP/HTTPS 反向代理服务器,主要用于将客户端的 HTTP/HTTPS 请求转发到后端的多个目标服务(如 API 接口、其他服务器等)

在这里插入图片描述

一、按请求类型拆分:HTTP vs WebSocket
httpx-static 同时支持 HTTP 请求WebSocket 请求 的转发,对应不同的业务场景:

1. HTTP 请求转发(常规接口、静态文件)

  • 请求示例

    • /rtc/v1/publish/ → 转发到 srs 1985 http api
    • /console/ng_index.html → 转发到 srs 1985 控制台
    • /players/srs_player.html → 转发到 srs 8080 播放器
  • 作用

    • 静态文件托管:像 srs_player.html 这类播放器页面,通过 httpx-static 直接代理到 SRS 的静态文件服务器(8080 端口),客户端访问 http://your-domain/players/srs_player.html 就能加载页面。
    • API 调用/rtc/v1/publish 是 SRS 的 HTTP API(1985 端口),用于触发流发布逻辑(如推流到 SRS)。
    • 控制台访问/console/ng_index.html 是 SRS 的 Web 管理界面,通过代理统一入口,方便运维人员访问。

2. WebSocket 请求转发(信令交互)

  • 请求示例

    • /sig/v1/rtc → 转发到 signal1989 信令服务器(WebSocket 协议)
  • 作用
    WebRTC 信令交互(如房间创建、SDP 交换、ICE 候选协商)依赖 WebSocket 长连接httpx-static 作为代理,将客户端的 WebSocket 请求(ws://your-domain/sig/v1/rtc)转发到信令服务器(1989 端口),确保实时信令能稳定传输。

二、路由逻辑:“流量分发规则”
httpx-static 通过 路径匹配 决定请求转发到哪个后端:

请求路径协议转发目标作用
/rtc/v1/publish/HTTPsrs 1985 http api调用 SRS 的流发布 API
/console/ng_index.htmlHTTPsrs 1985 控制台访问 SRS 管理界面
/players/srs_player.htmlHTTPsrs 8080 播放器加载 SRS 播放器静态页面
/sig/v1/rtcWebSocketsignal1989 信令服务器WebRTC 信令交互(房间、流协商)

三、业务价值:为什么需要这个“中枢”?
1. 统一入口,简化客户端配置

  • 客户端只需记住 httpx-static 的地址(如 http://your-domain),无需关心后端多个服务的具体端口(1985、8080、1989 等)。
  • 示例:
    • 播放器页面地址统一为 http://your-domain/players/srs_player.html,无需拼接 :8080 端口。
    • 信令连接地址统一为 ws://your-domain/sig/v1/rtc,无需关心信令服务器的 1989 端口。

2. 协议转换与兼容

  • httpx-static 可以将 外部 HTTPS 请求 转换为内部 HTTP 请求,反之亦然。
  • 示例:
    • 客户端用 https://your-domain 访问(更安全),httpx-static 内部转发到 SRS 的 HTTP 服务(1985、8080 等),无需后端服务单独配置 HTTPS。

3. 隐藏后端细节,提升安全性

  • 后端服务(如信令服务器 1989 端口)无需暴露到公网,只需在内部网络与 httpx-static 通信。
  • 减少公网暴露的端口数量,降低被攻击的风险(如 1989 端口不直接对外,仅通过 httpx-static 代理)。

4. 支持复杂业务流程

  • 比如 WebRTC 推流流程:
    1. 客户端通过 HTTP 请求 /rtc/v1/publish 告诉 SRS “我要推流”。
    2. 通过 WebSocket 连接 /sig/v1/rtc 与信令服务器协商推流参数。
    3. 最终音视频流通过 SRS 的 SFU 模块传输,但所有“控制面”请求都由 httpx-static 统一路由。

四、类比理解:把 httpx-static 当“小区门卫”

  • 客户端 = 小区居民,想访问小区内的不同设施(健身房、物业、快递柜)。
  • httpx-static = 小区门卫,负责登记居民需求,然后帮居民把请求转发到对应的设施:
    • 居民说“我要去健身房” → 门卫指引到健身房(转发到 srs 8080 播放器)。
    • 居民说“我要找物业开证明” → 门卫指引到物业办公室(转发到 srs 1985 控制台)。
    • 居民说“我要收发快递” → 门卫指引到快递柜(转发到 signal1989 信令服务器)。

这样,居民(客户端)无需记住每个设施的具体位置(端口),只需找门卫(httpx-static)即可~

3.4 交互流程

在这里插入图片描述
以下结合 httpx-static 代理SRS(SFU)信令服务器 与这张前端交互流程图,完整拆解 “用户 → 前端 → 后端服务” 的交互逻辑,理解从“进入网页”到“音视频互通”的全流程:

一、核心角色回顾

  1. 前端侧

    • one2one.html:前端页面(用户入口)。
    • srs.sig.js:信令交互工具库(处理 WebSocket 连接、收发信令)。
    • srs.sdk.js:WebRTC 工具库(处理音视频采集、发布、订阅)。
  2. 后端侧

    • httpx-static:反向代理(统一入口,转发 HTTP/WebSocket 请求)。
    • SRS(SFU):流媒体服务器(处理音视频流的发布、订阅、转发)。
    • 信令服务器:处理房间管理、SDP 协商、ICE 候选交换等信令逻辑。

二、流程拆解(从“用户进入网页”到“音视频互通”)

1. 初始化阶段:前端加载与配置

  • 用户操作:用户 1 访问 one2one.html 页面(进入网页)。
  • 前端逻辑
    1. one2one.html 加载后,调用 srs.sig.jsSrsRtcSignalingParse 方法,解析配置:
      • 返回 wsHost(WebSocket 信令地址,如 ws://your-domain/sig/v1/rtc,实际由 httpx-static 代理)。
      • 返回 room(房间 ID,如 1234)、display(用户标识,如 user1)等参数。

2. 信令连接阶段:建立 WebSocket 通道

  • 前端逻辑
    1. 调用 srs.sig.jsSrsRtcSignalingAsync 方法,基于 wsHost 创建 WebSocket 连接:
      • 返回 sig 对象(封装了 WebSocket 收发信令的能力)。
    2. 通过 sig.connect() 发起 WebSocket 连接,请求到达 httpx-static
  • httpx-static 转发
    • 识别路径 /sig/v1/rtc,将 WebSocket 请求转发到 信令服务器(如 signal1989)。
  • 信令服务器逻辑
    • 接受连接,为用户 1 分配信令通道,等待后续消息。

3. 加入房间阶段:信令交互(join

  • 前端逻辑
    1. 通过 sig.send({ action: 'join', room: '1234', display: 'user1' }) 发送 join 信令。
    2. 信令内容:告知信令服务器“用户 1 要加入房间 1234”。
  • 信令服务器逻辑
    1. 检查房间 1234 是否存在,若不存在则创建。
    2. 记录用户 1 为房间成员,返回房间信息(如现有成员、流列表)。
    3. 若有其他用户(如用户 2)已在房间,信令服务器会向用户 2 推送“新成员加入”事件。

4. 发布流阶段:采集并推送音视频(publish

  • 前端逻辑
    1. 调用 srs.sdk.jsnew SrsRtcPublisherAsync() 方法,初始化发布器:
      • 请求浏览器权限(摄像头、麦克风),采集音视频流。
      • 返回 Publisher 对象(封装了发布流的能力)。
    2. 通过 Publisher.publish() 发起流发布:
      • 生成 WebRTC 的 SDP(媒体能力描述),并通过 sig.send({ action: 'publish', sdp: '...' }) 发送给信令服务器。
  • 信令服务器逻辑
    1. 接收 publish 信令,解析 SDP 内容。
    2. 将 SDP 转发给 SRS(SFU)(通过 httpx-static 代理的 /rtc/v1/publish 接口)。
  • SRS(SFU)逻辑
    1. 接收 SDP,创建流发布通道,返回 SRS 的 SDP 响应(包含 ICE 候选等网络信息)。
    2. 信令服务器将 SRS 的响应回传给前端 Publisher

5. 订阅流阶段:接收对方音视频(用户 2 同理)

  • 用户 2 流程
    用户 2 重复 步骤 1-4,加入房间 1234 并发布自己的流。
  • 信令服务器通知
    当用户 2 发布流后,信令服务器向用户 1 推送“新流发布”事件(包含用户 2 的流地址,如 webrtc://your-domain/1234/user2)。
  • 前端订阅逻辑
    1. 用户 1 的 srs.sdk.js 收到事件后,调用 new SrsRtcSubscriberAsync() 初始化订阅器。
    2. 通过订阅器请求 SRS(SFU)拉取用户 2 的流,建立 WebRTC 连接。

6. 音视频互通阶段:媒体流传输

  • SRS(SFU)角色
    • 接收用户 1 的流(通过 WebRTC 推流),并转发给用户 2。
    • 接收用户 2 的流(通过 WebRTC 推流),并转发给用户 1。
  • 前端呈现
    • 用户 1 和用户 2 的浏览器通过 srs.sdk.js 渲染对方的音视频流,实现“一对一通话”。

三、关键交互链路总结

用户1 one2one.html srs.sig.js srs.sdk.js httpx-static 信令服务器 SRS(SFU) User2 进入网页 SrsRtcSignalingParse() wsHost/room/display SrsRtcSignalingAsync() sig对象 sig.connect() WebSocket连接 (/sig/v1/rtc) 转发WebSocket连接 sig.send(join) 发送join信令 返回房间信息 new SrsRtcPublisherAsync() Publisher对象 Publisher.publish() sig.send(publish) 发送publish信令 转发publish请求 (/rtc/v1/publish) 返回SDP/ICE信息 回传SDP/ICE 建立WebRTC推流 转发音视频流 用户2执行相同流程后,SRS转发双方流,实现互通 用户1 one2one.html srs.sig.js srs.sdk.js httpx-static 信令服务器 SRS(SFU) User2

四、核心协同点

  1. httpx-static 的“桥梁作用”

    • 统一代理 HTTP(如 /rtc/v1/publish)和 WebSocket(如 /sig/v1/rtc)请求,让前端只需访问一个域名,简化配置。
  2. 信令服务器的“指挥作用”

    • 管理房间、用户、流的状态,协调 SRS 转发媒体流,让“谁该推流、谁该拉流”逻辑清晰。
  3. SRS(SFU)的“管道作用”

    • 专注媒体流的转发,不处理业务逻辑,确保音视频传输低延迟、高性能。
  4. 前端 SDK 的“工具作用”

    • srs.sig.js 封装信令交互,srs.sdk.js 封装 WebRTC 能力,让前端开发者无需关注复杂的协议细节。

五、类比理解:把整个流程当“线上电话亭”

  • one2one.html = 电话亭的“操作面板”(用户输入要拨打的号码)。
  • srs.sig.js = 电话亭的“信号线路”(负责传递“拨号、接听”等信令)。
  • srs.sdk.js = 电话亭的“话筒+听筒”(负责采集、播放声音/画面)。
  • httpx-static = 电话局的“总机”(统一转接所有通话请求)。
  • 信令服务器 = 电话局的“交换机”(决定“谁能接通谁、怎么接通”)。
  • SRS(SFU) = 电话局的“传输线路”(负责把声音/画面从 A 传到 B)。

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

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

相关文章

第2篇:BLE 广播与扫描机制详解

本文是《BLE 协议从入门到专家》专栏第二篇,专注于解析 BLE 广播(Advertising)与扫描(Scanning)机制。我们将从协议层结构、广播包格式、设备发现流程、控制器行为、开发者 API、广播冲突与多设备调度等方面,全面拆解这一 BLE 最基础也是最关键的通信机制。 一、什么是 B…

开源 vGPU 方案:HAMi,实现细粒度 GPU 切分

本文主要分享一个开源的 GPU 虚拟化方案:HAMi,包括如何安装、配置以及使用。 相比于上一篇分享的 TimeSlicing 方案,HAMi 除了 GPU 共享之外还可以实现 GPU core、memory 得限制,保证共享同一 GPU 的各个 Pod 都能拿到足够的资源。…

盲盒一番赏小程序:引领盲盒新潮流

在盲盒市场日益火爆的今天,如何才能在众多盲盒产品中脱颖而出?盲盒一番赏小程序给出了答案,它以创新的玩法和优质的服务,引领着盲盒新潮流。 一番赏小程序的最大特色在于其独特的赏品分级制度。赏品分为多个等级,从普…

边缘计算设备全解析:边缘盒子在各大行业的落地应用场景

随着工业物联网、AI、5G的发展,数据量呈爆炸式增长。但你有没有想过,我们生成的数据,真的都要发回云端处理吗?其实不一定。特别是在一些对响应时间、网络带宽、数据隐私要求高的行业里,边缘计算开始“火”了起来&#…

Linux实现线程同步的方式有哪些?

什么是线程同步? 想象一下超市收银台:如果所有顾客(线程)同时挤向同一个收银台(共享资源),场面会一片混乱。线程同步就是给顾客们发"排队号码牌",确保: 有序访…

python学习day39

图像数据与显存 知识点回顾 1.图像数据的格式:灰度和彩色数据 2.模型的定义 3.显存占用的4种地方 a.模型参数梯度参数 b.优化器参数 c.数据批量所占显存 d.神经元输出中间状态 4.batchisize和训练的关系 import torch import torchvision import torch.nn as nn imp…

年度峰会上,抖音依靠人工智能和搜索功能吸引广告主

上周早些时候举行的第五届年度TikTok World产品峰会上,TikTok推出了一系列旨在增强该应用对广告主吸引力的功能。 新产品列表的首位是TikTok Market Scope,这是一个全新的分析平台,为广告主提供整个考虑漏斗的全面视图,使他们能够…

如何使用CodeRider插件在IDEA中生成代码

一、环境搭建与插件安装 1.1 环境准备 名称要求说明操作系统Windows 11JetBrains IDEIntelliJ IDEA 2025.1.1.1 (Community Edition)硬件配置推荐16GB内存50GB磁盘空间 1.2 插件安装流程 步骤1:市场安装 打开IDEA,进入File → Settings → Plugins搜…

电脑定时关机工具推荐

软件介绍 本文介绍一款轻量级的电脑自动关机工具,无需安装,使用简单,可满足定时关机需求。 工具简介 这款关机助手是一款无需安装的小型软件,文件体积仅60KB,下载后可直接运行,无需复杂配置。 使用…

前端异步编程全场景解读

前端异步编程是现代Web开发的核心,它解决了浏览器单线程执行带来的UI阻塞问题。以下从多个维度进行深度解析: 一、异步编程的核心概念 JavaScript的执行环境是单线程的,这意味着在同一时间只能执行一个任务。为了不阻塞主线程,J…

分布式光纤声振传感技术原理与瑞利散射机制解析

分布式光纤传感技术(Distributed Fiber Optic Sensing,简称DFOS)作为近年来迅速发展的新型感知手段,已广泛应用于边界安防、油气管道监测、结构健康诊断、地震探测等领域。其子类技术——分布式光纤声振传感(Distribut…

RocketMQ 客户端负载均衡机制详解及最佳实践

延伸阅读:🔍「RocketMQ 中文社区」 持续更新源码解析/最佳实践,提供 RocketMQ 专家 AI 答疑服务 前言 本文介绍 RocketMQ 负载均衡机制,主要涉及负载均衡发生的时机、客户端负载均衡对消费的影响(消息堆积/消费毛刺等…

【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理

这篇学习笔记是Spring系列笔记的第7篇,该笔记是笔者在学习黑马程序员SSM框架教程课程期间的笔记,供自己和他人参考。 Spring学习笔记目录 笔记1:【SSM】Spring基础: IoC配置学习笔记-CSDN博客 对应黑马课程P1~P20的内容。 笔记2…

C++课设:实现本地留言板系统(支持留言、搜索、标签、加密等)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、项目功能概览与亮点分析1. 核心功能…

【见合八方平面波导外腔激光器专题系列】用于干涉光纤传感的低噪声平面波导外腔激光器2

----翻译自Mazin Alalus等人的文章 摘要 1550 nm DWDM 平面波导外腔激光器具有低相位/频率噪声、窄线宽和低 RIN 等特点。该腔体包括一个半导体增益芯片和一个带布拉格光栅的平面光波电路波导,采用 14 引脚蝶形封装。这种平面波导外腔激光器设计用于在振动和恶劣的…

Xcode 16.2 版本 pod init 报错

Xcode 版本升级到 16.2 后,项目执行 pod init 报错; ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchron…

timestamp时间戳转换工具

作为一名程序员,一款高效的 在线转换工具 (在线时间戳转换 计算器 字节单位转换 json格式化)必不可少!https://jsons.top 排查问题时非常痛的点: 经常在秒级、毫秒级、字符串格式的时间单位来回转换,于是决定手撸一个…

数据库管理与高可用-MySQL故障排查与生产环境优化

目录 #1.1MySQL单案例故障排查 1.1.1MySQL常见的故障排查 1.1.2MySQL主从故障排查 #2.1MySQL优化 2.1.1硬件方面的优化 2.1.2进程方面的优化 #3.1MySQL存储引擎 3.1.1 MyISAM存储引擎 3.1.2 InnoDB存储引擎 1.1MySQL单案例故障排查 1.1.1MySQL常见的故障排查 (1&…

LangChain + LangSmith + DeepSeek 入门实战:构建代码生成助手

本文基于 Jupyter Notebook 实践代码,结合 LangChain、LangSmith 和 DeepSeek 大模型,手把手演示如何构建一个代码生成助手,并实现全流程追踪与优化。 一、环境准备与配置 1. 安装依赖 pip install langchain langchain_openai2. 设置环境变…

【Elasticsearch基础】Elasticsearch批量操作(Bulk API)深度解析与实践指南

目录 1 Bulk API概述 1.1 什么是批量操作 1.2 Bulk API的优势 2 Bulk API的工作原理 2.1 请求处理流程 2.2 底层机制 3 Bulk API的使用方法 3.1 基本请求格式 3.2 操作类型示例 3.3 响应格式 4 Bulk API的最佳实践 4.1 批量大小优化 4.2 错误处理策略 4.3 性能调…