前端实现实现视频播放的方案和面试问题

作为 Web 前端工程师,视频播放是高频且核心的业务场景之一,涉及原生 API、播放器封装、兼容性、性能优化、高级功能 等多个维度。以下从「基础技术层」「核心实现方案」「进阶功能」「性能与兼容」四个层面,系统拆解视频播放的技术体系和落地方式。

一、核心基础技术:Web 视频播放的底层支撑

首先要明确 Web 端视频播放的核心技术底座,所有播放器都是基于这些基础能力封装而来。

1. HTML5 原生<video>标签(最基础)

HTML5 推出的<video>标签是 Web 视频播放的基石,无需插件(如 Flash),原生支持视频渲染,是所有前端视频播放的起点。

  • 核心属性(必掌握):

    属性 作用
    src 视频资源地址(支持本地 / 远程 URL,或通过<source>指定多格式)
    controls 显示浏览器原生控制栏(播放 / 暂停、进度、音量、全屏等)
    autoplay 自动播放(需满足浏览器静音策略:muted+autoplay才会生效)
    muted 静音播放
    loop 循环播放
    poster 视频封面图(播放前显示)
    preload 预加载策略:none(不预加载)/metadata(仅预加载元信息)/auto(全量)
    playsinline 移动端内联播放(避免自动全屏,适配 H5 页面)
  • 最简实现示例

    <video
    id="videoPlayer"
    src="./video.mp4"
    controls
    poster="./cover.jpg"
    playsinline
    width="640"

    复制代码
    <!-- 降级提示:浏览器不支持video标签时显示 -->
    您的浏览器不支持HTML5视频播放,请升级浏览器
2. 视频编码与格式(兼容性关键)

前端必须关注视频格式,不同浏览器 / 设备对编码的支持差异极大,核心兼容方案是「多格式适配」。

  • 主流格式对比

    格式 编码 浏览器支持 适用场景
    MP4 H.264/AAC 所有现代浏览器(IE9+) 通用场景(PC / 移动端)
    WebM VP9/Opus Chrome/Firefox/Edge 开源免费,体积更小(无版权)
    Ogg Theora/Vorbis Firefox/Chrome(几乎不用) 小众场景
  • 多格式适配实现 (通过<source>标签):

注:type属性中指定codecs能让浏览器更快判断是否支持该格式,提升加载效率。

3. Media API(原生 JS 控制)

<video>标签暴露了完整的 JavaScript API,用于自定义播放逻辑(替代原生控制栏),核心 API 分为「属性、方法、事件」三类。

(1)核心方法(主动控制)
复制代码
const video = document.getElementById('videoPlayer');
// 播放/暂停
video.play(); // 返回Promise(需处理异步,如自动播放失败)
video.pause();
// 跳转进度
video.currentTime = 60; // 跳转到60秒处
// 音量控制(0-1)
video.volume = 0.5;
// 全屏(需兼容)
if (video.requestFullscreen) {
  video.requestFullscreen();
} else if (video.webkitRequestFullscreen) { // 移动端webkit内核
  video.webkitRequestFullscreen();
}
(2)核心事件(监听状态)
复制代码
// 播放状态变化(播放/暂停)
video.addEventListener('play', () => console.log('开始播放'));
video.addEventListener('pause', () => console.log('暂停播放'));
// 进度更新(每秒触发4-6次)
video.addEventListener('timeupdate', () => {
  console.log('当前进度:', video.currentTime, '/', video.duration);
});
// 加载完成(元信息加载完毕,可获取duration)
video.addEventListener('loadedmetadata', () => {
  console.log('视频时长:', video.duration);
});
// 播放结束
video.addEventListener('ended', () => {
  console.log('播放完成');
  // 循环播放:重新播放
  video.play();
});
// 加载失败
video.addEventListener('error', () => {
  console.log('播放失败:', video.error);
});

二、实际业务场景:核心实现方案

原生<video>仅满足基础播放,实际业务中需解决「自定义控制栏、倍速播放、断点续播、流媒体播放」等问题,以下是高频场景的实现方式。

场景 1:自定义视频控制栏(替代原生 controls)

原生控制栏样式不可定制,业务中通常隐藏原生控件,自己实现 UI + 逻辑。

