前端在浏览器端播放直播流协议的2种方式讲解

作者:像素漫游

时间:2026-10-31

浏览:588

本文详细讲解前端在浏览器端播放直播流的两种主流方案:基于hls.js的.m3u8播放和基于flv.js的.flv播放。内容涵盖库的安装、核心API调用、错误恢复机制、动态切换播放源及资源销毁等关键操作步骤,帮助开发者实现无Flash的流畅直播体验。

文章目录

直播流主要包含两种协议:后缀为.flv的文件通常对应http-flv协议,而后缀为.m3u8的文件则对应hls协议。

一、播放.m3u8

1、hls.js

HLS(HTTP Live Streaming)是由Apple公司开发的流媒体传输技术,其结构包含一个.m3u8索引文件、多个.ts分片文件以及.key加密密钥文件。该技术广泛应用于视频点播和直播场景。

hls.js是一个JavaScript库,用于在客户端实现HTTP Live Streaming播放功能。它依赖于HTML5视频标签和MediaSource Extensions(MSE)扩展来完成播放任务。

其工作原理是将MPEG-2传输流和AAC/MP3流转换为ISO BMFF(MP4)片段。若浏览器支持,可利用Web Worker异步执行此转换过程。自WWDC2016起,hls.js也支持HLS + fmp4格式。

使用hls.js无需额外播放器插件,它可直接在标准的HTML video元素上运行。

该库使用ECMAScript 6(*.js)和TypeScript(*.ts,即ES6的强类型超集)编写,并通过TypeScript编译器编译为ECMAScript 5代码。

特性

  • 支持点播(VOD)和直播播放列表
  • 支持实时播放列表上的DVR(数字视频录像)功能
  • 支持碎片化MP4容器
  • 支持MPEG-2 TS容器
  • 支持ITU-T H.264和ISO/IEC 14496-10基本流
  • 支持ISO/IEC 13818-7 ADTS AAC基本流
  • 支持ISO/IEC 11172-3 / ISO/IEC 13818-3(MPEG-1/2 Audio Layer III)基本流
  • 支持打包元数据(ID3v2.3.0)基本流
  • 支持AAC容器(仅限音频流)
  • 支持MPEG音频容器(MPEG-1/2 Audio Layer III 仅限音频流)
  • 支持HTTP Live Streaming的定时元数据(ID3格式,MPEG-2 TS承载)
  • 支持AES-128解密
  • 支持SAMPLE-AES解密(仅在MPEG-2 TS容器下支持)
  • 支持DRM(数字版权管理)的加密媒体扩展(EME)
  • 支持Widevine CDM(仅在演示页面使用shaka-packager test-stream进行测试时有效)
  • 支持CEA-608/708字幕
  • 支持WebVTT字幕
  • 支持VoD和直播列表中的备用音轨切换(通过主播放列表中的备用音频)
  • 支持自适应流媒体
  • 手动和自动质量切换
    • 3种质量切换模式可用(可通过API方式控制)
      • 即时切换:在当前视频位置立即进行质量切换
      • 平滑切换:在下一个加载片段时进行质量切换
      • 带宽保守切换:在下一个加载片段时更改质量,且不刷新缓冲区
    • 在自动质量模式下,若带宽突然下降,会紧急降低质量以最小化缓冲。
  • 支持VoD和直播中的精确搜索(不限于片段或关键帧边界)
  • 具备在缓冲区和后台缓冲区中查找的能力,无需重新下载段。
  • 内置分析功能
  • 可监控所有内部事件(包括网络事件和视频事件)
  • 播放会话指标也已公开
  • 具备容错能力
  • 库中内置了重试机制
  • 可触发恢复操作以修复致命的媒体或网络错误

2、使用hls.js

1. 安装hls.js

npm i hls.js

2. 使用hls.js实现播放m3u8格式流,获取video节点

<video id="video" ref="videoRef" autoplay width="800" height="400" controls></video>
import Hls from 'hls.js'

// 获取视频元素
var video = document.getElementById('video');

if (video.canPlayType('application/vnd.apple.mpegurl')) {
    video.src = videoSrc;
	//
	// If no native HLS support, check if HLS.js is supported
	//
} else if (Hls.isSupported()) {
    let config = {
	    xhrSetup: function (xhr, url) {
	    	xhr.withCredentials = true; // 会携带cookie
		    // xhr.setRequestHeader('token',"my-token")
	    },
	}

    // 创建一个新的HLS实例
    var hls = new Hls(config);

 
    // 绑定 canplay 事件,当能够播放时开始播放
    hls.on(Hls.Events.MANIFEST_PARSED, function() {
      video.play();
    });
 
    // 绑定错误事件
    hls.on(Hls.Events.ERROR, function(event, data) {
      var errorType = data.type;
      var errorDetails = data.details;
      var errorFatal = data.fatal;

      if (data.fatal) {
        switch(data.type) {
          case Hls.ErrorTypes.NETWORK_ERROR:
            // 网络错误处理
            break;
          case Hls.ErrorTypes.MEDIA_ERROR:
            // 媒体错误处理
            break;
          default:
            // 其他错误处理
            break;
        }
      }
    });
 
    // 在video元素上附加MSE
    hls.attachMedia(video);
 
    // 开始加载HLS流
    hls.loadSource('xxx.m3u8');
}

