徐旺的个人博客

一个 9.8 年开发经验即将被AI取代的前端牛马,热爱开源,喜欢分享

H.265 HLS 直播流播放器

文章
多品牌摄像头 H.265 编码 → 浏览器直接播放,商用免费,无需插件

目录


快速开始

安装依赖

pnpm add hls.js @ffmpeg/ffmpeg @ffmpeg/util antd @ant-design/icons

启动服务

npx next dev -p 3004
# 访问 http://localhost:3004/h265-hls-player

快速测试

播放器内置了公共测试流,点击标签即可一键加载:

| 测试流 | 地址 | 说明 | |--------|------|------| | Mux Test | https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8 | Mux 官方测试流 | | Apple Sample | https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8 | Apple 官方 HLS 样例 |


技术架构

整体链路

┌─────────────┐     HLS (.m3u8)      ┌──────────────────────────────┐
│  摄像头      │ ──────────────────► │        浏览器               │
│  (H.265)    │                     │                              │
│  海康/大华   │                     │  ┌────────────────────────┐ │
│  宇视/华为   │                     │  │  自动能力检测            │ │
└─────────────┘                     │  │                         │ │
                                     │  │  ├─ WebCodecs (优先)   │ │
                                     │  │  │  H.265 硬件直解       │ │
                                     │  │  │  Chrome 107+        │ │
                                     │  │  ├─ Native HLS        │ │
                                     │  │  │  Safari 16.4+       │ │
                                     │  │  └─ FFmpeg.wasm (兜底) │ │
                                     │  │     H.265→H.264 软件   │ │
                                     │  └────────────────────────┘ │
                                     │             │                │
                                     │             ▼                │
                                     │  ┌────────────────────────┐  │
                                     │  │  MediaSource Extension │  │
                                     │  │  → HTML5 <video>       │  │
                                     │  └────────────────────────┘  │
                                     └──────────────────────────────┘

三层解码策略

| 优先级 | 解码方式 | 触发浏览器 | 实时性 | 商用 | |:------:|---------|-----------|:------:|:----:| | 🥇 1 | WebCodecs (硬件解码) | Chrome 107+ (Win/macOS + HEVC 硬件) | ✅ 实时 | ✅ 免费 | | 🥈 2 | Native HLS (原生支持) | Safari 16.4+ | ✅ 实时 | ✅ 免费 | | 🥉 3 | FFmpeg.wasm (软件转码) | 所有现代浏览器 | ⚠️ 见限制 | ✅ LGPL |

浏览器自动检测并选择最优解码路径,无需手动配置。

组件清单

| 文件 | 说明 | |------|------| | components/H265HlsPlayer.tsx | 核心播放器组件 | | pages/h265-hls-player.tsx | 独立演示页面 | | pages/h265-player.tsx | H.265 文件转码播放器 | | pages/hls-stream.tsx | 通用 HLS 流播放器 |


部署指南

Next.js 配置

播放器需要 SharedArrayBuffer 支持,必须在 next.config.js 中添加 COOP/COEP 响应头:

// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          { key: 'Cross-Origin-Opener-Policy', value: 'same-origin' },
          { key: 'Cross-Origin-Embedder-Policy', value: 'require-corp' },
        ],
      },
    ];
  },
};

重启开发服务器后生效(npm run dev)。

生产环境 CORS

流媒体服务器必须返回正确的 CORS 头:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Range, Content-Type

HTTPS 要求

FFmpeg.wasm 的 SharedArrayBuffer 需要 HTTPSlocalhost,生产环境必须使用 HTTPS。


API 参考

H265HlsPlayer

import H265HlsPlayer from '@/components/H265HlsPlayer';

// 基础用法
<H265HlsPlayer />

// 传入默认 URL
<H265HlsPlayer defaultUrl="https://your-camera/stream.m3u8" />

属性

| 属性 | 类型 | 默认值 | 说明 | |------|------|--------|------| | defaultUrl | string | '' | 默认加载的 HLS URL |

回调

<H265HlsPlayer
  onStreamLoaded={(url) => console.log('Stream loaded:', url)}
  onError={(err) => console.error('Stream error:', err)}
/>

next.config.js 配置(完整版)

/** @type {import('next').NextConfig} */
module.exports = {
  async headers() {
    return [
      {
        // 匹配所有页面
        source: '/(.*)',
        headers: [
          // COEP: 启用跨域隔离,SharedArrayBuffer 才可用
          { key: 'Cross-Origin-Embedder-Policy', value: 'require-corp' },
          // COOP: 防止跨域窗口通信问题
          { key: 'Cross-Origin-Opener-Policy', value: 'same-origin' },
          // CORS: HLS 流跨域访问
          { key: 'Access-Control-Allow-Origin', value: '*' },
          { key: 'Access-Control-Allow-Methods', value: 'GET, OPTIONS' },
          { key: 'Access-Control-Allow-Headers', value: 'Range, Content-Type' },
        ],
      },
    ];
  },
};

许可说明

| 组件 | 许可 | 商用 | 链接 | |------|------|:----:|------| | FFmpeg.wasm | LGPL 2.1+ | ✅ | https://github.com/ffmpegwasm/ffmpeg.wasm | | hls.js | BSD 2-Clause | ✅ | https://github.com/video-dev/hls.js | | WebCodecs API | W3C | ✅ | https://www.w3.org/TR/webcodecs/ | | H.264 解码器 (浏览器内置) | MPEG LA | ✅ | 仅解码器免费,不含编码器 |