复制代码
<!-- 容器:视频 + 自定义控制栏 -->
<div class="video-container" style="position: relative; width: 640px;">
  <video 
    id="customVideo"
    src="./video.mp4" 
    playsinline
    style="width: 100%;"
  ></video>
  <!-- 自定义控制栏(默认隐藏,hover显示) -->
  <div class="video-controls" style="position: absolute; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,0.5); color: #fff; padding: 10px; display: none;">
    <button id="playBtn">播放/暂停</button>
    <input id="progressBar" type="range" min="0" max="100" value="0">
    <button id="fullscreenBtn">全屏</button>
    <select id="speedSelect">
      <option value="0.5">0.5倍</option>
      <option value="1" selected>1倍</option>
      <option value="1.5">1.5倍</option>
      <option value="2">2倍</option>
    </select>
  </div>
</div>

<script>
const video = document.getElementById('customVideo');
const controls = document.querySelector('.video-controls');
const playBtn = document.getElementById('playBtn');
const progressBar = document.getElementById('progressBar');
const fullscreenBtn = document.getElementById('fullscreenBtn');
const speedSelect = document.getElementById('speedSelect');

// 1. 显示/隐藏控制栏
video.addEventListener('mouseenter', () => controls.style.display = 'block');
video.addEventListener('mouseleave', () => controls.style.display = 'none');

// 2. 播放/暂停逻辑
playBtn.addEventListener('click', async () => {
  if (video.paused) {
    try {
      await video.play(); // 处理自动播放权限问题
    } catch (e) {
      alert('播放失败,请手动点击播放');
    }
  } else {
    video.pause();
  }
});

// 3. 进度条同步与控制
// 进度更新时同步进度条
video.addEventListener('timeupdate', () => {
  const progress = (video.currentTime / video.duration) * 100;
  progressBar.value = progress;
});
// 拖动进度条跳转播放位置
progressBar.addEventListener('input', () => {
  const pos = (progressBar.value / 100) * video.duration;
  video.currentTime = pos;
});

// 4. 倍速播放
speedSelect.addEventListener('change', () => {
  video.playbackRate = speedSelect.value; // 原生支持0.5-2倍速
});

// 5. 全屏控制
fullscreenBtn.addEventListener('click', () => {
  if (video.requestFullscreen) {
    video.requestFullscreen();
  } else if (video.webkitRequestFullscreen) {
    video.webkitRequestFullscreen();
  }
});
</script>
场景 2:断点续播(记住上次播放位置)

利用localStorage存储播放进度,下次打开时自动跳转。

复制代码
const video = document.getElementById('customVideo');
const VIDEO_KEY = 'video_progress_' + video.src; // 唯一标识

// 页面加载时恢复进度
window.addEventListener('load', () => {
  const savedProgress = localStorage.getItem(VIDEO_KEY);
  if (savedProgress) {
    video.currentTime = Number(savedProgress);
  }
});

// 进度更新时保存(节流,避免频繁存储)
let timer = null;
video.addEventListener('timeupdate', () => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    localStorage.setItem(VIDEO_KEY, video.currentTime);
  }, 1000);
});

// 播放结束时清空进度(可选)
video.addEventListener('ended', () => {
  localStorage.removeItem(VIDEO_KEY);
});
场景 3:流媒体播放(HLS/FLV,大文件 / 直播)

普通 MP4 是「完整文件播放」,直播 / 大视频需流媒体(边下载边播放),前端主流方案:

  • HLS(HTTP Live Streaming):苹果推出,基于 TS 切片,移动端兼容好(M3U8 格式)。
  • FLV:基于 HTTP 的流式传输,适合直播,体积小。

实现方式:原生<video>不支持 HLS/FLV,需借助第三方库(如hls.jsflv.js)。

(1)HLS 播放(hls.js)
复制代码
<video id="hlsVideo" controls playsinline></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
const video = document.getElementById('hlsVideo');
const hlsUrl = 'https://example.com/stream.m3u8'; // HLS地址

if (Hls.isSupported()) { // 检测浏览器是否支持
  const hls = new Hls();
  hls.loadSource(hlsUrl);
  hls.attachMedia(video);
  hls.on(Hls.Events.MANIFEST_PARSED, () => {
    video.play(); // 解析完成后播放
  });
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
  // 移动端Safari原生支持HLS,无需库
  video.src = hlsUrl;
  video.addEventListener('loadedmetadata', () => {
    video.play();
  });
}
</script>
(2)FLV 播放(flv.js)
复制代码
<video id="flvVideo" controls playsinline></video>
<script src="https://cdn.jsdelivr.net/npm/flv.js@latest/dist/flv.min.js"></script>
<script>
const video = document.getElementById('flvVideo');
const flvUrl = 'https://example.com/stream.flv'; // FLV地址

