实现p2p的webrtc-srs版本

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:直接调用设备传感器,获取音视频流,支持参数配置(如分辨率、帧率、摄像头方向)。

    javascript 复制代码
    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

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

    1. 检查房间 1001 是否存在,若不存在则创建。

    2. 记录 CWR 为房间 1001 的参与者,维护"房间 - 参与者列表":{"1001": ["CWR"]}

    3. 返回房间当前状态给 CWR:

      json 复制代码
      // 信令服务器返回给 CWR 的响应
      {
        "code": 0,
        "roomId": "1001",
        "participants": ["CWR"], // 目前只有自己
        "streams": [] // 暂时没有流发布
      }

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

  • CWR 操作

    1. 调用信令服务器的 publish 接口,告知"要发布流":

      json 复制代码
      {
        "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 自己)推送流发布事件

      json 复制代码
      {
        "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

    json 复制代码
    {
      "action": "join",
      "roomId": "1001",
      "userId": "CZ"
    }
  • 信令服务器逻辑

    1. 检查房间 1001 已存在,将 CZ 加入参与者列表:{"1001": ["CWR", "CZ"]}

    2. 返回房间当前状态给 CZ,包含已存在的参与者和流

      json 复制代码
      {
        "code": 0,
        "roomId": "1001",
        "participants": ["CWR", "CZ"],
        "streams": [
          {
            "userId": "CWR",
            "streamId": "CWR_stream",
            "streamUrl": "webrtc://srs.server/1001/CWR_stream"
          }
        ]
      }
    3. 向房间内其他参与者(CWR) 推送新成员加入事件

      json 复制代码
      {
        "action": "participant_joined",
        "roomId": "1001",
        "userId": "CZ"
      }

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

  • CZ 操作

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

    json 复制代码
    {
      "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 接口,告知"要发布流":

      json 复制代码
      {
        "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) 推送流发布事件

      json 复制代码
      {
        "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

yaml 复制代码
# 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)候选等。比如,在多人视频通话中,信令服务器会将一个用户的媒体流信息转发给其他用户,使得各方能够建立起正确的媒体连接。
bash 复制代码
cd ~/git/srs/trunk/3rdparty/signaling && make && ./objs/signaling

3.3 http-static

bash 复制代码
#运行命令
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/ HTTP srs 1985 http api 调用 SRS 的流发布 API
/console/ng_index.html HTTP srs 1985 控制台 访问 SRS 管理界面
/players/srs_player.html HTTP srs 8080 播放器 加载 SRS 播放器静态页面
/sig/v1/rtc WebSocket signal1989 信令服务器 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)。
相关推荐
qq192572302719 分钟前
网络协议传输层
网络·网络协议
却道天凉_好个秋1 小时前
WebRTC(二):工作机制
webrtc
玩转4G物联网4 小时前
零基础玩转物联网-串口转以太网模块如何快速实现与MQTT服务器通信
服务器·物联网·网络协议·tcp/ip·信息与通信·iot·fs100p
前端.火鸡8 小时前
记录一篇HTTPS的文章
网络协议·http·https
接着奏乐接着舞。9 小时前
WebSocket心跳机制
websocket·网络协议·php
邪恶的贝利亚10 小时前
WebRTC 中 ICE 流程优化:SRS 轻量级部署与 NAT 类型检测实战
c++·webrtc·流媒体·ice
CheungChunChiu10 小时前
如何使用 IP 地址修改 Android 的 Captive Portal 校验 URL
android·网络协议·tcp/ip
循环渐进Forward14 小时前
【TinyWebServer】HTTP连接处理
linux·网络·c++·网络协议·算法·http
chian-ocean14 小时前
深入了解UDP套接字:构建高效网络通信
网络·网络协议·udp
hgdlip15 小时前
wifi改ip地址有什么用?wifi改ip地址怎么改
服务器·网络协议·tcp/ip