<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>实时视频 - tag - 沐木</title><link>https://oldletter.cn/tags/%E5%AE%9E%E6%97%B6%E8%A7%86%E9%A2%91/</link><description>实时视频 - tag - 沐木</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Sat, 11 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://oldletter.cn/tags/%E5%AE%9E%E6%97%B6%E8%A7%86%E9%A2%91/" rel="self" type="application/rss+xml"/><item><title>实时视频（二）：RTP 解包、Access Unit 与关键帧等待</title><link>https://oldletter.cn/posts/rtsp-browser-02-rtp-access-unit/</link><pubDate>Sat, 11 Jul 2026 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/rtsp-browser-02-rtp-access-unit/</guid><description><![CDATA[<blockquote>
<p>系列导航：<a href="/posts/rtsp-browser-01-protocol-options/" rel="">8</a> | <a href="/posts/rtsp-browser-02-rtp-access-unit/" rel="">9</a> | <a href="/posts/rtsp-browser-03-webcodecs-wasm/" rel="">10</a></p></blockquote>
<p>RTP 一个包不等于一帧视频。H.264 和 H.265 都支持单 NAL、聚合和分片，网络还会产生乱序、重复、丢包和序列号回绕。播放器下游需要的是带时间戳、关键帧标记、参数集版本和完整性结果的 Access Unit，不能把 RTP 细节继续泄漏到渲染代码。</p>
<h2 id="扩展序列号和乱序窗口">扩展序列号和乱序窗口</h2>
<p>每个 SSRC 维护自己的序列号状态。RTP 序列号是 16 位，扩展序列号需要根据已记录的基准判断回绕方向。实现不应直接用普通整数比较，否则从 <code>65535</code> 到 <code>0</code> 会被当成大范围乱序。</p>
<p>乱序缓冲保存包、到达时间和期望序列号。窗口按包数或时间限制，窗口到期就记录缺口并决定丢弃当前 NAL。重复包不再次拼接，但计入重复指标。SSRC 变化时切换独立状态，不能把两路源的分片放进同一缓冲。</p>
<div class="mermaid" id="id-2" data-mermaid-definition="Zmxvd2NoYXJ0IFRECiAgICBQYWNrZXRbUlRQIOWMhV0gLS0&#43;IEhlYWRlclvmoKHpqowgUlRQIOWktOS4jiBTU1JDXQogICAgSGVhZGVyIC0tPiBPcmRlclvmianlsZXluo/liJflj7fkuI7kubHluo/nqpflj6NdCiAgICBPcmRlciAtLT4gUGF5bG9hZHvotJ/ovb3nsbvlnot9CiAgICBQYXlsb2FkIC0tPiBTaW5nbGVb5Y2VIE5BTF0KICAgIFBheWxvYWQgLS0&#43;IEFnZ3JlZ2F0ZVvogZrlkIjljIXmi4bliIZdCiAgICBQYXlsb2FkIC0tPiBGcmFnbWVudFvliIbniYfph43nu4RdCiAgICBTaW5nbGUgLS0&#43;IEFVW&#43;aMieaXtumXtOaIs&#43;e7hCBBY2Nlc3MgVW5pdF0KICAgIEFnZ3JlZ2F0ZSAtLT4gQVUKICAgIEZyYWdtZW50IC0tPiBBVQogICAgQVUgLS0&#43;IENoZWNrW&#43;WujOaVtOaAp&#43;S4juWPguaVsOmbhuajgOafpV0KICAgIENoZWNrIC0tPiBLZXlb5YWz6ZSu5bin562J5b6F5oiW5Lqk5LuYXQ==">flowchart TD
    Packet[RTP 包] --&gt; Header[校验 RTP 头与 SSRC]
    Header --&gt; Order[扩展序列号与乱序窗口]
    Order --&gt; Payload{负载类型}
    Payload --&gt; Single[单 NAL]
    Payload --&gt; Aggregate[聚合包拆分]
    Payload --&gt; Fragment[分片重组]
    Single --&gt; AU[按时间戳组 Access Unit]
    Aggregate --&gt; AU
    Fragment --&gt; AU
    AU --&gt; Check[完整性与参数集检查]
    Check --&gt; Key[关键帧等待或交付]</div><h2 id="h264-与-h265-负载解析">H.264 与 H.265 负载解析</h2>
