跳转到内容

直播与 WebRTC/HLS/FLV

livestream 控制 WHIP/RTMP 推流、WHEP/RTMP/RTSP/HTTP-FLV 外部拉流、WebRTC 会话、HLS 分片、HTTP-FLV 连接和直播缓存。

如果你只使用点播媒体 Provider,这一页大部分配置可以保持默认。

直播子系统包含推流入口、RTP/frame 分发、WHEP/FLV 播放、HLS remux、HLS 存储和跨节点 publisher registry。点播 Provider 处理外部媒体 URL 和 Range proxy;直播子系统处理持续产生的数据流。

SyncTV 直播流水线图,展示 WHIP、RTMP 和外部拉流进入 StreamHub,再分发到 WHEP、HTTP-FLV 与 HLS,并通过 gRPC 在节点间转发 frame 和 RTP。SyncTV 直播流水线图,展示 WHIP、RTMP 和外部拉流进入 StreamHub,再分发到 WHEP、HTTP-FLV 与 HLS,并通过 gRPC 在节点间转发 frame 和 RTP。
WHIP 和上游 WHEP 同时保留 RTP 与 remux frame;WHEP 使用 RTP,HTTP-FLV 和 HLS 使用 frame。集群 relay 按源能力传输一条或两条数据通道。
  • WHIP ingest: 推流端向主 HTTP 服务提交 SDP offer。SyncTV 协商 H.264/Opus,保留 RTP,并生成 H.264/AAC frame。
  • WHEP playback: 客户端通过 SDP offer 建立 WebRTC 播放会话。源必须提供 RTP。
  • RTMP ingest: 推流端通过 RTMP 连接进入,认证阶段会把 publisher 注册到本节点或共享 registry。
  • RTSP ingest: 外部 RTSP 源通过 DESCRIBE/SETUP/PLAY 拉取,经过 RTP 解包后进入同一个 StreamHub。
  • StreamHub: 进程内同时分发 RTP packet 和 remux frame。普通 RTMP/RTSP/HTTP-FLV 源只提供 frame。
  • HTTP-FLV: 适合低延迟观看。客户端保持长连接,服务端持续写 FLV chunk,并通过写超时保护慢客户端。
  • HLS: 适合通用播放器和 CDN/对象存储形态。延迟更高,但对客户端兼容性和多副本扩展更友好。
协议 优点 代价 适合场景
WHEP WebRTC 低延迟、浏览器原生媒体轨道、ICE/TURN 穿透 源需要保留 RTP,服务端和客户端都需要可达 ICE candidate WHIP 推流、外部 WHEP 代理、低延迟浏览器播放
HTTP-FLV 延迟低、链路短、服务端直接推 chunk 长连接多,弱网慢客户端需要严格超时 互动直播、房间内同步观看
HLS 播放器兼容性强,天然按 playlist/segment 拉取,可配共享存储 延迟高于 FLV,需要管理分片存储 移动端、通用播放器、多副本、对象存储

SyncTV 在主 HTTP(S) 服务上实现 WHIP resource 和 WHEP resource。两个协议都使用一次性 SDP offer/answer;当前实现收集完整 ICE candidate,不提供 trickle ICE PATCH

操作 HTTP 资源 鉴权
创建 publish key POST /api/playback-providers/{roomId}/rtmp/{mediaId}/publish-key 当前用户 token 与推流权限
创建 WHIP 推流 POST /api/playback-providers/{roomId}/rtmp/{mediaId}/whip Bearer <publish-key>
删除 WHIP 推流 DELETE <POST 响应的 Location> 同一个 publish key
播放 managed live POST /api/playback-providers/{roomId}/live/{mediaId}/whep 当前用户或游客访问 token
播放 LiveProxy POST /api/playback-providers/{roomId}/live-proxy/{mediaId}/whep 当前用户或游客访问 token
删除 WHEP 播放 DELETE <POST 响应的 Location> 同一个观看身份

POST 请求使用 Content-Type: application/sdp。成功响应返回 201 Created、SDP answer 和同源 Location;客户端停止推流或播放时应发送 DELETE。服务器在连接关闭、会话超时或进程退出时清理本地资源。

公开名称 live 表示由 SyncTV 管理的 WHIP/RTMP 推流源;liveProxy 表示 SyncTV 拉取的外部 WHEP/RTSP/RTMP/HTTP-FLV 源。protobuf wire/source-config oneof 继续使用 RTMP/rtmp 表示 SyncTV 管理的直播源。

Provider prepare API 使用 POST /api/providers/prepare/live。HLS 和 HTTP-FLV 播放 URL 同样使用 /api/playback-providers/{roomId}/live/...

CLI 使用 live 创建 managed live 媒体,rtmp 仍作为输入别名:

终端窗口
synctv media add <ROOM_ID> --username alice \
--source-provider live \
--source-config-json '{"mode":"default"}' \
--name "直播"

使用 publish-key API 创建密钥后,响应会同时包含 rtmp_urlstream_keywhip_url。生产环境设置公开 HTTP(S) origin:

livestream:
public_webrtc_base_url: "https://live.example.com"
webrtc:
enabled: true
ice_gathering_timeout_seconds: 10
max_sdp_bytes: 262144
max_sessions: 1000
max_session_duration_seconds: 86400

public_webrtc_base_url 为空时,publish-key 响应返回相对当前 API origin 的 WHIP URL。该值只接受无 path、query 和 fragment 的 HTTP(S) origin。

WHIP 客户端把 publish key 放在 Bearer header:

终端窗口
curl -i -X POST "$WHIP_URL" \
-H "Authorization: Bearer $PUBLISH_KEY" \
-H "Content-Type: application/sdp" \
--data-binary @offer.sdp

WHEP 客户端使用访问房间的 token:

终端窗口
curl -i -X POST "$WHEP_URL" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/sdp" \
--data-binary @offer.sdp

curl 只能验证信令。媒体传输需要 WebRTC peer。浏览器客户端应创建 recvonly 音视频 transceiver,等待 ICE gathering 完成,POST pc.localDescription.sdp,再把响应设置为 remote answer。播放结束时对 Location 发送 DELETE。

OBS 的 WHIP service 填写响应中的 whip_url 和 publish key。GStreamer 需要安装带 whipclientsink 的 rswebrtc 插件,并输出 H.264/Opus。不同版本的属性名存在差异,可用 gst-inspect-1.0 whipclientsink 查看 endpoint 和 auth token 属性。FFmpeg 构建对 WHIP 的支持不一致;用 ffmpeg -muxers 检查当前二进制。没有 WHIP muxer 时,FFmpeg 可以继续向 rtmp_url 推送 H.264/AAC。

WHIP 和外部 WHEP 接受 H.264 constrained-baseline(profile-level-id=42e01fpacketization-mode=1)与 Opus。固定 H.264 profile 可以让未转码的 WHEP RTP 输出保持与 SDP 一致。SyncTV 将 H.264 RTP 解包为 AVC frame,并把 Opus 解码后编码为 AAC,因此同一输入可供 HLS 和 HTTP-FLV 播放。

SyncTV 实现标准 WHIP resource 语义和 WHEP draft resource 语义。云厂商的私有签名参数、私有信令接口、SIMULCAST 控制 API 和专用 ingest SDK 不属于这两个协议;接入此类服务时需要一个标准 WHIP/WHEP endpoint。

LiveProxy 可以把远程 WHEP 资源代理到本地 WHEP、HLS 和 HTTP-FLV:

{
"provider": "liveProxy",
"source": {
"protocol": "whep",
"url": "https://origin.example.com/whep/channel-1",
"authorization": "Bearer upstream-token"
}
}

SyncTV 对 endpoint 做 SSRF 校验和 DNS pinning,禁止 HTTP redirect,并要求上游返回 201 Createdapplication/sdp 与同源 Location。服务端限制 SDP 大小和读取时间;本地拉流结束后会 DELETE 远程 resource。管理查询不会回显 authorization,日志也不会记录上游 URL 或 Authorization。

WHEP URL 可以使用 query token。URL 不接受 userinfo 和 fragment;HTTP header 凭据应放在 authorization 字段。

livestream.webrtc.ice_servers 配置直播 PeerConnection 使用的 STUN/TURN 服务。顶层 webrtc 配置管理房间语音/媒体 P2P 和内置 STUN,两组选项服务不同的 WebRTC 功能。

livestream:
webrtc:
ice_servers:
- urls:
- "stun:stun.example.com:3478"
- "turn:turn.example.com:3478?transport=udp"
- "turns:turn.example.com:5349?transport=tcp"
username: "synctv"
credential_file: "/run/secrets/livestream_turn_credential"

STUN 只帮助 peer 发现地址。服务器位于 Kubernetes、NAT 或严格防火墙后时,部署一个客户端和 Pod 都可访问的 TURN 服务。TURN UDP 提供较低延迟,TURN/TLS over TCP 适合限制 UDP 的网络。

WHIP/WHEP 信令走现有 HTTP Service。ICE 媒体使用动态 UDP 端口,Helm chart 不创建固定的 WebRTC media UDP Service。Kubernetes 部署应使用 TURN;采用 hostNetwork 时需同时开放节点的 ICE UDP 端口范围。stunService 只暴露内置 STUN listener,不转发媒体。

RTSP 外部源使用显式协议配置。每个媒体条目对应一个独立拉流会话,多个媒体条目可以并行拉取多个摄像头或流媒体服务器;每个节点默认最多运行 100 个外部流。