3. 销毁

应调用销毁方法以释放所占用的资源并销毁hls上下文。

hls.destroy() 

4. 致命错误恢复

hls.js提供了两种方法用于“尝试”恢复致命的网络和媒体错误:

hls.startLoad()

应调用此方法以恢复网络错误。

hls.recoverMediaError()

应调用此方法以恢复媒体错误。

错误恢复示例代码

hls.on(Hls.Events.ERROR, function (event, data) {
  if (data.fatal) {
    switch (data.type) {
      case Hls.ErrorTypes.NETWORK_ERROR:
        // try to recover network error
        console.log('fatal network error encountered, try to recover');
        hls.startLoad();
        break;
      case Hls.ErrorTypes.MEDIA_ERROR:
        console.log('fatal media error encountered, try to recover');
        hls.recoverMediaError();
        break;
      default:
        // cannot recover
        hls.destroy();
        break;
    }
  }
});

hls.swapAudioCodec()

如果调用后仍引发媒体错误,调用hls.recoverMediaError()可能有助于解决音频编解码器不匹配问题。工作流程如下:

关于第一次媒体错误:调用hls.recoverMediaError()

如果在第一个媒体错误后“快速”引发另一个媒体错误:先调用hls.swapAudioCodec(),再调用hls.recoverMediaError()。

5. 切换播放源

首先检查hls对象是否已定义,若已定义则停止当前播放器实例。随后创建新的播放器实例,绑定至video元素,并开始加载新的播放源。加载成功后,播放器会自动开始播放新视频内容。若加载过程中发生错误,将执行相应的错误处理逻辑。

if (typeof hls !== 'undefined') {
  // 停止当前的播放器实例
  hls.destroy();
}
 
// 新的播放源URL
var newVideoUrl = 'new_source_url.m3u8';
 
// 创建新的HLS播放器实例
var hls = new Hls();
 
// 绑定到video元素
var video = document.getElementById('video');
hls.attachMedia(video);
 
// 监听加载事件
hls.on(Hls.Events.MANIFEST_PARSED, function () {
  video.play();
});
 
// 错误处理
hls.on(Hls.Events.ERROR, function (event, data) {
  if (data.fatal) {
    switch (data.type) {
      case Hls.ErrorTypes.NETWORK_ERROR:
        // 网络错误处理
        break;
      case Hls.ErrorTypes.MEDIA_ERROR:
        // 媒体错误处理
        break;
      default:
        // 其他错误处理
        break;
    }
  }
});
 
// 加载新的播放源
hls.loadSource(newVideoUrl);

二、播放.flv

Flv.js是一个纯原生JavaScript开发的HTML5 Flash视频(FLV)播放器,未使用Flash技术,由bilibili网站开源。其工作原理是将FLV文件流转码复用为ISO BMFF(MP4碎片)片段,再通过Media Source Extensions将MP4片段输入浏览器进行播放。

1、安装flv.js

npm i flv.js

2、使用flv.js实现播放flv格式流,获取video节点

import flvjs from 'flv.js'

let videoElement = document.getElementById('my-player');

if (flvjs.isSupported()) {
    flvPlayer = flvjs.createPlayer({
        type: 'flv',					//媒体类型
        url: 'XXXX'						//flv格式媒体URL
        isLive: true,					//数据源是否为直播流
        hasAudio: false,				//数据源是否包含有音频
	    hasVideo: true,					//数据源是否包含有视频
	    enableStashBuffer: false		//是否启用缓存区
    },{
        enableWorker: false, 			//不启用分离线程
        enableStashBuffer: false, 		//关闭IO隐藏缓冲区
        autoCleanupSourceBuffer: true 	//自动清除缓存
    });

    flvPlayer.attachMediaElement(videoElement);	//将播放实例注册到节点
    flvPlayer.load(); 					//加载数据流
    flvPlayer.play();					//播放数据流
}

3、关闭视频流

flvPlayer.pause();						//暂停播放数据流							
flvPlayer.unload();						//取消数据流加载
flvPlayer.detachMediaElement();			//将播放实例从节点中取出
flvPlayer.destroy();					//销毁播放实例

4、flv.js常用方法

1:flvjs.isSupported():判断当前浏览器是否支持播放

2:flvPlayer = flvjs.createPlayer(mediaDataSource: MediaDataSource, config?: Config):创建一个播放实例

3:flvPlayer.attachMediaElement(mediaElement: HTMLMediaElement):将播放实例注册到video节点

4:flvPlayer.load():加载数据流

5:flvPlayer.play():播放数据流

6:flvPlayer.pause():暂停播放数据流

7:flvPlayer.unload():取消数据流加载

8:flvPlayer.detachMediaElement():将播放实例从节点中取出

9:flvPlayer.destroy():销毁播放实例

参考文档

hls.js - npm

flv.js - npm

到此这篇关于前端在浏览器端播放直播流协议的2种方式讲解的文章就介绍到这了,更多相关前端浏览器端播放直播流协议内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章