if (flvjs.isSupported()) {
  const flvPlayer = flvjs.createPlayer({
    type: 'flv',
    url: flvUrl
  });
  flvPlayer.attachMediaElement(video);
  flvPlayer.load();
  flvPlayer.play();
}
</script>
场景 4:视频封面优化(预加载 / 懒加载)
  • 封面加载时机poster属性是静态封面,若需动态封面(如视频第一帧),可在视频加载后截取:

    video.addEventListener('loadeddata', () => {
    // 视频加载第一帧后,隐藏poster,显示视频帧
    video.poster = '';
    });

  • 懒加载:非首屏视频延迟加载,减少首屏资源消耗:

    <video
    id="lazyVideo"
    data-src="./video.mp4"
    controls
    playsinline

    <script> // 监听滚动,进入视口后加载 const lazyVideo = document.getElementById('lazyVideo'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { lazyVideo.src = lazyVideo.dataset.src; observer.unobserve(lazyVideo); } }); }); observer.observe(lazyVideo); </script>

三、进阶功能:提升用户体验

1. 倍速播放(原生支持)
复制代码
// 设置倍速(0.5/1/1.5/2是主流)
video.playbackRate = 1.5;
// 获取当前倍速
console.log(video.playbackRate);
2. 画中画(Picture-in-Picture)

PC 端 Chrome/Firefox、移动端部分浏览器支持,实现悬浮小窗播放:

复制代码
const pipBtn = document.getElementById('pipBtn');
// 检测是否支持画中画
if ('pictureInPictureEnabled' in document) {
  pipBtn.addEventListener('click', async () => {
    if (video !== document.pictureInPictureElement) {
      await video.requestPictureInPicture();
    } else {
      await document.exitPictureInPicture();
    }
  });
} else {
  pipBtn.disabled = true; // 不支持则禁用按钮
}
3. 预加载优化

通过preload属性控制预加载策略,结合canplay事件触发播放:

复制代码
// 仅预加载元信息,用户点击播放后再加载视频
video.preload = 'metadata';
// 当视频可播放(加载足够数据)时提示
video.addEventListener('canplay', () => {
  console.log('视频可开始播放');
});

四、性能与兼容性:避坑指南

1. 兼容性问题
问题场景 解决方案
移动端自动播放失败 muted属性 + 用户交互后(如 click)再播放;避免纯自动播放
iOS 视频自动全屏 playsinline属性;X5 内核需额外配置:x5-video-player-type="h5"
不同浏览器格式兼容 提供 MP4(H.264)+ WebM 双格式;优先 MP4
全屏 API 兼容 封装兼容函数(requestFullscreen/webkitRequestFullscreen/mozRequestFullscreen)
2. 性能优化
  • 视频压缩:使用 H.265 编码(比 H.264 体积小 50%),或适配不同分辨率(480p/720p/1080p);
  • 懒加载:非首屏视频延迟加载,减少初始加载时间;
  • 节流监听timeupdate事件节流(如 1 秒一次),避免频繁 DOM 操作;
  • 资源 CDN:视频文件部署到 CDN,开启 Gzip/Brotli 压缩,提升加载速度;
  • 预加载控制 :根据网络状态调整preload(弱网设为none)。
3. 错误处理
复制代码
video.addEventListener('error', () => {
  const error = video.error;
  switch (error.code) {
    case MediaError.MEDIA_ERR_ABORTED: // 用户终止加载
      console.log('视频加载被终止');
      break;
    case MediaError.MEDIA_ERR_NETWORK: // 网络错误
      console.log('网络异常,视频加载失败');
      // 重试逻辑:刷新视频src
      setTimeout(() => {
        video.src = video.src;
        video.load();
      }, 3000);
      break;
    case MediaError.MEDIA_ERR_DECODE: // 解码失败(格式不支持)
      console.log('视频格式不支持,解码失败');
      break;
    case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED: // 资源地址无效
      console.log('视频地址无效');
      break;
  }
});

五、成熟播放器库(避免重复造轮子)

如果业务需求复杂(如弹幕、倍速、清晰度切换、直播连麦),直接使用成熟库更高效:

