iOS 12–14 完全不支持 RTSP,必须服务端转 HLS;需用 H.264 Baseline、AAC-LC 编码,严格遵循 Apple HLS 规范,并正确设置 viewport 和安全区。

iOS 低版本(iOS 12–14)根本不能直接播放 RTSP
不是“兼容性差”,而是完全不支持——rtsp:// 协议在 Safari(包括所有 iOS 浏览器)中从未被实现过,无论版本新旧。iOS 12、13、14 的 Safari 都没有 RTSP 解析器, 会静默失败,控制台通常连错误都不报,只显示黑屏或加载转圈。
- 哪怕你加了
type="application/rtsp",浏览器也直接忽略该 type,当无效 source 处理 - 所谓“iOS 14 支持 HTML5”是指支持
+ MP4/HLS/WebM,和 RTSP 无关 - 本地文件(
file://)下更糟:iOS 连 fetch、WebSocket 都可能被禁用,调试都困难
唯一可行路径:服务端转 HLS,且必须适配 iOS 12+ 的 HLS 要求
iOS 全系(含 iOS 12)原生支持 HLS,但对切片格式、编码参数极其敏感。FFmpeg 转出来的流若不符合 Apple 的《HTTP Live Streaming Recommendations》,Safari 会直接拒绝加载,尤其老机型。
- 必须用 H.264 Baseline 或 Main Profile(
-profile:v baseline),High Profile 在 iOS 12–13 上大概率失败 - 音频必须是 AAC-LC(
-c:a aac -ac 2 -ar 44100),HE-AAC 不被部分旧设备识别 -
-hls_time建议设为4或6(不能太大),iOS 12 对 >10s 切片的容错极低 - 务必在 Nginx 中配置 MIME 类型:
types { application/x-mpegURL m3u8; },否则 iOS Safari 拒绝解析
示例命令(实测 iOS 12.4 iPhone 7 可播):
ffmpeg -i rtsp://user:pass@192.168.1.100:554/stream \ -c:v libx264 -profile:v baseline -level 3.0 -b:v 800k \ -c:a aac -ac 2 -ar 44100 -b:a 96k \ -f hls -hls_time 4 -hls_list_size 6 -hls_flags delete_segments \ /var/www/html/cam1.m3u8
别信“HTML5 原生 RTSP 播放器”宣传
市面上标榜“零转码”“原生支持 RTSP”的 JS 库(如某些 html5_rtsp_player 分支),实际都依赖 WebSocket 代理 + MSE 拼帧。它们在 iOS 上基本不可用,原因很实在:
立即学习“前端免费学习笔记(深入)”;
- iOS Safari 的
MediaSourceAPI 在 iOS 12–14 上有严重限制:不支持动态 append 多个 SourceBuffer、对 H.264 Annex B NALU 起始码校验极严、buffer 更新卡顿易崩 - WebSocket 连接在后台标签页会被系统限频甚至断开,iOS 13+ 尤其明显
- 所有这类方案都需要自建代理服务(如
ws_rtsp),而 iOS 对非 HTTPS 的 ws:// 连接默认拦截(即使 localhost)
viewport 和安全区不是次要问题,而是 iOS 播放器能显示的前提
就算 HLS 流本身能播,如果页面没正确设置 viewport 或未处理安全区,视频容器可能被刘海/圆角裁切、controls 按钮点不到、全屏按钮失效——用户第一反应就是“播不了”,其实只是 UI 错位。
- 必须加:
- 视频容器需留出安全边距:
padding-bottom: env(safe-area-inset-bottom) - 避免用
width=375等固定值;iOS 会无视并强制缩放,导致 canvas 渲染模糊、触摸坐标偏移
真正在 iOS 12–14 上跑通 RTSP 播放,核心不在“怎么写 JS”,而在“怎么让服务端输出 Safari 认得的流 + 怎么让页面不被系统 UI 吃掉”。漏掉任意一环,都会表现为“白屏”“无声音”“点不动”,而不是明确报错。