<p>H.264 常见单 NAL、STAP-A 和 FU-A。H.265 使用不同的 NAL 头以及聚合和分片类型，NAL 类型所在的位段不能直接复用 H.264 的掩码。聚合包每个单元带长度字段，解析前检查长度不超过剩余字节；一项越界，整个 RTP 包丢弃。</p>]]></description></item><item><title>实时视频（三）：解码与断流</title><link>https://oldletter.cn/posts/rtsp-browser-03-webcodecs-wasm/</link><pubDate>Sat, 11 Jul 2026 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/rtsp-browser-03-webcodecs-wasm/</guid><description><![CDATA[<blockquote>
<p>系列导航：<a href="/posts/rtsp-browser-01-protocol-options/" rel="">8</a> | <a href="/posts/rtsp-browser-02-rtp-access-unit/" rel="">9</a> | <a href="/posts/rtsp-browser-03-webcodecs-wasm/" rel="">10</a></p></blockquote>
<p>浏览器有 <code>VideoDecoder</code> 接口，不代表当前 H.264/H.265 配置一定可用。能力探测、输入格式、解码队列和断流重建必须放在同一条状态链里。当前 demo 采用 Worker 解耦主线程，Rust/WASM 在解码提交前检查码流结构。</p>
<h2 id="能力探测绑定具体配置">能力探测绑定具体配置</h2>
<p>收到参数集后构造 <code>VideoDecoderConfig</code>，配置中包含 codec string、description、codedWidth、codedHeight 和必要的硬件提示。先调用 <code>VideoDecoder.isConfigSupported()</code>，成功后再创建解码器。参数集摘要、分辨率或 profile 变化时，旧结果失效，必须重新探测。</p>
<div class="mermaid" id="id-2" data-mermaid-definition="c3RhdGVEaWFncmFtLXYyCiAgICBbKl0gLS0&#43;IElkbGUKICAgIElkbGUgLS0&#43;IFByb2Jpbmc6IOaUtuWIsOWPguaVsOmbhgogICAgUHJvYmluZyAtLT4gV2ViQ29kZWNzOiDmlK/mjIEKICAgIFByb2JpbmcgLS0&#43;IFdhc206IOS4jeaUr&#43;aMgeaIluWIneWni&#43;WMluWksei0pQogICAgV2ViQ29kZWNzIC0tPiBQbGF5aW5nOiDlhbPplK7luKflj6/op6PnoIEKICAgIFdhc20gLS0&#43;IFBsYXlpbmc6IFdvcmtlciDliJ3lp4vljJblrozmiJAKICAgIFBsYXlpbmcgLS0&#43;IFdhaXRpbmdLZXlmcmFtZTog5Lii5YyF5oiW6YWN572u5Y&#43;Y5YyWCiAgICBXYWl0aW5nS2V5ZnJhbWUgLS0&#43;IFByb2Jpbmc6IOaWsOWPguaVsOmbhgogICAgUGxheWluZyAtLT4gUmVjb3ZlcmluZzog5pat5rWB5oiW6Kej56CB6ZSZ6K&#43;vCiAgICBSZWNvdmVyaW5nIC0tPiBQcm9iaW5nOiDph43lu7rmiJDlip8KICAgIFJlY292ZXJpbmcgLS0&#43;IEVycm9yOiDotoXov4fph43or5XpooTnrpc=">stateDiagram-v2
    [*] --&gt; Idle
    Idle --&gt; Probing: 收到参数集
    Probing --&gt; WebCodecs: 支持
    Probing --&gt; Wasm: 不支持或初始化失败
    WebCodecs --&gt; Playing: 关键帧可解码
    Wasm --&gt; Playing: Worker 初始化完成
    Playing --&gt; WaitingKeyframe: 丢包或配置变化
    WaitingKeyframe --&gt; Probing: 新参数集
    Playing --&gt; Recovering: 断流或解码错误
    Recovering --&gt; Probing: 重建成功
    Recovering --&gt; Error: 超过重试预算</div><p>探测失败和解码失败是两类信号。前者说明配置不被当前实现接受，后者可能来自 Annex B/长度前缀不匹配、缺失参考帧或坏包。用异常重试代替能力探测会让错误路径反复创建解码器，页面只会越来越卡。</p>]]></description></item><item><title>实时视频（一）：RTSP 到浏览器的协议选择</title><link>https://oldletter.cn/posts/rtsp-browser-01-protocol-options/</link><pubDate>Sat, 11 Jul 2026 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/rtsp-browser-01-protocol-options/</guid><description><![CDATA[<blockquote>