库名 特点 适用场景
Video.js 开源、跨浏览器、支持 HLS/FLV(需插件)、自定义插件丰富 通用场景(点播 / 简单直播)
Plyr 轻量、美观、易定制、支持 HTML5/HLS 轻量级自定义播放器
TCPlayer 腾讯云出品,支持 FLV/HLS/MP4、直播 / 点播、弹幕、画质切换 国内业务(适配 X5 内核)
AliPlayer 阿里云出品,功能全,支持加密播放、直播回放 阿里云生态业务

为什么要使用hls和flv?

在 Web 端视频场景中选择 HLS 或 FLV,核心是解决原生<video>标签的局限性,适配不同业务场景的需求(如直播 / 点播、低延迟 / 兼容性),同时兼顾性能、兼容性和用户体验。

一、先明确:原生<video>的短板(为什么需要 HLS/FLV)

Web 原生<video>标签仅支持 MP4、WebM 等静态封装格式,无法满足复杂视频场景的核心需求:

  1. 直播场景:MP4 是完整文件,无法 "实时流式播放",而直播需要边推流边播放;
  2. 自适应码率:不同网络(4G/5G/WiFi)下,MP4 无法动态切换清晰度,易出现卡顿 / 加载慢;
  3. 低延迟需求:原生 MP4 播放需先缓冲部分数据,直播延迟可达数十秒,无法满足电商直播、赛事等低延迟场景;
  4. 大文件点播:GB 级的长视频(如电影)若用 MP4,首次加载需等待大量缓冲,用户体验差。

HLS 和 FLV 正是为解决这些痛点而生 ------ 本质是适配流媒体传输的协议 / 格式,让 Web 端能高效、灵活地播放视频。

二、使用 HLS 的核心原因(适配 "通用、兼容、自适应" 场景)

HLS(HTTP Live Streaming)是目前最主流的流媒体协议,核心价值体现在:

1. 跨端兼容性拉满(Web / 移动端 / 智能设备)
  • 原生支持:Safari(桌面 + iOS)、Android 原生浏览器直接支持 HLS(m3u8),无需额外插件;
  • 全端适配:非 Safari 浏览器(Chrome/Firefox)可通过hls.js解析,覆盖 99% 以上的 Web 场景;
  • 设备兼容:智能电视、机顶盒、游戏机等终端均支持 HLS,是跨端视频的 "通用解"。
2. 自适应码率(ABR)------ 解决 "网络波动导致的卡顿"

HLS 将视频切割为 2~10 秒的 TS 小切片,并生成包含不同码率(360p/720p/1080p)的 m3u8 索引文件:

  • 播放器可实时检测网络速度(如通过切片下载耗时),自动切换对应码率;
  • 弱网时降级为低清晰度(如 360p)保证播放流畅,网络恢复后切回高清,无需用户手动操作。
3. 适配 "点播 + 非低延迟直播" 的通用场景
  • 点播:大文件视频切片后,支持 "边下载边播放",首次加载仅需下载首个切片(2~5 秒),无需等待完整文件;
  • 直播:虽然原生 HLS 延迟 10~30 秒,但通过 "低延迟 HLS(LL-HLS)" 可将延迟降至 3~5 秒,满足大多数直播场景(如教育直播、新闻直播)。
4. 基于 HTTP 传输 ------ 部署 / 运维成本低

HLS 基于标准 HTTP/HTTPS 协议,无需搭建专用流媒体服务器(如 RTMP):

  • 可直接部署到 CDN(阿里云 / 腾讯云等均支持 HLS 加速),降低带宽成本;
  • 穿透防火墙 / 代理:HTTP 是通用协议,避免 RTMP 等专用协议被拦截的问题;
  • 断点续传:切片传输天然支持断点续传,播放中断后恢复无需重新加载全部数据。

三、使用 FLV 的核心原因(适配 "低延迟、高性能直播" 场景)

FLV(Flash Video)虽因 Flash 衰落一度式微,但基于flv.js(纯 JS 解析)重生,核心价值是低延迟 + 高性能

1. 极致低延迟(1~3 秒)------ 秒杀原生 HLS

FLV 采用 "流式传输"(无切片,连续字节流),结合 HTTP-FLV/WS-FLV 协议:

  • 直播延迟可控制在 1~3 秒,是电商直播、直播带货、赛事直播的首选(这类场景对互动性要求极高,延迟 > 5 秒会影响用户体验);
  • 对比:原生 HLS 延迟 10~30 秒,即使 LL-HLS 也仅能降到 3~5 秒,FLV 在低延迟场景无可替代。
2. 解析性能高 ------ 轻量且高效

