Skip to content

Live777 Core (liveion) ​

一个为 WebRTC 而生的 SFU 服务器。

默认支持 WHIP / WHEP 协议。启用 rtsp feature 后,liveion 还可以作为 RTSP 服务器运行:通过 ANNOUNCE/RECORD 推流,通过 DESCRIBE/PLAY 拉流。

a core SFU server, If you need a single server, use this

目前支持的编码 ​

protocolvideo codecsaudio codecs
WHIPAV1, VP9, VP8, H265, H264Opus, G722
WHEPAV1, VP9, VP8, H265, H264Opus, G722
RTSPAV1, VP9, VP8, H265, H264Opus, G722

live777-apps

目前客户端的支持情况 ​

ApplicationAV1VP9VP8H265H264OPUSG722
Browser whip⭐⭐⭐⭐⭐⭐⭐
Browser whep⭐⭐⭐⭐⭐⭐⭐
Gstreamer whip⭐⭐⭐⭐⭐⭐⭐
Gstreamer whep📺 2⭐⭐⭐⭐⭐⭐
Gstreamer whipinto📺 1⭐⭐⭐⭐📺 1⭐
Gstreamer whepfrom📺 2⭐⭐⭐⭐⭐⭐
FFmpeg whipinto💩⭐⭐⭐⭐⭐⭐
FFmpeg whepfrom💩⭐⭐⭐⭐⭐⭐
VLC whipinto💩💩⭐⭐⭐⭐💩
VLC whepfrom💩💩⭐⭐⭐⭐💩
OBS Studio whip📺 3💩💩⭐⭐⭐💩
  • ⭐ 正常运行
  • 💩 不支持
  • 💡 未知/未测试
  • 📺 存在问题(需注意)
    1. 正常运行,但浏览器无法播放此视频,Gstreamer 到 Gstreamer 传输正常
    2. 我不知道为什么 av1 和 whep 会出错
    3. OBS av1 编解码器无法播放

认证 ​

关闭认证 ​

注意

默认是关闭认证的

如果没有设置任何关于 [auth] 块的内容,会关闭认证

Bearer token ​

静态的 HTTP bearer token 只能是超级管理员权限。 一般用于开发,测试和集群管理

toml
# WHIP/WHEP auth token
# Headers["Authorization"] = "Bearer {token}"
[auth]
# static JWT token, superadmin, debuggger can use this token
tokens = ["live777"]

JWT(JSON Web Token) ​

JWT 里面包含了权限信息,可以对单个流的推拉流和管理进行授权

toml
# WHIP/WHEP auth token
# Headers["Authorization"] = "Bearer {token}"
[auth]
# JSON WEB TOKEN secret
secret = "<jwt_secret>"

Cascade ​

什么是 cascade? ​

cascade

庞大的集群 ​

mash-cascade

live777 Cascade 有两种模式:

  • cascade-pull
  • cascade-push

live777-cascade

静态 cascade-pull(WHEP 源) ​

cascade-pull 除了调用 API,也可以声明为静态流的输入。构建时启用 source-whep feature,然后在预注册流上添加 whep:// 源即可;它与其他 配置源一样参与完整的生命周期(on_demand 启停、断线重连、RTCP 关键帧 反馈):

toml
[[stream.cam1.sources]]
url = "whep://edge-0:7777/whep/cam1"
# 需要 Bearer 鉴权时:
# url = "whep://token@edge-0:7777/whep/cam1"

当这个源配合 on_demand = true 使用时,即使 on_demand_start_timeout_ms 更低,live777 也会至少等待 35000ms 让上游 WHEP 源就绪。这样冷启动的 上游 WHEP/on-demand 源可以完成 HTTP setup 超时预算并送出第一包媒体。

外出的 WHEP peer 使用服务器自己的 [[ice_servers]] 配置收集 ICE 候选(默认为空——仅 host candidate,没有硬编码的 STUN 服务器),并使用 [webrtc] ice_udp_addrs 绑定的 UDP 端口。