完整许可链

FFmpeg.wasm 核心 (LGPL 2.1+) ──免费──► ffmpeg.wasm-core.wasm
                                              │
                                              ▼ libx264 (GPL) ──► 仅用户本地使用,分发无需 GPL
                                              │
                                              ▼
                                         最终输出 H.264 (浏览器解码器免费)

说明:ffmpeg.wasm 自带的 libx264 是 GPL 版本,但最终产物 H.264 视频流通过浏览器的 MPEG LA 免费解码器播放,不构成 GPL 分发。个人项目和 SaaS 内部使用完全合规。商业产品如需更严格合规,可使用 LGPL 版或换用 VP9 编码器。


已知限制

FFmpeg.wasm 软件解码性能

| 分辨率 | 帧率 | 推荐等级 | 说明 | |--------|------|:--------:|------| | 720p | 25fps | ✅ 推荐 | 软件解码基本流畅 | | 1080p | 25fps | ⚠️ 可用 | 可能需要降低帧率或画质 | | 4MP+ | 25fps | ❌ 不推荐 | 超出软件解码能力 | | 4K | - | ❌ 不可用 | 无实用价值 |

解决建议:搭配服务端转码(见 RTSP 摄像头方案).

浏览器兼容性

| 浏览器 | H.265 HLS 支持 | 推荐程度 | |--------|--------------|:--------:| | Chrome 107+ (Win + HEVC 硬件) | ✅ WebCodecs | ⭐⭐⭐⭐⭐ | | Safari 16.4+ | ✅ Native HLS | ⭐⭐⭐⭐⭐ | | Chrome (无 HEVC 扩展) | ⚠️ FFmpeg.wasm | ⭐⭐⭐ | | Firefox | ⚠️ FFmpeg.wasm | ⭐⭐ | | Edge (Chromium) | ⚠️ FFmpeg.wasm | ⭐⭐⭐ | | 移动端浏览器 | ⚠️ 表现不一 | ⚠️ |


FAQ

Q: 摄像头只输出 RTSP,不支持 HLS,怎么处理?

需要服务端将 RTSP 转换为 HLS。推荐使用 go2rtc(MIT 协议,商用免费):

# 单流转发
go2rtc --static "cam1:rtsp://user:pass@192.168.1.100:554/1"

# Docker 快速部署
docker run -it --rm \
  -p 1984:1984 \
  -v ./go2rtc.yaml:/config/go2rtc.yaml \
  alexxit/go2rtc

# 浏览器访问
http://localhost:1984/live/cam1.m3u8

go2rtc.yaml 配置示例:

streams:
  cam1:
    - rtsp://admin:admin123@192.168.1.100:554/1
  cam2:
    - rtsp://admin:admin123@192.168.1.101:554/1

Q: 支持多少个摄像头同时播放?

取决于设备性能。实测参考:

  • 4 通道 720p 同时播放:普通 PC 可行
  • 4 通道 1080p 同时播放:建议 RTX 3060+ 或使用 go2rtc 服务端转码
  • 多画面监控墙:推荐 go2rtc + HLS,降低浏览器负担

Q: 画面延迟有多高?

| 方案 | 理论延迟 | 说明 | |------|:--------:|------| | WebCodecs (硬件) | 100-500ms | 最优 | | Native HLS (Safari) | 1-3s | 取决于 HLS 切片大小 | | FFmpeg.wasm + MSE | 3-10s | 依赖转码速度 | | 服务端 go2rtc HLS | 1-5s | 取决于服务端配置 |

低延迟需求:使用 go2rtc 的 WebRTC 模式,可达 200-500ms。

Q: 如何集成到现有项目?

// 1. 复制组件到你的项目
// 2. 安装依赖
pnpm add hls.js @ffmpeg/ffmpeg @ffmpeg/util

// 3. 添加 next.config.js COEP/COOP 配置(见上文)

// 4. 页面中使用
import H265HlsPlayer from '@/components/H265HlsPlayer';

export default function CameraPage() {
  return (
    <div>
      <H265HlsPlayer defaultUrl="https://your-camera/stream.m3u8" />
    </div>
  );
}

Q: 画面出现花屏或卡顿怎么办?

  1. FFmpeg.wasm 模式下:降低摄像头编码的分辨率或帧率
  2. 网络问题:检查网络带宽是否充足
  3. 浏览器兼容性:Chrome 切换到 Safari 或使用 go2rtc 服务端方案
  4. 摄像头码率过高:建议摄像头码率设置在 2-4 Mbps

Q: 可以在微信小程序中使用吗?

❌ 不可以。小程序 webview 不支持 FFmpeg.wasm 和 WebCodecs API。

替代方案

  • 使用摄像头厂商的微信小程序 SDK
  • 或使用 go2rtc → WebRTC → 微信小程序 webview(需要企业认证)

更新日志

| 版本 | 日期 | 变更 | |------|------|------| | v1.0 | 2024-02-13 | 初始版本,支持 WebCodecs / Native HLS / FFmpeg.wasm 三层解码 |

评论