FLV 格式结构简单,flv.js解析时无需复杂的切片管理,CPU / 内存占用低于 HLS:

  • 适合移动端 / 低配设备:在中低端手机上播放 FLV 直播,卡顿概率低于 HLS;
  • 实时性强:流数据到达后可立即解析播放,无需等待切片完整,进一步降低延迟。
3. 兼容 RTMP 推流生态

直播行业早期以 RTMP 协议为主(主播推流、服务端转码),FLV 可直接对接 RTMP 生态:

  • 服务端将 RTMP 流转换为 HTTP-FLV 流,无需额外转码为 HLS 切片,降低服务器压力;
  • 成熟的开源方案(如 SRS/FFmpeg)支持 RTMP→FLV 的实时转换,部署成本低。

四、HLS vs FLV:什么时候选哪个?

业务场景 优先选 HLS 优先选 FLV
点播(电影 / 剧集 / 课程) ✅ 自适应码率 + 跨端兼容 ❌ 无切片,大文件加载慢
低延迟直播(电商 / 赛事) ❌ 延迟高(LL-HLS 也仅 3~5 秒) ✅ 1~3 秒延迟,互动性强
通用直播(教育 / 新闻) ✅ 兼容性好,无需极致低延迟 ❌ 移动端部分浏览器兼容略差
跨端适配(PC + 移动端 + TV) ✅ 全端支持,无需额外适配 ❌ TV / 部分 iOS 浏览器兼容差
弱网环境 ✅ 自动降级码率,播放更稳定 ❌ 无自适应码率,易卡顿

如何实现直播?

方案 延迟 兼容性 适合场景 核心依赖
FLV(推荐) 1~3 秒(低) 大部分浏览器 电商直播、赛事、带货 flv.js
HLS 10~30 秒 全端兼容 教育直播、新闻直播 hls.js
直播方案 后端给的 URL 示例 核心特点
FLV https://live.example.com/room/666.flv 后缀是.flv,基于 HTTP-FLV 协议
HLS https://live.example.com/room/666.m3u8 后缀是.m3u8,切片索引文件

优先选 FLV(直播核心需求是低延迟)

第二步:FLV 直播前端实现

前置准备
  1. 先安装依赖:flv.js 是纯 JS 写的 FLV 解析库,无需后端配合,前端直接用

    复制代码
    # npm安装(推荐)
    npm install flv.js --save
    # 或直接引入CDN(不想装npm的话)
    <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.min.js"></script>
  2. 找一个测试用的 FLV 直播流(开发中后端给的也是可直接播放的直播流 URL 地址 ):http://pullhls3.a.yximgs.com/upic/2024/01/01/12/BMjAyNDAxMDEwOTUzNDFfNzg5Nzc2MDlfMzcwNzY0ODk0MF8xXzM=_HD.flv