链式 on-demand 拉流默认支持一跳:该源的 WHEP HTTP 请求最长等待 40000ms 应答,可以覆盖自身最多挂起 35000ms 的上游(on-demand WHEP 源)。更深的链路需要按部署对齐各级预算。停止该源(例如 on_demand 流的最后一个订阅者离开)可能需要等待一个在途的 WHEP HTTP 请求结束, 上限同为 40000ms。

静态 cascade-push(WHIP target) ​

cascade-push 除了调用 API,也可以声明为静态流的输出。构建时启用 target-whip feature,然后在预注册流上添加 whip:// target 即可:

toml
[[stream.cam1.targets]]
url = "whip://edge-1:7777/whip/cam1"
# 需要 Bearer 鉴权时:
# url = "whip://token@edge-1:7777/whip/cam1"

推流是媒体驱动的:当流获得发布者(WHIP 发布端或配置的 source)时建立, 发布者离开时拆除,因此下游节点看到的是普通的发布者上线/下线周期, 下游自己的 auto_delete_*/on-demand 策略可以正常工作。在 on_demand 流上配置的 target 相当于常驻需求:只要流既没有发布者也没有推流会话, 就会(重新)拉起该流的源,因此下游从不可达恢复后继流会自动恢复。 会话丢失后(下游关闭、ICE 失败、预注册流 reset)会以指数退避重建 (5 秒起步翻倍,60 秒封顶)——on-demand 源的重新拉起也受同一退避约束, 大约每分钟最多一次。

静态 RTSP 推流(RTSP target) ​

流也可以作为 RTSP 客户端推到 RTSP 服务器(ANNOUNCE/SETUP/RECORD)—— mediamtx、另一个 live777 的 RTSP 服务器(见下文)或 gst-rtsp-server。 它与 rtsp:// 源互为镜像:构建时启用 target-rtsp feature,然后在 预注册流上添加 rtsp:// target:

toml
[[stream.cam1.targets]]
url = "rtsp://mediamtx:8554/cam1"
# 需要 Digest/Basic 鉴权并使用 TCP interleaved 传输时(默认 UDP):
# url = "rtsp://admin:secret@mediamtx:8554/cam1?transport=tcp"

生命周期与 WHIP target 一致:流获得发布者时建立会话,发布者离开时拆除 (UDP 发送 TEARDOWN,TCP 关闭连接,服务器立即释放已发布的路径),失败 后以指数退避重建;on_demand 流上的 target 相当于常驻需求。只公告第 一条视频轨和第一条音频轨;视频会重新打包并在每个 IDR 前内联 SPS/PPS; 从服务器回传的关键帧请求(例如 mediamtx 转发的拉流端 PLI)会送达发布 端。whip://、rtp://、rtsp:// target 可以在同一条流上混用。

DataChannel 转发 ​

完整说明见 Cable(DataChannel 转发):按 label 声明的消息管 道([[stream.<name>.cables]])、带参数的服务器创建 channel、以及 cable <-> UDP 桥。

live777-datachannel

RTSP 服务器 ​

使用 rtsp feature 编译,即可在 WHIP/WHEP 之外暴露 RTSP 服务:

bash
cargo build --release --bin live777 --features rtsp

在 live777.toml 中配置监听 URL。当 URL 中包含凭据时,自动启用 Digest 认证:

toml
[rtsp]
# 无认证:
listen = "0.0.0.0:8554"
# 启用 Digest 认证:
# listen = "rtsp://admin:secret@0.0.0.0:8554"

同一个端口同时处理推流和拉流:

  • 推流地址:rtsp://host:8554/{stream_id}(ANNOUNCE + RECORD)
  • 拉流地址:rtsp://host:8554/{stream_id}(DESCRIBE + PLAY)

同时支持 UDP 和 TCP(RTP/AVP/TCP)传输。URL 的第一段路径作为 liveion 的流标识符。

