Skip to content

HLS 控制 ​

English

为 Hls.js 播放器添加画质与音轨菜单。插件控制你放在 art.hls 上的 Hls.js 实例,不负责下载、创建或销毁 SDK。

本页描述当前重构分支。这里说明的自动刷新与生命周期修复尚未发布;未固定版本的 npm/CDN 安装仍使用已发布版本。

安装 ​

sh
yarn add artplayer hls.js artplayer-plugin-hls-control
js
import Artplayer from 'artplayer';
import Hls from 'hls.js';
import artplayerPluginHlsControl from 'artplayer-plugin-hls-control';

通过 script 标签使用时,先加载 ArtPlayer、Hls.js 和插件的 dist/artplayer-plugin-hls-control.js。插件全局名称为 artplayerPluginHlsControl。应用中应固定依赖版本,并使用允许浏览器访问的视频地址。

完整示例 ​

下面与在线 HLS 示例使用同一份代码和站点容器。接入自己的应用时替换容器与视频地址。

▶ Run Code
js
// npm i hls.js
// npm i artplayer-plugin-hls-control

// import Hls from 'hls.js';
// import artplayerPluginHlsControl from 'artplayer-plugin-hls-control';

const useHls = Hls.isSupported()
let hls

function destroyHls() {
  const previous = hls
  hls = undefined
  if (previous)
    previous.destroy()
}

const art = new Artplayer({
  container: '.artplayer-app',
  url: 'https://playertest.longtailvideo.com/adaptive/elephants_dream_v4/index.m3u8',
  setting: true,
  plugins: useHls
    ? [
        artplayerPluginHlsControl({
          quality: {
            // Show quality choices in the controls
            control: true,
            // Show quality choices in settings
            setting: true,
            // Get the quality name from level
            getName: level => `${level.height}P`,
            // I18n
            title: 'Quality',
            auto: 'Auto',
          },
          audio: {
            // Show audios in control
            control: true,
            // Show audios in setting
            setting: true,
            // Get the audio name from track
            getName: track => track.name || track.lang || 'Audio',
            // I18n
            title: 'Audio',
            auto: 'Auto',
          },
        }),
      ]
    : [],
  customType: {
    m3u8: function playM3u8(video, url, art) {
      destroyHls()
      if (useHls) {
        hls = new Hls()
        art.hls = hls
        hls.loadSource(url)
        hls.attachMedia(video)
      }
      else if (video.canPlayType('application/vnd.apple.mpegurl')) {
        video.src = url
      }
      else {
        art.notice.show = 'Unsupported playback format: m3u8'
      }
    },
  },
})

art.on('destroy', destroyHls)

仅在支持 Hls.js 时安装控制插件。若改用浏览器原生 HLS,示例直接设置 video.src,不安装必须依赖 art.hls 的插件;该插件不会为原生播放提供画质或音轨选择。单个播放器实例保持固定的 useHls,更换播放集成方式时重新创建播放器。

配置 ​

artplayerPluginHlsControl(option?) 同步返回插件工厂。quality 与 audio 都可以使用以下字段:

字段含义与默认行为
control显示底部控制器;省略时不显示。
setting显示设置项;省略时不显示,同时需要播放器的 setting: true。
title菜单标题,画质默认 Quality,音轨默认 Audio。
auto当前项未知时的文字,默认 Auto;画质还用于自动选项。音轨不会因此新增一个虚拟 Auto 轨道。
getName(item, index?)根据原始 SDK 档位或轨道对象返回字符串。当前标签调用没有 index,列表调用带有索引。

省略画质回调时,标签取 level.name 或 level.height + 'P';音轨依次取 track.name、track.lang、track.language。空标题和空 Auto 文字会使用默认值。媒体没有相关字段时,自定义回调应提供字符串回退。

回调按普通函数调用,this 不会绑定到播放器,不能把可选索引视为必传字段。相同标签会合并成一个选项;如果想区分同高度的多个档位,可在标签中加入码率。轨道列表变空时会移除对应菜单。

选择画质会写入 hls.currentLevel,Auto 对应 -1;当 autoLevelEnabled 为 true 时,当前标签反映自动模式。选择音轨会把 SDK 轨道 ID 写入 hls.audioTrack。菜单选择是同步操作,不代表新流已经完成缓冲或解码。

外部修改后的刷新 ​

播放器 ready、restart 会刷新菜单;SDK 提供事件接口时,清单、档位、音轨与销毁事件也会刷新或清除菜单。选中项来自当前 SDK 状态。

把替换后的实例绑定到同一个 video 并赋给 art.hls 后,如需立即刷新,可以调用已有同步方法:

js
art.plugins.artplayerPluginHlsControl.update();

update() 返回 undefined,不是 Promise;在没有已绑定 Hls.js 实例时调用可能抛错。没有对应事件接口的自定义适配器需要在状态变化后手动刷新。菜单名 hls-quality 和 hls-audio 由插件使用,其他菜单请使用不同名称。

SDK 所有权与换源 ​

换源继续使用播放器已有的 switchUrl() 或 switchQuality(),并处理返回的 Promise。示例在创建新 SDK 前销毁旧实例,再更新 art.hls,每个播放器只保留一个最终清理监听器,每个 SDK 实例只销毁一次。不要在每次加载时累积新的播放器 destroy 监听器,同时又自行销毁被替换的实例。

控制插件只释放自己的 SDK 订阅;替换或销毁播放器后,旧菜单回调不再修改 SDK。插件不会销毁 SDK、移除其他使用者的监听器或实现 Hls.js 错误恢复;应用仍负责处理 SDK 致命错误和播放策略。

TypeScript ​

默认回调类型包含画质高度/名称和音轨 ID/名称/语言字段。可以通过泛型使用应用所需的 SDK 元数据类型;下面的示例只声明实际使用的字段,无需导入 Hls.js 声明:

ts
import hlsControl from 'artplayer-plugin-hls-control';

interface Level { height: number; bitrate: number }
interface Track { id: number; name: string; lang?: string }

const plugin = hlsControl<Level, Track>({
    quality: {
        control: true,
        getName: level => level.height + 'p / ' + level.bitrate,
    },
    audio: {
        setting: true,
        getName: track => track.name || track.lang || 'Audio',
    },
});

根入口导出 Option、Config、QualityLevel、AudioTrack 和 Result 类型,原根入口及 legacy 路径继续保留。声明不会假定每个 ArtPlayer 实例都有 Hls.js;请在应用的集成类型中描述 art.hls。

注册结果只有固定的 name: 'artplayerPluginHlsControl' 和 update()。工厂普通调用允许省略配置;最后一个声明重载保留必填参数,因此 Parameters<typeof hlsControl>[0] 仍为 Option,不包含 undefined。本包没有 /runtime 子路径,也没有工厂 .default 自引用。

验证范围 ​

重构使用本地媒体和真实 worker 验证 Hls.js 1.5.17 / 1.7.2;这两个版本是验证点,不是新定义的支持范围。Firefox 的分组播放崩溃和另一项切组停滞仍在排查。Windows Playwright WebKit 缺少测试所需的 MSE 路径,不能代表 Safari/iOS 原生 HLS 已验收。采用尚未发布的重构前,应验证实际媒体与目标设备。