← Blog.backToBlog

用 JavaScript 构建自己的 M3U8 播放器

8 min read

项目搭建

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>
<body>
  <input id="urlInput" placeholder="粘贴 M3U8 URL" />
  <button id="loadBtn">加载</button>
  <select id="qualitySelect"></select>
  <video id="video" controls></video>
  <div id="stats"></div>
</body>
</html>

核心播放实现

const video = document.getElementById("video");
const urlInput = document.getElementById("urlInput");
const loadBtn = document.getElementById("loadBtn");
let hls = null;

function loadStream(url) {
  if (hls) hls.destroy();
  if (Hls.isSupported()) {
    hls = new Hls();
    hls.loadSource(url);
    hls.attachMedia(video);
    hls.on(Hls.Events.MANIFEST_PARSED, updateQualityList);
  } else if (video.canPlayType("application/vnd.apple.mpegurl")) {
    video.src = url;
  }
}

loadBtn.addEventListener("click", () => {
  const url = urlInput.value.trim();
  if (url) loadStream(url);
});

画质选择 UI

function updateQualityList() {
  const select = document.getElementById("qualitySelect");
  select.innerHTML = "";
  const auto = new Option("自动", "-1");
  select.appendChild(auto);
  hls.levels.forEach((level, index) => {
    select.appendChild(
      new Option(
        level.height + "p (" + (level.bitrate / 1e6).toFixed(1) + " Mbps)",
        String(index)
      )
    );
  });
  select.onchange = () => {
    hls.currentLevel = Number(select.value);
  };
}

简单统计面板

setInterval(() => {
  if (!hls || hls.currentLevel < 0) return;
  const level = hls.levels[hls.currentLevel];
  const buffered =
    video.buffered.length > 0
      ? (video.buffered.end(video.buffered.length - 1) - video.currentTime).toFixed(1)
      : "0.0";
  document.getElementById("stats").textContent =
    level.width + "x" + level.height + " | " +
    Math.round(level.bitrate / 1000) + " kbps | buffer " + buffered + "s";
}, 1000);

错误处理基础

监听 Hls.Events.ERROR。非致命错误可忽略或重试;致命网络/媒体错误可能需要 startLoad()recoverMediaError() 或彻底重启。深入:hls.js 无法工作。入门:hls.js 教程

不想自建时更快上线

若只需要可用的生产 UI,直接嵌入或使用我们免费的在线 M3U8 播放器,不必维护自己的控件。

常见问题解答

自建 HLS 播放器难吗?
基础播放用 hls.js 很直接;打磨体验更费时。

必须 React/Vue 吗?
不必——原生 JS 足够。

如何支持 Safari?
检测原生 HLS 并设置 video.src

能加离线下载吗?
下载流水线应与播放器分开实现。