{
"provider": "liveProxy",
"source": {
"protocol": "rtsp",
"url": "rtsp://camera.example/live",
"transport": "tcp",
"videoTrack": { "mode": "firstCompatible" },
"audioTrack": { "mode": "firstCompatible" }
}
}

可用设置:

字段 含义
transport tcp / udp TCP 使用 interleaved RTP;UDP 适合可控局域网
videoTrack firstCompatible / index / disabled 选择 H.264/H.265 视频轨道
audioTrack firstCompatible / index / disabled 选择 AAC 音频轨道

指定 SDP 中第 2 个视频轨道并关闭音频:

{
"videoTrack": { "mode": "index", "index": 1 },
"audioTrack": { "mode": "disabled" }
}

Basic 和 Digest 认证可使用 RTSP URL userinfo,例如 rtsp://user:password@camera.example/live。日志会移除 userinfo、query 和 fragment;部署侧应通过受控配置入口管理包含凭据的 source config。

RTSP 输入支持 H.264、H.265 和 AAC。SyncTV 将它们转换为 AVC/HEVC/AAC FLV tag,HTTP-FLV 与 HLS 沿用现有直播交付、集群注册、跨节点 relay、空闲清理和断线重试链路。

外部 RTMP 源通过 mode 控制转发的媒体类型。RTMP 消息本身按音频和视频分类,mode 负责过滤消息类型,不涉及 RTSP 的轨道编号选择。

{
"provider": "liveProxy",
"source": {
"protocol": "rtmp",
"url": "rtmp://origin.example/live/stream",
"mode": "default"
}
}

mode 可取 default(音频和视频)、videoOnly(只转发视频)或 audioOnly(只转发音频)。外部 RTMP 拉流在拉流会话中过滤,SyncTV 管理的 RTMP 推流在认证后的 server session 中过滤,HTTP-FLV 和 HLS 会得到同一份筛选后的 Live StreamHub 数据。

RTSP 的 videoTrackaudioTrack 至少需要启用一项。双 disabled 配置会在添加媒体时被拒绝;具体轨道编号与编码兼容性在 RTSP SDP 建立连接时继续校验。

RTSP、外部 RTMP 与内部 RTMP 推流都进入同一个 Live StreamHub。SyncTV 为它们生成 HLS 和 HTTP-FLV;HLS playlist 使用短滑动窗口,TS 分片随窗口淘汰,任意时间跳转与持久录制属于当前产品范围之外。

memory 是默认值,分片只存在当前进程内。它最简单,适合单副本、开发环境和低流量多副本。

限制:进程重启会丢分片;多副本下非 publisher 节点需要通过 HLS gRPC proxy 到 publisher 节点读取 playlist/segment。它可以工作,但不适合作为高并发生产 HLS 的首选。

  1. Publisher 通过 WHIP 或 RTMP 连接到任意一个 SyncTV 节点;LiveProxy 也可以在任意节点拉取外部 WHEP。
  2. 认证通过后,节点把 room_id/media_id -> node_id/api_address 注册到 publisher registry。集群模式下 registry 使用 Redis。
  3. 本节点 StreamHub 接收 frame;WHIP/WHEP 源还会保留 RTP。HTTP-FLV 和 HLS 订阅 frame,WHEP 订阅 RTP。
  4. HLS 分片写入 memoryfileshared_files3 backend。
  5. 观众请求落到非 publisher 节点时,该节点通过共享 registry 找到 publisher owner。gRPC relay 分别传输 frame 和 RTP,并使用 generation ID 与 lease epoch 拒绝过期 publisher。
  6. shared_file 的 TS 分片请求由当前节点从共享路径读取;本地 backend 仍使用 publisher-node HLS gRPC proxy 读取远端 playlist/segment。

默认值:1935

作用:RTMP 推流端口。

OBS 推流地址通常类似:

rtmp://your-domain:1935/live/<stream-key>

managed live Provider 的媒体 source config 也支持相同的 mode 字段:

{
"provider": "live",
"mode": "audioOnly"
}

该配置决定进入 StreamHub 的音视频类型,播放端继续使用 SyncTV 生成的 HLS 或 HTTP-FLV 地址。

如果服务器已经有其他 RTMP 服务占用 1935,可以改成别的端口。

默认值为空。

作用:返回给推流客户端的公开 RTMP 主机名。

生产环境通常需要显式设置,尤其是:

  • 集群内部 server.advertise_host 是 Pod IP。
  • 真实用户需要通过公网域名或 LoadBalancer 推流。

示例:

livestream:
public_rtmp_host: "live.example.com"

如果为空,SyncTV 只会回退到本机绑定地址,适合本地开发或单机内网测试;不会使用 Pod IP 或集群内部 server.advertise_host 作为公开推流地址。

默认值:2

