Vue通过HLS协议播放m3u8格式视频

850 阅读2分钟

名词解释

M3U8

M3U(MP3 URL的缩写)是一种播放多媒体列表的文件格式,M3U文件是一种纯文本文件。
而M3U8则是以utf-8编码的M3U文件,用于指示视频片段(ts)的位置和顺序。

HLS

HLS全称是Http Live Streaming,用于实时的音视频流的传输。
HLS协议由HTTP(传输协议),m3u8(索引文件)和ts(音视频片段数据)三部分组成。
HLS会把整个流分割成一个个ts文件,根据m3u8索引文件的位置和顺序,实时发送http请求下载ts片段。

MIME

MIME是描述消息内容类型的标准,所以MIME类型可以表示该消息的内容,如文本、图像、音频、视频或其他应用程序专用的数据。
浏览器通常使用MIME类型来确定如何处理URL,因此Web服务器在响应头中添加正确的MIME类型非常重要,否则浏览器可能会无法解析文件内容。
MIME的组成结构非常简单,由类型子类型两个字符串中间用 / 分隔而组成,不允许有空格
如:text/plain

相关MIME类型

.m3u8文件:application/x-mpegapplication/x-mpegURL
m3u8文件MIME类型.png
.ts文件:video/MP2T
ts文件MIME类型.png

hls.js安装

npm
安装 npm install --save hls.js
使用 import Hls from 'hls.js';

举例

<!-- 如果页面只有1个video标签可以使用id获取元素,如果有多个建议使用ref -->
<video ref="videoRef" autoplay="true" controls></video>
const videoRef = ref();
const hls = ref<Hls>();

const setLiveHls = (url: string) => {
  if (hls.value) {
    hls.value.destroy();
  }
  // 如果给定的MIME类型和(可选的)编解码器可被当前的用户代理支持,则返回 true 
  if (Hls.isSupported()) {
    hls.value = new Hls({
      // Hlsjs 将持续缓冲,直到以下两个条件都满足为止:
      // 缓冲区大小超出 maxBufferSize
      // 缓冲区长度超出 maxBufferLength
      maxBufferLength: 30, // 最大缓冲区长度
    });

    // 将 hls.js 附加到媒体元素
    hls.value.attachMedia(videoRef.value);
    // 绑定成功后 启动并载入 HLS 流
    hls.value.on(Hls.Events.MEDIA_ATTACHED, () => {
      if (hls.value) {
        hls.value.loadSource(videoData.url);
      }
    });
    // 索引文件解析完成后开始播放视频
    hls.value.on(Hls.Events.MANIFEST_PARSED, () => {
      videoRef.value.play();
    });
    // hls错误处理
    hls.value.on(Hls.Events.ERROR, (event, data) => {
      if (data.fatal && hls.value) {
        switch (data.type) {
          case Hls.ErrorTypes.NETWORK_ERROR:
            // 恢复网络错误
            hls.value.startLoad();
            break;
          case Hls.ErrorTypes.MEDIA_ERROR:
            // 恢复媒体错误
            hls.value.recoverMediaError();
            break;
          default:
            // 销毁实例
            hls.value.destroy();
            break;
        }
      }
    });
  } else if (videoRef.value.canPlayType('application/vnd.apple.mpegurl')) {
    videoRef.value.src = url;
  }
};

// 可以在需要的地方调用方法,但是要保证videoRef有值
onMounted(() => {
  setLiveHls('url');
});
HLS的error事件中的data数据类型
export declare interface ErrorData {
    type: ErrorTypes;
    details: ErrorDetails;
    error: Error;
    fatal: boolean;
    errorAction?: IErrorAction;
    buffer?: number;
    bytes?: number;
    chunkMeta?: ChunkMetadata;
    context?: PlaylistLoaderContext;
    event?: keyof HlsListeners | 'demuxerWorker';
    frag?: Fragment;
    part?: Part | null;
    level?: number | undefined;
    levelRetry?: boolean;
    loader?: Loader<LoaderContext>;
    networkDetails?: any;
    stats?: LoaderStats;
    mimeType?: string;
    reason?: string;
    response?: LoaderResponse;
    url?: string;
    parent?: PlaylistLevelType;
    sourceBufferName?: SourceBufferName;
    /**
     * @deprecated Use ErrorData.error
     */
    err?: {
        message: string;
    };
}