目标:在不转码或尽量少转码的前提下,把 RTSP 转发为 RTMP,用于中心/边缘/CDN;同时支持预览、录像、实时静音、多路并发与 URL 动态切换。实现载体为 大牛直播SDK 的跨平台转发模块(Windows / Linux x86_64 & aarch64 / Android / iOS)。
传统做法:摄像头(RTSP/RTMP)→ 中心转发 → CDN/业务平台。 现实需求:无人机、机器人、移动安防、工业终端等“第一公里”就要低时延、少回源、可离线/弱网运行。 端侧或边缘节点上做转发,能显著降低首跳时延、缓解中心压力,并提升临时布控能力。大牛直播SDK提供的 多路 RTSP/RTMP → RTMP 转发 以 SDK 形态供二次集成,适合做成“端侧转发盒子/APP/嵌入式模块”。
把转发做稳,首要是把边界划清楚:
工程原则
典型顺序:OPTIONS → DESCRIBE → (逐 track) SETUP → PLAY → [Keepalive] → TEARDOWN
OPTIONS
或 GET_PARAMETER
定期保活,避免会话超时。
建议携带:CSeq
、User-Agent
、Accept: application/sdp
。许多设备要求 逐 track SETUP,聚合 URI PLAY(总控制 URI 来自 SDP 的 a=control:*
或 a=control:rtsp://...
)。
UDP 单播(低时延,受 NAT/防火墙影响大)
客户端声明本地端口区间,服务端回传其 server_port
:
SETUP rtsp://cam/trackID=1 RTSP/1.0 Transport: RTP/AVP;unicast;client_port=5000-5001
服务端响应(示例):
Transport: RTP/AVP;unicast;client_port=5000-5001;server_port=6000-6001 Session: 8a1b2c;timeout=60
注意:外网/NAT 下需打洞与端口映射;路由/ACL 不友好时易失败。
TCP 内嵌(穿透友好,弱网更稳,时延略高) RTP/RTCP 复用在 RTSP TCP 连接 内,通过 channel 编号区分:
SETUP rtsp://cam/trackID=1 RTSP/1.0 Transport: RTP/AVP/TCP;unicast;interleaved=0-1
$ <1字节channel> <2字节长度> <RTP/RTCP负载>
0-1
,audio 用 2-3
。
选择策略(Android 建议)
SETUP
/PLAY
返回:Session: <id>[;timeout=xx]
;
Session
;
timeout
的一半~三分之二间隔发送 OPTIONS
/GET_PARAMETER
;
SETUP
。
开始播放时,服务端可在响应中下发参考点:
Range: npt=0.000- RTP-Info: url=rtsp://cam/trackID=1;seq=34567;rtptime=123456789
seq/rtptime
用于 首帧对齐与时间线锚定;
Range
指定从何处开始(直播多为 npt=0-
或不带 Range)。
DESCRIBE/SETUP/PLAY
;
TCP_NODELAY
,减少交付抖动;
connect/read
合理分级(如 3s/5s/10s),重试带退避;
丢包/重传(若有)/RTT/重连次数/会话时长
,联动上层限速与回落策略。
小结:Transport 的正确选择 + Session 的稳定维护 + RTP-Info 的首播对齐,决定了拉流侧的可用性与首开体验;在 Android 端,把“自动回落/保活/分诊与重建”做扎实,能显著提升弱网下的成功率与稳定性。
示例(简化):
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=42c01f;sprop-parameter-sets=...
m=audio 0 RTP/AVP 97
a=rtpmap:97 MPEG4-GENERIC/48000/2
a=fmtp:97 mode=AAC-hbr;config=1190;sizeLength=13;indexLength=3;indexDeltaLength=3
sprop-parameter-sets
下发(H.265 有 VPS/SPS/PPS 对应语义)。
config
是 AudioSpecificConfig,对应到 RTMP/FLV 的 AAC sequence header。
定位:把“已经重组好的编码帧”(H.264/H.265 视频、AAC 音频)复用成 RTMP/FLV 上行消息,确保时间基一致、首包可解、长时间稳定播放。
C0/C1/C2 ↔ S0/S1/S2
。
connect(app)
→ 设置 Window Acknowledgement Size / Set Peer Bandwidth / Set Chunk Size
。
createStream
→ publish(stream, “live”)
。
onMetaData
(Script/AMF,宽高、帧率、编码信息等);
timestamp
表示 DTS;当值 ≥ 16777215 需用 extended timestamp 扩展。
Message Type ID
:Video=9、Audio=8、Script=18。
Message Stream ID
通常固定为 1(也可按需设置),音视频共用同一 Stream ID;
chunk size
(如 4096–8192)以降低分片开销。
AVCDecoderConfigurationRecord
,携带 SPS/PPS、NAL 长度字段(一般 4 字节)。
AVC NALU
(AVCC 格式,长度前缀而非起始码);
CT = PTS - DTS
,为 有符号 24 位。
AudioSpecificConfig
(Profile、采样率索引、声道数)。
onMetaData
→ 视频 SH → 音频 SH → 关键帧 → 正常流;
chunk size
。
目标:端侧转发在不转码的前提下,确保 时间线单调、A/V 同步稳定、首开迅速且无花屏。核心是把 RTP/采样时钟 映射为 RTMP 毫秒时基,并在抖动与漂移下维持可播放的时间序列。
锚点策略:
v_base
),首帧 DTS/PTS 归零 或对齐到小正数(如 0/40 ms)。
a_base
),或通过 RTCP SR 对齐到视频锚点(更精确)。
v_ms = (rtp_ts - v_base) / 90
CT = PTS_ms - DTS_ms
30 fps 示例:相邻帧 RTP 递增 3000 → 3000 / 90 = 33.333… ms
。累计小数残差,不得用四舍五入截断导致长时间漂移。
Δa_ms = 1000 * 1024 / sample_rate
21.333… ms
23.219… ms
Δ = (a_ms - v_ms)
最小闭环(不转码/可选转 AAC):
[RTSP/RTMP Source] --(拉流SDK回调)--> [复用/时间戳映射/可选音频转AAC]
\
+--> [RTMP推流SDK] --(ms时基/首包IDR)--> [RTMP Server/CDN]
备注
rtmp_ms = rtp_ts / 90
(Video);AAC 按帧步进累加;禁止时间戳回拨;CompositionTime(CT)控制在 0–250 ms(如无 B 帧),有 B 帧时仅在同一 GOP 内允许小幅负值。
setThreadPriority
)。
校验:拥塞期依然保证“可见可懂”(关键帧链不断),回落后画面快速恢复。
把规范读薄,把实现做厚。 读薄,在于边界清晰:RTSP 负责控制、SDP 做能力描述、RTP/RTCP 承载与校时、RTMP 负责复用与上行,外加一条可验证的时钟映射(RTP→毫秒)。 做厚,在于工程韧性:最短缓冲与直通优先、多路并发隔离、弱网自适与回落、指标完备与可观测、故障分诊与 7×24 自愈。
依托 大牛直播SDK 的「拉流回调 + 推流输入」组合,你可以把 RTSP→ RTMP 转发 沉淀为一块可复用、可运维、可规模化的底座能力:
最终效果是:同一套接口语义、同一套观测指标、同一套稳定性策略,贯穿端—边—云全链路。实时视频因此更贴近现场、更贴近业务,也更容易被复制、被维护、被长期运营。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。