核心代码(HTML+JS)
复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>FLV直播播放</title>
    <!-- 样式:简单做个播放器容器 -->
    <style>
        #live-player {
            width: 800px;
            height: 450px;
            border: 1px solid #ccc;
            margin: 20px auto;
            background: #000;
        }
        .control {
            text-align: center;
            margin: 10px 0;
        }
        button {
            padding: 8px 16px;
            margin: 0 5px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <!-- 1. 视频播放容器 -->
    <video id="live-player" controls autoplay muted></video>
    <!-- 2. 控制按钮(播放/暂停/重连) -->
    <div class="control">
        <button id="play-btn">播放</button>
        <button id="pause-btn">暂停</button>
        <button id="reconnect-btn">重新连接</button>
    </div>

    <!-- 引入flv.js(CDN方式,不用npm的话) -->
    <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.min.js"></script>
    <script>
        // 核心变量
        const videoElement = document.getElementById('live-player');
        let flvPlayer = null; // FLV播放器实例
        // 你的直播流地址(替换成自己的!)
        const liveFlvUrl = 'http://pullhls3.a.yximgs.com/upic/2024/01/01/12/BMjAyNDAxMDEwOTUzNDFfNzg5Nzc2MDlfMzcwNzY0ODk0MF8xXzM=_HD.flv';

        // 初始化FLV播放器
        function initFlvPlayer() {
            // 先判断浏览器是否支持
            if (flvjs.isSupported()) {
                // 创建播放器实例
                flvPlayer = flvjs.createPlayer({
                    type: 'flv', // 流类型
                    url: liveFlvUrl, // 直播流地址
                    isLive: true, // 标记为直播(关键!优化直播播放逻辑)
                    hasAudio: true, // 有音频
                    hasVideo: true, // 有视频
                    enableStashBuffer: false // 关闭缓存(降低直播延迟)
                });
                // 将播放器挂载到video标签
                flvPlayer.attachMediaElement(videoElement);
                // 加载流
                flvPlayer.load();
                // 自动播放(注意:浏览器要求需用户交互后才能播放音频,所以先静音)
                flvPlayer.play().catch(err => {
                    console.log('自动播放失败(浏览器限制),点击播放器后可播放', err);
                });

                // 监听错误(关键!断流后自动重连)
                flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
                    console.error('直播出错:', errType, errDetail);
                    // 销毁错误的播放器
                    if (flvPlayer) {
                        flvPlayer.destroy();
                        flvPlayer = null;
                    }
                    // 3秒后自动重连
                    setTimeout(() => {
                        initFlvPlayer();
                    }, 3000);
                });

                // 监听播放状态
                flvPlayer.on(flvjs.Events.PLAYING, () => {
                    console.log('直播播放中');
                });
            } else {
                alert('你的浏览器不支持FLV直播,请更换Chrome/Firefox!');
            }
        }

        // 按钮事件绑定
        document.getElementById('play-btn').addEventListener('click', () => {
            if (flvPlayer) flvPlayer.play();
            videoElement.muted = false; // 取消静音
        });
        document.getElementById('pause-btn').addEventListener('click', () => {
            if (flvPlayer) flvPlayer.pause();
        });
        document.getElementById('reconnect-btn').addEventListener('click', () => {
            if (flvPlayer) {
                flvPlayer.destroy();
                flvPlayer = null;
            }
            initFlvPlayer();
        });

        // 页面加载时初始化
        window.onload = () => {
            initFlvPlayer();
        };

        // 页面关闭时销毁播放器(避免内存泄漏)
        window.onbeforeunload = () => {
            if (flvPlayer) {
                flvPlayer.destroy();
                flvPlayer = null;
            }
        };
    </script>
</body>
</html>
代码说明(重点)
  1. isLive: true:必须设为 true,告诉播放器这是直播,优化缓存逻辑,降低延迟;
  2. enableStashBuffer: false:关闭缓存,直播流来了就播,进一步降低延迟;
  3. 错误监听 + 自动重连:直播最容易断流(网络波动、服务端推流中断),必须加这个逻辑 ;
  4. 静音自动播放:浏览器规定 "非用户交互的自动播放只能静音",所以先静音,用户点击播放按钮后再取消静音。

第三步:HLS 直播方案(兼容优先时用)

如果你的直播对延迟要求不高(比如教育直播),用 HLS 更兼容(比如 iOS Safari 原生支持),代码几乎和 FLV 一样,只是换库:

第四步:前端必避的坑(踩过的都懂!)

  1. 跨域问题:直播流地址必须配置 CORS(跨域允许),否则前端会报 "No Access-Control-Allow-Origin" 错误,让后端 / CDN 配置即可;
  2. 自动播放限制:所有浏览器都禁止 "无用户交互的有声自动播放",所以必须先静音,用户点击后再开声音;
  3. 移动端适配
    • 移动端要加<meta name="viewport" content="width=device-width, initial-scale=1">
    • 全屏播放用videoElement.requestFullscreen()(兼容:webkitEnterFullscreen for iOS);
  4. 断流重连:一定要加错误监听和自动重连,直播流不可能 100% 稳定;
  5. HTTPS 问题:如果你的网页是 HTTPS,直播流也必须是 HTTPS(浏览器禁止混合内容),否则会加载失败。
相关推荐
十一.3662 小时前
131-133 定时器的应用
前端·javascript·html
xhxxx3 小时前
你的 AI 为什么总答非所问?缺的不是智商,是“记忆系统”
前端·langchain·llm
3824278274 小时前
python:输出JSON
前端·python·json
2503_928411564 小时前
12.22 wxml语法
开发语言·前端·javascript
光影少年4 小时前
Vue2 Diff和Vue 3 Diff实现及底层原理
前端·javascript·vue.js
傻啦嘿哟4 小时前
隧道代理“请求监控”实战:动态调整采集策略的完整指南
前端·javascript·vue.js
JIngJaneIL4 小时前
基于java + vue个人博客系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
C_心欲无痕4 小时前
vue3 - readonly创建只读的响应式对象
前端·javascript·vue.js
Rabi'4 小时前
编译ATK源码
前端·webpack·node.js