<p>系列导航：<a href="/posts/rtsp-browser-01-protocol-options/" rel="">8</a> | <a href="/posts/rtsp-browser-02-rtp-access-unit/" rel="">9</a> | <a href="/posts/rtsp-browser-03-webcodecs-wasm/" rel="">10</a></p></blockquote>
<p>浏览器没有通用的 RTSP 播放入口。摄像头的 RTP 负载需要经过协议转换、容器封装或转码，才能交给浏览器的媒体栈。协议选择不能从“哪个库能播放”开始，应从延迟预算、编码格式、网络边界、并发方式和音频要求倒推。</p>
<h2 id="先写延迟预算">先写延迟预算</h2>
<p>端到端延迟可以拆成：</p>
<p>$$L = L_{capture} + L_{encode} + L_{gateway} + L_{network} + L_{buffer} + L_{decode} + L_{render}$$</p>
<p>每一项都要有观测点。只看浏览器缓冲区会漏掉摄像头编码和网关排队。实时云台控制通常需要低延迟和快速恢复，回放或大屏分发更看重 CDN 复用和长连接稳定性。延迟预算写成上限后，协议比较才有可执行标准。</p>
<div class="mermaid" id="id-2" data-mermaid-definition="Zmxvd2NoYXJ0IFRECiAgICBDYW1lcmFbUlRTUCDmkYTlg4/lpLRdIC0tPiBQdWxsW&#43;acjeWKoeerr&#43;aLiea1geS4juS/nea0u10KICAgIFB1bGwgLS0&#43;IFJUUFtSVFAg6Kej5YyFXQogICAgUlRQIC0tPiBBVVtBY2Nlc3MgVW5pdF0KICAgIEFVIC0tPiBXZWJSVENbV2ViUlRDIOaJk&#43;WMhV0KICAgIEFVIC0tPiBGTVA0W2ZNUDQg5bCB6KOFXQogICAgQVUgLS0&#43;IFdTW1dlYlNvY2tldCDlrZfoioLpgJrpgZNdCiAgICBXZWJSVEMgLS0&#43;IEJyb3dzZXJb5rWP6KeI5Zmo5pKt5pS&#43;XQogICAgRk1QNCAtLT4gTVNFW01TRV0KICAgIEZNUDQgLS0&#43;IEhMU1tMTC1ITFNdCiAgICBXUyAtLT4gRGVjb2RlcltXZWJDb2RlY3Mg5oiWIFdBU01dCiAgICBNU0UgLS0&#43;IEJyb3dzZXIKICAgIEhMUyAtLT4gQnJvd3NlcgogICAgRGVjb2RlciAtLT4gQnJvd3Nlcg==">flowchart TD
    Camera[RTSP 摄像头] --&gt; Pull[服务端拉流与保活]
    Pull --&gt; RTP[RTP 解包]
    RTP --&gt; AU[Access Unit]
    AU --&gt; WebRTC[WebRTC 打包]
    AU --&gt; FMP4[fMP4 封装]
    AU --&gt; WS[WebSocket 字节通道]
    WebRTC --&gt; Browser[浏览器播放]
    FMP4 --&gt; MSE[MSE]
    FMP4 --&gt; HLS[LL-HLS]
    WS --&gt; Decoder[WebCodecs 或 WASM]
    MSE --&gt; Browser
    HLS --&gt; Browser
    Decoder --&gt; Browser</div><h2 id="四种下游路径">四种下游路径</h2>
<p>WebRTC 适合交互预览。它有 ICE、拥塞控制、抖动缓冲和关键帧反馈，工程重点落在信令、TURN、会话权限和媒体服务器。低延迟不等于零延迟，编码 GOP、网络中继和浏览器缓冲仍会影响体验。</p>]]></description></item></channel></rss>