GOP 是视频编码中的一组帧。GOP 缓存可以让新连接的观众更快开始播放,不必等下一个关键帧。

普通部署保持默认即可。

默认值:100

作用:限制单个直播流的 GOP 缓存内存。总 GOP 缓存占用可能接近该值乘以活跃直播流数量。

调大场景:

  • 视频码率高。
  • 新观众经常加入,想提升起播体验。

调小场景:

  • 服务器内存有限。

默认值:300

作用:拉流空闲多久后自动停止。

如果你有长时间无人观看但希望保持拉流的场景,可以调大。否则保持默认能节省上游和本机资源。

默认值:10

拉流失败最多重试多少次。

默认值:1000

第一次失败后等待多久再重试。

默认值:30000

重试等待时间最多增长到多少。

上游直播源短暂断线时,SyncTV 会自动重试。等待时间会逐步变长,避免持续高频请求上游。

默认值:10485760,也就是 10 MB。

作用:限制单个 FLV tag 最大大小,防止异常流导致内存占用过高。

不建议随意调大。除非你明确知道上游会产生更大的合法 tag。

默认值:memory

可选值:

作用 适用场景
memory HLS 分片保存在当前进程内存里 单副本、临时直播、开发环境
file HLS 分片写入当前节点的 livestream.hls_storage.path 单副本文件存储,或小规模多副本 publisher-node proxy
shared_file HLS 分片写入所有副本共享的 livestream.hls_storage.path 多副本共享文件系统,TS 分片由当前节点从共享路径读取
s3 HLS 分片写入 S3 兼容对象存储 多副本、Kubernetes、跨节点共享

规范值是 memoryfileshared_files3

集群模式可以使用 memoryfile。非 publisher 节点会通过 HLS gRPC proxy 到 publisher 节点读取 playlist/segment。这个模式适合小规模部署或验证环境;生产高并发 HLS 推荐使用:

  • shared_file,并且 hls_storage.path 是所有副本可读写的共享文件系统。.ts 请求会由当前节点直接从共享路径读取。
  • s3,并配置 livestream.hls_storage.*

默认值:0,表示使用内置默认。

作用:限制 hls_storage.type=memory 时的 HLS 分片内存占用。0 使用内置默认,当前内置默认是 512 MB。

livestream:
hls_storage:
type: "shared_file"
path: "/var/lib/synctv/hls"

shared_file 明确表示这个路径是 NFS、RWX PVC、CSI volume 等所有副本可见的共享文件系统。不要把 Pod 本地 emptyDir/tmp 或本机磁盘配置成 shared_file

shared_file 模式下,publisher 节点负责写入 HLS 分片;任意节点收到 .ts 请求时,会从当前节点挂载的共享路径读取分片,不再回源到 publisher 节点获取 TS 文件。

默认值为空。

作用:hls_storage.type=fileshared_file 时的 HLS 分片存储路径。相对路径会相对 data_dir

示例:

data_dir: "/var/lib/synctv"
livestream:
hls_storage:
type: "file"
path: "livestream/hls"

实际路径:

/var/lib/synctv/livestream/hls

hls_storage.type=s3 时,SyncTV 使用 S3 兼容对象存储保存 HLS 分片。

livestream:
hls_storage:
type: "s3"
endpoint: "https://s3.example.com"
bucket: "synctv-hls"
region: "auto"
base_path: "synctv/hls/"

secret 建议使用环境变量或 secret 文件注入:

终端窗口
export SYNCTV_LIVESTREAM_HLS_STORAGE_ACCESS_KEY_ID="..."
export SYNCTV_LIVESTREAM_HLS_STORAGE_SECRET_ACCESS_KEY="..."

字段说明:

字段 默认值 作用
livestream.hls_storage.endpoint "" S3-compatible endpoint,例如 AWS S3、MinIO、Cloudflare R2 或兼容服务的 endpoint
livestream.hls_storage.bucket "" 存储 HLS 分片的 bucket
livestream.hls_storage.access_key_id "" Access key ID,支持 access_key_id_file
livestream.hls_storage.secret_access_key "" Secret access key,支持 secret_access_key_file
livestream.hls_storage.region null S3 region;某些兼容服务可留空或使用服务商要求的值
livestream.hls_storage.base_path hls/ bucket 内对象前缀;会规范化为不以 / 开头、以 / 结尾

livestream.flv_max_connection_duration_seconds

Section titled “livestream.flv_max_connection_duration_seconds”

默认值:86400,也就是 24 小时。

作用:单个 HTTP-FLV 连接最长保持多久。

设置为 0 可以关闭限制,但不推荐。长时间连接如果永不限制,异常客户端可能长期占用资源。

默认值:30

作用:向客户端写数据时最多等待多久。

如果客户端网络很慢,写入一直阻塞,SyncTV 会在超时后断开连接,避免慢客户端拖垮服务。