H5 直播在工程上是三种完全不同的东西。多数方案失败,是因为把"网页看直播"和"网页开直播"当成了一件事。本文结合 ZEGO RTC 的能力,讲清 H5 直播的三种形态(观看、浏览器推流、双向连麦),再按延迟预算选 HLS、HTTP-FLV 或 WebRTC 等协议,附可运行代码与兼容性兜底。
1. 先分清:你要的是"能看"还是"能播"?
| 形态 | 谁在推流 | H5 负责什么 | 协议 | 典型场景 |
|---|---|---|---|---|
| 纯观看 | App、OBS、摄像机 | 只拉流播放 | HLS / HTTP-FLV / WebRTC | 活动直播、公开课、发布会 |
| 浏览器推流 | 主播自己的浏览器 | 采集 + 推流 + 本地预览 | WebRTC | 网页开播、远程面试、在线客服 |
| 双向连麦 | 主播 + 上麦观众 | 推流 + 同时拉多路流 | WebRTC + 混流 | 连麦直播、互动课堂 |
三条边界
- 传统 H5 直播页只拉流。 HLS 和 HTTP-FLV 都是单向分发协议,播放器没有上行通道。
- 浏览器推流默认 WebRTC 一条路。 不自建 WebRTC,就用封装了 WebRTC 能力的 SDK(比如ZEGO Express Web SDK)。
- RTMP 在 H5 里不能直接播。 Flash 已被主流浏览器彻底移除,RTMP 现在的角色是推流和服务端内部传输。
决策顺序
有没有主播端?
├─ 没有 → 纯观看:选 HLS / FLV / RTC 播放
└─ 有 → 主播在哪推流?
├─ App / OBS → H5 仍是纯观看
└─ 浏览器 → WebRTC 推流
└─ 观众要不要上麦?
├─ 不要 → 单路推流 + CDN 分发
└─ 要 → RTC 房间 + 混流
和 App 直播、小程序直播的对比
| 维度 | H5 直播 | App 直播 | 小程序直播 |
|---|---|---|---|
| 安装成本 | 无 | 需下载 | 需跳转授权 |
| 传播能力 | 最强,链接直达 | 弱 | 中 |
| 推流能力 | WebRTC,受浏览器限制 | 完整可控 | 受平台限制 |
| 延迟可控性 | 取决于协议 | 最强 | 中 |
| 后台播放 | 基本不可用 | 支持 | 支持 |
| 适合场景 | 活动、公开课、轻量带货 | 长期直播业务 | 微信生态内转化 |
2、协议选型:先定延迟预算,再定协议
选协议前,先问清自己的业务能容忍多少延迟。
五种协议对比
| 维度 | HLS | LL-HLS | HTTP-FLV | WebRTC | RTMP |
|---|---|---|---|---|---|
| 典型延迟 | 10s 以上(优化后 5–10s) | 2–5s | 1–3s | 0.2–1s | 1–3s |
| 首帧 | 较慢 | 中 | 快 | 最快 | — |
| iOS 播放 | 原生支持 | 需系统支持 | 无 MSE | √ | × |
| 安卓播放 | 需 hls.js | ⚠️ | √ MSE | √ | × |
| CDN 友好度 | 最高 | 高 | 中 | 低(需 SFU) | 低 |
| 实现成本 | 低 | 中 | 中 | 高 | 中 |
| 适合场景 | 大并发观看、回放 | 中低延迟观看 | 低延迟观看 | 连麦、强互动 | 推流入口 |
延迟为典型区间,实际受切片时长、GOP、播放器缓冲策略和网络状况影响,不同厂商口径存在差异。
延迟预算决策表
| 业务能容忍的延迟 | 选什么 | 代价 |
|---|---|---|
| < 1 秒 | WebRTC | 兼容性要求高、带宽成本高、需要 SFU 或 RTC 服务 |
| 1–3 秒 | HTTP-FLV(非 iOS)+ HLS 兜底 | 要做双协议,要处理延迟累积 |
| 3–10 秒 | LL-HLS 或优化后的 HLS | 需要服务端支持低延迟切片 |
| > 10 秒 | 标准 HLS | 兼容性最好,成本最低 |
多协议同源输出
成熟的做法不是一个端选一个协议,而是一条源流,多协议输出:
主播推流(RTMP / WebRTC)
↓
流媒体服务器 / RTC 服务
↓
┌────────┬─────────┬──────────┐
HLS HTTP-FLV WebRTC
(全平台) (安卓/桌面) (低延迟端)
服务端负责把同一路流转成多种格式,前端根据浏览器能力选择。这样既不用维护多套推流,也不会被单一协议的短板卡死。
3、观看端实现的方案
观看端有三条实现路径。 选一条主路,再准备一条备用路,不要只写一条。
| 方案 | 延迟 | 兼容性 | 依赖 | 适用 |
|---|---|---|---|---|
A. video + hls.js | 高 | 最好 | hls.js | 大并发、兼容优先 |
| B. flv.js / mpegts.js | 中 | 安卓/桌面 | MSE | 低延迟观看 |
| C. RTC SDK | 最低 | 现代浏览器 | SDK + 服务端 | 强互动、低延迟 |
以 RTC SDK(以ZEGO Express Web SDK为例):
安装:
npm install zego-express-engine-webrtc
完整拉流链路:
import { ZegoExpressEngine } from 'zego-express-engine-webrtc';
const appID = 123456789; // ZEGO 控制台获取
const server = 'YOUR_SERVER_ADDRESS'; // 控制台「项目信息」中的 Server 地址
const roomID = 'live_room_001';
const userID = 'viewer_' + Date.now();
const streamID = 'stream_001';
// Token 必须由业务服务端签发,前端只拿结果
const tokenRes = await fetch(`/api/live/token?roomID=${roomID}&userID=${userID}`);
const { token } = await tokenRes.json();
const zg = new ZegoExpressEngine(appID, server);
// 1. 能力检测:不支持 WebRTC 就不要继续
const support = await zg.checkSystemRequirements();
if (!support.webRTC) {
// 降级到 HLS
throw new Error('当前浏览器不支持 WebRTC');
}
// 2. 登录房间
const loginOK = await zg.loginRoom(
roomID,
token,
{ userID, userName: userID },
{ userUpdate: true }
);
if (!loginOK) throw new Error('登录房间失败');
// 3. 拉流并渲染
const remoteStream = await zg.startPlayingStream(streamID);
const remoteView = zg.createRemoteStreamView(remoteStream);
remoteView.play('remote-video', { enableAutoplayDialog: true });
// 4. 首帧回调
remoteView.on('canPlayVideo', () => {
console.log('首帧渲染完成');
});
// 5. 拉流状态
zg.on('playerStateUpdate', (result) => {
console.log('拉流状态变更', result);
});
4、推流端实现:浏览器开播的边界与代码
浏览器能推流,只在 WebRTC 路线上成立。 而且要同时满足四个条件:HTTPS、用户授权、iOS 14.3 以上、浏览器内核可用。
第一步:采集
let localStream;
try {
localStream = await navigator.mediaDevices.getUserMedia({
video: {
width: { ideal: 1280 },
height: { ideal: 720 },
frameRate: { ideal: 30 },
facingMode: 'user',
},
audio: {
echoCancellation: true,
noiseSuppression: true,
},
});
document.getElementById('preview').srcObject = localStream;
} catch (err) {
switch (err.name) {
case 'NotAllowedError':
// 用户拒绝授权,或页面不是 HTTPS
break;
case 'NotFoundError':
// 没有摄像头 / 麦克风
break;
case 'NotReadableError':
// 设备被其他程序占用
break;
case 'OverconstrainedError':
// 约束条件当前设备满足不了,降低分辨率重试
break;
}
}
第二步:推流(以 ZEGO RTC 为例)
// 创建本地流(节选)
const zegoLocalStream = await zg.createZegoStream();
// 推流
const publishOK = zg.startPublishingStream(streamID, zegoLocalStream);
// 监听推流状态
zg.on('publisherStateUpdate', (result) => {
if (result.state === 'PUBLISHING') {
console.log('推流成功');
}
});
什么时候需放弃 H5 推流
出现下面情况,建议不要在浏览器里硬做:
- 主播需要稳定的长时间开播(浏览器标签页会被降频、休眠)。
- 需要屏幕共享且用户在移动端。
- 用户主要在企业微信里打开。
- 需要美颜、滤镜、多机位等前处理能力。
- 推流并发规模大,且对失败率敏感。
这些场景应该改用 App 或 OBS 推流,H5 只承担观看。
5、兼容性:上线前必须验证的 5 个场景
H5 直播的线上事故,八成来自环境,不是代码。 上线前可过一遍:
场景 1:微信内置浏览器
微信的 WebView 内核和系统浏览器不是同一个。iOS 走 WKWebView,安卓走 X5 / XWeb。
- 拉流、推流都支持,屏幕共享不支持。
- 首次安装或清理数据后,内核可能还没下载完,此时采集会失败。等 Wi-Fi 下自动下载完成再试。
- 微信内无法通过配置放开自动播放限制,必须做用户手势兜底。
场景 2:企业微信内置浏览器
和微信不同:企业微信可以拉流,但不能推流,也不能屏幕共享。
如果产品同时投放微信和企业微信,要按 UA 分别判断,不能只判断是不是微信。
场景 3:iOS Safari
video默认会全屏接管,必须加playsinline和webkit-playsinline。- 低电量模式下,连静音自动播放都可能被禁止。
- iPhone 不支持 MSE,FLV 方案直接不可用。
场景 4:安卓 X5 内核接管视频
部分安卓浏览器(尤其 X5 内核)会用自己的播放器接管 video 标签,导致自定义控件、弹幕层、封面全部失效。
处理方式:
- 给
video加webkit-playsinline、x5-playsinline、x5-video-player-type="h5"。 - 仍被接管时,联系内核方为域名开白名单,或引导用户跳转系统浏览器。
上线前的检测代码
ZEGO Web SDK 提供了统一的能力检测,一次拿到所有关键项:
const result = await zg.checkSystemRequirements();
console.log(result);
// {
// webRTC: true,
// customCapture: true,
// camera: true,
// microphone: true,
// videoCodec: { H264: true, H265: false, VP8: true, VP9: true },
// screenSharing: true,
// errInfo: {}
// }
用法: 页面初始化时先跑一次,把结果存进全局状态,后续所有功能入口按它来显隐——不支持推流就不显示「开播」按钮,不支持屏幕共享就不显示「共享屏幕」。
六、自建还是买:三条路线的成本结构
决定成本的不是自建还是买,是并发数 × 码率 × 时长。 先算带宽,再谈路线。
先算带宽
所需出口带宽(Mbps) ≈ 并发观看数 × 单路平均码率(Mbps) × 冗余系数
冗余系数一般取 1.2–1.5,用于覆盖峰值波动和协议开销。
举例:1000 人同时看 720p、平均码率 2 Mbps 的流,理论出口带宽约 2000 Mbps,加 1.3 的冗余系数就是 2.6 Gbps。这个量级已经不可能靠单台服务器扛,必须上 CDN。
三条路线
| 维度 | 自建(SRS / ZLMediaKit) | 云直播 CDN | RTC 厂商 |
|---|---|---|---|
| 前期投入 | 高(服务器、带宽、部署) | 低 | 低 |
| 运维负担 | 高,需要专人 | 低 | 低 |
| 延迟能力 | 可做到 FLV 级,WebRTC 需自己搭 | 中 | 最低 |
| 弹性扩容 | 差,要提前采购 | 好 | 好 |
| 适合规模 | 稳定大流量、有强合规要求 | 大多数业务 | 强互动业务 |
| 主要风险 | 带宽成本和故障自担 | 厂商绑定 | 厂商绑定、单价较高 |
判断线
- 日活较低、没有专职音视频运维:可直接用云服务,自建的人力成本远高于节省的流量费。
- 流量稳定且规模大、有合规或私有化要求:自建源站 + 外采 CDN,把可控性和弹性分开。
- 延迟要求低于 1 秒:不要在自建上纠结,直接选 RTC 厂商。
常见问题
H5 可以推流吗?
可以,但只能走 WebRTC。浏览器用 getUserMedia 采集后推流,要求 HTTPS、用户授权、iOS 14.3 以上,企业微信内置浏览器不支持推流。
H5 直播延迟一般是多少?
取决于协议。HLS 通常 10 秒以上,HTTP-FLV 约 1 到 3 秒,WebRTC 可低于 1 秒。要 1 秒内只能选 WebRTC,代价是兼容性和成本。
H5 直播一定要用 HTTPS 吗?
推流必须,纯播放不强制。浏览器只在 HTTPS 等安全上下文开放 getUserMedia,HTTP 页面采不到摄像头。HLS 或 FLV 拉流走 HTTP 也能工作。
H5 直播在 iPhone 上为什么播不了 FLV?
iPhone 的 Safari 不支持 MSE,而 flv.js 依赖 MSE 转封装 FLV。iOS 只能播原生 HLS 的 m3u8,或改用 WebRTC,所以必须做双协议。
H5 直播和 App 直播有什么区别?
H5 免安装、传播快、成本低,但推流和低延迟受浏览器限制。App 能控制采集与缓冲,延迟更可控。延迟高低主要由协议决定,与 H5 或 App 无关。