流钩子(Stream Hooks) ​

Live777 可以在流生命周期事件上执行外部脚本:流的创建/删除,以及推流 开始/停止(WHIP/cascade 推流端挂载,或配置源启停)。典型用途是为 live777 无法直接驱动的设备做按需激活:真正需要媒体时由 hook 启动采集 设备 / 硬件编码器,最后一个消费者离开时再把它关掉以节省资源。

内置替代方案:配置的源([[stream.<name>.sources]])支持 on_demand = true, 可随订阅者有无自动启停摄像头或 RTSP 拉流——无需编写脚本。参见 livehal — 预注册流与按需源。

哪些事件代表"有人在看"?对预注册流(任何 [stream.<name>] 条目), stream-created 在启动时触发一次,无法用于电源控制——请改用 publish-started / publish-stopped。配置源的启停以会话 ID virtual-source 上报为推流事件。对动态流(auto_create_whep), stream-created 仍与首次使用同时发生。

toml
# 全局 hook,对所有流生效
[hooks]
timeout_ms = 5000    # 单个脚本超时(毫秒),0 表示不限制
on_error = "stop"    # "stop":脚本失败后跳过本事件剩余 hook;
                     # "continue":失败后仍继续执行
on_stream_created = ["/etc/live777/hooks/notify.sh"]
on_stream_deleted = ["/etc/live777/hooks/notify.sh", "/etc/live777/hooks/cleanup.sh"]
on_publish_started = ["/etc/live777/hooks/camera-power.sh"]
on_publish_stopped = ["/etc/live777/hooks/camera-power.sh"]

# 每流 hook,在全局 hook 之后执行
[stream.cam1.hooks]
on_stream_created = ["/etc/live777/hooks/cam1-created.sh"]
on_stream_deleted = ["/etc/live777/hooks/cam1-deleted.sh"]
on_publish_started = ["/etc/live777/hooks/cam1-power-on.sh"]
on_publish_stopped = ["/etc/live777/hooks/cam1-power-off.sh"]

执行保证:

  • 同一事件的 hook 按顺序串行执行:先全局、后每流,各自按配置顺序。
  • 所有事件共用一个 FIFO 队列处理——前一事件的全部 hook 执行完毕后,后 一事件的第一个 hook 才开始,因此同一条流的 stream-created hook 一定先于 它的 stream-deleted hook 执行完。
  • 脚本失败(非零退出、启动失败、超时被杀)只会被记录并按 on_error 处 理,不会影响后续事件,也不会影响服务器本身。

脚本以直接执行方式启动(不经过 shell),事件元数据同时通过 argv 和环境 变量传入:

argv环境变量取值
$1LIVE777_EVENTstream-created / stream-deleted / publish-started / publish-stopped
$2LIVE777_STREAM流名
$3(仅删除/停止时)LIVE777_REASONstream-deleted:api-deleted / publish-leave-timeout / subscribe-leave-timeout / orphaned / reset;publish-stopped:peer-closed / api-deleted / replaced / idle-timeout
—LIVE777_SESSION(仅推流事件)推流会话 ID;配置源为 virtual-source

注意事项:

  • 脚本应在发起工作后尽快返回(例如把编码器放到后台启动)。脚本阻塞多久, 整个 hook 队列就阻塞多久。
  • 脚本要幂等:推流端自身死亡(publish-leave-timeout)也会触发 stream-deleted hook,停止脚本必须能容忍设备已经停止的状态。
  • 做按需源时,配合 [strategy] auto_create_whep = true 和较大的 auto_delete_whep(如 30000),避免观众短暂掉线导致硬件反复启停。 每流覆盖配置在 [stream.<name>.strategy] 下。配置了 on_demand = true 的流已通过 on_demand_close_after_ms 自带防抖。
  • 服务器关闭时不会触发 hook(此时不产生 stream-deleted 事件)。

Released under the MPL-2.0 License.