当前位置: 首页 > article >正文

实现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:直接调用设备传感器,获取音视频流,支持参数配置(如分辨率、帧率、摄像头方向)。
    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-candidatecandidate $CANDIDATE;
}vhost __defaultVhost__ {rtc {enabled     on;# @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtmp-to-rtcrtmp_to_rtc off;# @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtc-to-rtmprtc_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 portcandidate $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)。

相关文章:

实现p2p的webrtc-srs版本

1. 基本知识 1.1 webrtc 一、WebRTC的本质:实时通信的“网络协议栈”类比 将WebRTC类比为Linux网络协议栈极具洞察力,二者在架构设计和功能定位上高度相似: 分层协议栈架构 Linux网络协议栈:从底层物理层到应用层(如…...

Android多媒体——音/视频数据播放(十八)

在媒体数据完成解码并准备好之后,播放流程便进入了最终的呈现阶段。为了确保音视频内容能够顺利输出,系统需要首先对相应的播放设备进行初始化。只有在设备初始化成功后,才能真正开始音视频的同步渲染与播放。这一过程不仅影响播放的启动速度,也直接关系到播放的稳定性和用…...

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

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

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

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

EC2安装WebRTC sdk-c环境、构建、编译

1、登录新的ec2实例,证书可以跟之前的实例用一个: ssh -v -i ~/Documents/cert/qa.pem ec2-user70.xxx.165.xxx 2、按照sdk-c demo中readme的描述开始安装环境: https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-c 2…...

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

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

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

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

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

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

python打卡day47

昨天代码中注意力热图的部分顺移至今天 知识点回顾: 热力图 作业:对比不同卷积层热图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import D…...

python学习day39

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

Ansible+Zabbix-agent2快速实现对多主机监控

ansible Ansible 是一款开源的自动化工具,用于配置管理(Configuration Management)、应用部署(Application Deployment)、任务自动化(Task Automation)和编排(Orchestration&#xf…...

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

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

Vuex:Vue.js 应用程序的状态管理模式

什么是Vuex? Vuex 是专门为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 在大型单页应用中,当多个组件共享状态时,简单的单向数据流…...

【中间件】Web服务、消息队列、缓存与微服务治理:Nginx、Kafka、Redis、Nacos 详解

Nginx 是什么:高性能的HTTP和反向代理Web服务器。怎么用:通过配置文件定义代理规则、负载均衡、静态资源服务等。为什么用:提升Web服务性能、高并发处理、负载均衡和反向代理。优缺点:轻量高效,但动态处理能力较弱&am…...

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

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

电脑定时关机工具推荐

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

Ubuntu 可执行程序自启动方法

使用 autostart(适用于桌面环境) 适用于 GNOME/KDE 桌面环境(如 Ubuntu 图形界面) 1. 创建 .desktop 文件 sudo vi ~/.config/autostart/my_laser.desktop[Desktop Entry] TypeApplication NameMy Laser Program Execbash -c &…...

Springboot多数据源配置实践

Springboot多数据源配置实践 基本配置文件数据库配置Mapper包Model包Service包中业务代码Mapper XML文件在某些复杂的业务场景中,我们可能需要使用多个数据库来存储和管理不同类型的数据,而不是仅仅依赖于单一数据库。本技术文档将详细介绍如何在 Spring Boot 项目中进行多数…...

第6章:Neo4j数据导入与导出

在实际应用中,数据的导入与导出是使用Neo4j的重要环节。无论是初始数据加载、系统迁移还是数据备份,都需要高效可靠的数据传输机制。本章将详细介绍Neo4j中的各种数据导入与导出方法,帮助读者掌握不同场景下的最佳实践。 6.1 数据导入策略 …...

uni-app学习笔记二十三--交互反馈showToast用法

showToast部分文档位于uniapp官网-->API-->界面:uni.showToast(OBJECT) | uni-app官网 uni.showToast(OBJECT) 用于显示消息提示框 OBJECT参数说明 参数类型必填说明平台差异说明titleString是提示的内容,长度与 icon 取值有关。iconString否图…...

Go爬虫开发学习记录

Go爬虫开发学习记录 基础篇:使用net/http库 Go的标准库net/http提供了完善的HTTP客户端功能,是构建爬虫的基石: package mainimport ("fmt""io""net/http" )func fetchPage(url string) string {// 创建自定…...

前端异步编程全场景解读

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

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

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

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

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

Q1起重机指挥理论备考要点分析

Q1起重机指挥理论备考要点分析 一、考试重点内容概述 Q1起重机指挥理论考试主要包含三大核心模块:安全技术知识(占40%)、指挥信号规范(占30%)和法规标准(占30%)。考试采用百分制,8…...

c++算法学习3——深度优先搜索

一、深度优先搜索的核心概念 DFS算法是一种通过递归或栈实现的"一条路走到底"的搜索策略,其核心思想是: 深度优先:从起点出发,选择一个方向探索到底,直到无路可走 回溯机制:遇到死路时返回最近…...

如何让非 TCP/IP 协议驱动屏蔽 IPv4/IPv6 和 ARP 报文?

——从硬件过滤到协议栈隔离的完整指南 引言 在现代网络开发中,许多场景需要定制化网络协议(如工业控制、高性能计算),此时需确保驱动仅处理特定协议,避免被标准协议(如 IPv4/IPv6/ARP)干扰。本文基于 Linux 内核驱动的实现,探讨如何通过硬件过滤、驱动层拦截和协议栈…...

组合模式:构建树形结构的艺术

引言:处理复杂对象结构的挑战 在软件开发中,我们常遇到需要处理部分-整体层次结构的场景: 文件系统中的文件与文件夹GUI中的容器与组件组织结构中的部门与员工菜单系统中的子菜单与菜单项组合模式正是为解决这类问题而生的设计模式。它允许我们将对象组合成树形结构来表示&…...

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

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

Spring Boot SQL数据库功能详解

Spring Boot自动配置与数据源管理 数据源自动配置机制 当在Spring Boot项目中添加数据库驱动依赖(如org.postgresql:postgresql)后,应用启动时自动配置系统会尝试创建DataSource实现。开发者只需提供基础连接信息: 数据库URL格…...