vue3 中播放 m3u8 格式视频 您所在的位置:网站首页 免费读绘本故事 vue3 中播放 m3u8 格式视频

vue3 中播放 m3u8 格式视频

2023-05-09 05:25| 来源: 网络整理| 查看: 265

视频文件格式

视频文件格式是指视频文件的编码和压缩方式,

1.容器和编解码器是任何视频文件的两个组成部分。

视频格式是存储音频,视频,字幕和任何其他源数据的容器。 编解码器是对音频和视频之类的多媒体数据进行编码和解码。

2.创建视频时,视频编解码器对视频进行编码和压缩,而音频编解码器对声音也是如此。 之后,编码的视频和音频将同步并存储在媒体容器(文件格式)中。

常见在线流媒体格式:mp4、flv、f4v、webm

移动设备格式:m4v、mov、3gp、3g2

RealPlayer :rm、rmvb

微软格式 :wmv、avi、asf

MPEG 视频 :mpg、mpeg、mpe、ts

DV格式 :div、dv、divx

其他格式 :vob、dat、mkv、lavf、cpk、dirac、ram、qt、fli、flc、mod

选择视频格式之前,请考虑以下情况:

1.对于在线视频,请选择大多数网络浏览器支持的文件格式。 这样,您的视频将在浏览器上本地播放。 MP4和WEBM是与浏览器兼容的视频格式。

2.对于家庭视频录像,请选择高质量的视频格式,以备将来使用。 开源文件格式比企业控制的专有格式更具面向未来性。 MP4或AVI格式非常适合该类别。

3.对于Windows应用程序,请选择与Windows兼容的格式。 在这种情况下,WMV是一个不错的选择。

m3u8

m3u8是一种视频流媒体播放列表文件格式,常用于将视频内容分割成多个小文件并进行流式传输。

现在的视频网站采用的是流媒体传输协议,将一段视频切成无数个小段,这几个小段就是ts格式的视频文件,一段一段的网站上播放。

服务器采集编码传输视频到切片器 切片器对视频创建索引文件,并切割成 n 个 ts 文件 这两个文件传输到 http 服务器上 网站/客户端根据索引文件查找 http 服务器上的 ts 文件,连续播放这 n 个 ts 文件,就可以了。

索引文件里面存储着ts文件的网络url链接,网站需要拿到索引文件,去按照url链接下载在http服务器中的ts文件。拿到了ts文件之后,本身这些ts文件就是原视频中的一小段视频,所有ts文件下载、顺序播放,就完成了整个视频的播放。而索引文件就是 m3u8 文件。

m3u8是文件记录了一个索引纯文本文件,打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。这种格式通常用于在网络上实现实时视频直播和点播服务,可以通过多种设备和平台进行播放。

Hls

HLS是苹果公司开发的一种流媒体传输协议,全称为HTTP Live Streaming,用于实时流传输的协议。

它通过将整个视频分割成多个小的ts文件,每个文件都有自己的URL地址,然后通过HTTP协议进行传输,实现了在网络上的流式传输。

HLS协议支持多种码率和分辨率的视频,可以自适应地根据用户的网络环境和设备性能进行调整,提供更好的观看体验。

hls.js是一个JavaScript库,可实现HTTP Live Streaming客戶端。 它依靠HTML5视频和MediaSource扩展进行播放。

它通过将MPEG-2传输流和AAC / MP3流转换为ISO BMFF(MP4)片段来工作。 如果在浏览器中可用,可以使用Web Worker异步执行此转换。hls.js还支持HLS + fmp4,不需要任何播放器,它可以直接在标准HTML 元素上运行。

video.js 播放 m3u8

在项目中可以使用 video.js 播放m3u8格式的视频文件文件, 同时video.js也对vue3提供支持。 顺便感慨一句 video 的文档我真的看不懂😭

首先在项目中安装video.js

yarn add video.js videojs-contrib-hls 复制代码 初始化video.js // 定义 videojs 实例 const myPlayer = ref() const playVideo = reactive({ videoUrl: 'xxxx.m3u8', }) onMounted(()=>{ const videoUrl ="xxx.example.m3u8" initVideoSource(videoUrl) }) function initVideoSource () { myPlayer.value = videojs('my-video', { controls: true, // 是否显示控制条 preload: 'auto', autoplay: false, loop: false, // 循环播放 // fluid: true, // 自适应宽高 language: 'zh-CN', // 设置语言 muted: false, // 是否静音 inactivityTimeout: false, // 设置控制条组件 controlBar: { // 设置控制条组件 // 设置控制条里面组件的相关属性及显示与否 currentTimeDisplay: true, timeDivider: true, durationDisplay: true, remainingTimeDisplay: false, volumePanel: { inline: false, }, pictureInPictureToggle: false, // 或者使用 children 定义 /* 使用children的形式可以控制每一个控件的位置,以及显示与否 */ // children: [ // { name: 'playToggle' }, // 播放按钮 // { name: 'currentTimeDisplay' }, // 当前已播放时间 // { name: 'progressControl' }, // 播放进度条 // { name: 'durationDisplay' }, // 总时间 // { // name: 'volumePanel', // 音量控制 // inline: false, // 不使用水平方式 // }, // { name: 'FullscreenToggle' }, // 全屏 // ], }, sources: [ { src: playVideo.videoUrl, type: 'application/x-mpegURL', }, ], userActions: { seek: false, }, }) } 复制代码 video.js 语言设置

引入 zh-CN.json 语言包后在配置项中设置中文即可,亲测有效

import videojs from "video.js" import "video.js/dist/video-js.css" import video_zhCN from 'video.js/dist/lang/zh-CN.json' videojs.addLanguage('zh-CN', video_zhCN) 在设置里配置成中文:language:“zh-CN” 复制代码 import videojs from 'video.js/dist/video.min' import 'video.js/dist/video-js.min.css' import videoLanguage from 'video.js/dist/lang/zh-CN.json' // videojs 语言设置 videojs.addLanguage('zh-CN', videoLanguage) const myPlayer = ref() const playVideo = reactive({ videoUrl: 'xxxx.m3u8', }) onMounted(() => { initVideoSource() }) function initVideoSource () { videojs.addLanguage('zh-CN', videoLanguage) const myPlayer = videojs('my-video', { controls: true, // 是否显示控制条 preload: 'auto', autoplay: false, fluid: true, // 自适应宽高 language: 'zh-CN', // 设置语言 muted: false, // 是否静音 inactivityTimeout: false, controlBar: { // 设置控制条组件 children: [ { name: 'playToggle' }, // 播放按钮 { name: 'currentTimeDisplay' }, // 当前已播放时间 { name: 'progressControl' }, // 播放进度条 { name: 'durationDisplay' }, // 总时间 { name: 'volumePanel', // 音量控制 inline: false, // 不使用水平方式 }, { name: 'FullscreenToggle' }, // 全屏 ], }, sources: [ // 视频播放资源 { src: playVideo.videoUrl, type: 'application/x-mpegURL', }, ], }) // 自动播放 myPlayer.play() } 复制代码 video.js 触发事件汇总

在 video 上的监听事件

事件描述loadstart浏览器开始在网上寻找媒体数据progress浏览器正在获取媒体数据loadedmetadata浏览器获取完毕媒体的时间长和字节数play即将开始播放,当执行了play方法时触发,或数据下载后元素被设为autoplay属性pause播放暂停,当执行了pause方式时触发waiting播放过程由于得不到下一帧而暂停播放(例如下一帧尚未加载完毕),但很快就能够得到下一帧timeupdate由于播放位置被改变,可能是播放过程中的自然改变,也可能是被人为的改变,或由于播放不能连续而发生的跳变ended播放结束后停止播放canplay浏览器能够播放媒体,但估计以当前的播放速率不能直接播放完毕,播放期间需要缓冲canplaythrough浏览器能够播放媒体,而且以当前播放速率能够将媒体播放完毕,不再需要进行缓冲seekingseeking属性变为true,浏览器正在请求数据seekedseeking属性变为false,浏览器停止请求数据suspend浏览器暂停获取媒体数据,但是下载过程并滑正常结束ratechangedefaultplaybackRate属性(默认播放速率)或playbackRate属性(当前播放速率)被改变druationchange播放时长被改变stalled浏览器尝试获取媒体数据失败abort浏览器在下载完全部媒体数据之前中止获取媒体数据,但是并不是由错误引起的error获取媒体数据过程中出错emptiedvideo元素或audio元素所在网络突然变为未初始化状态可能原因有两个:1.载入媒体过程中突然发生一个致命错误volumechangevolume属性(音量)被改变或muted属性(静音状态)被改变fullscreenchange监听全屏事件

设置监听的方式一:在video 的dom元素上绑定事件监听

function onPlayerPlay(player:any){ console.log('即将开始播放', player.target) } function onPlayerLoadeddata (player:any) { // 获取视频总时长,只能在视频加载完成之后获取 const totalTime = player.target.duration console.log('playVideo play!', playVideo) } 复制代码

监听方式二:

function initVideoSource () { // videojs 语言设置 videojs.addLanguage('zh-CN', videoLanguage) myPlayer.value = videojs('my-video', { controls: true, // 是否显示控制条 preload: 'auto', autoplay: false, loop: false, // 循环播放 // fluid: true, // 自适应宽高 language: 'zh-CN', // 设置语言 muted: false, // 是否静音 inactivityTimeout: false, // 设置控制条组件 controlBar: { children: [ { name: 'playToggle' }, // 播放按钮 { name: 'currentTimeDisplay' }, // 当前已播放时间 { name: 'progressControl' }, // 播放进度条 { name: 'durationDisplay' }, // 总时间 { name: 'remainingTimeDisplay' }, // 剩余时间 { name: 'volumePanel', // 音量控制 inline: false, // 不使用水平方式 }, { name: 'FullscreenToggle' }, // 全屏 ], }, sources: [ { src: url, type: 'application/x-mpegURL', }, ], userActions: { seek: false, }, }) myPlayer.value.on('loadedmetadata', function () { // 视频播放定位到上次播放时间 myPlayer.value.currentTime(playVideo.currentSecond) }) // 视频播放结束 myPlayer.value.on('ended', async () => { // 提交视频记录 更新视频信息 setCurrentVideo() getCurrentCourse() }) // 暂停时提交 myPlayer.value.on('pause', () => { setCurrentVideo() }) // 监听全屏按钮事件 myPlayer.value.on('fullscreenchange', () => { console.log('全屏') }) 复制代码 暂停播放时展示按钮

通过样式控制,vjs-paused 下的按钮设置为 display:block

// 播放暂停时 展示暂停按钮 ::v-deep .vjs-paused > .vjs-big-play-button { display: block; } 复制代码 获取视频总时长

只能在视频加载完之后获取

function onPlayerLoadeddata (player:any) { // 获取视频总时长,只能在视频加载完成之后获取 const totalTime = player.target.duration console.log('playVideo play!', playVideo) } 复制代码 即时记录播放时间

监听播放进度,获取当前播放事件,通过取余的方式判断当前经过的时间,每过 n 秒向服务器提交一次时间记录用户当前播放的进度

//播放时长(秒) var totalTime = 0; myPlayer.on('timeupdate', function() { //当前播放时长(秒) var currentTime = Math.floor(myPlayer.currentTime()); if (currentTime > 0 && currentTime > totalTime && (currentTime % 5 == 0)) { //每隔5秒,向服务器提交播放时间(秒) } totalTime = currentTime; }); 复制代码 禁止视频拖拽、阻止用户快进

只允许用户在当前已经播放的时间内调整观看进度,不允许用户快进。

通过 timeupdate 获取当前视频播放的时间差,当时间小于一秒的属于视频的正常播放,否则为人为的拖拽快进

const myPlayer = ref() function initVideoSource () { // 在video实例初始化时监听视频播放时长更新 myPlayer.value.on('timeupdate', async () => { // videojs 播放的当前位置 const currentTime = myPlayer.value.currentTime() if (currentTime > 0 && Math.ceil(currentTime) - 1 === playVideo.currentSecond && (Math.ceil(currentTime) % 15 === 0)) { // 每隔15秒,向服务器提交播放时间(秒) await setCurrentVideo() } // 禁止用户拖拽 if (currentTime > playVideo.maxSecond) { const num = Math.ceil(currentTime) - Math.ceil(playVideo.maxSecond) if (num { const id = 'waterMark' const videoElement = documentRef.value const videoChild = videoElement.firstChild as HTMLElement const can = document.createElement('canvas') // 设置画布的长宽 can.width = 300 can.height = 300 const cans = can.getContext('2d')! // 旋转角度 cans.rotate((-20 * Math.PI) / 180) cans.font = '16px Vedana' // 设置填充绘画的颜色、渐变或者模式 cans.fillStyle = 'rgba(196, 198, 203,.4)' // 设置文本内容的当前对齐方式 cans.textAlign = 'left' // 在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置) cans.fillText(str, can.width / 8, can.height / 2) const div = document.createElement('div') div.id = id div.style.pointerEvents = 'none' div.style.top = '0px' div.style.left = '0px' div.style.position = 'absolute' div.style.zIndex = '100000' div.style.width = document.documentElement.clientWidth + 'px' div.style.height = screen.height + 'px' // 全屏时的屏幕高度 div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat' videoChild.appendChild(div) } 复制代码

由于视频当前水印的大小获取的是浏览器的宽高,能够适用于播放器全屏的情况下,

在浏览器未全屏的情况下可以用 overflow: hidden 控制水印的范围

在初始化 video 组件时添加水印

function initVideoSource () { .... // 设置视频全屏水印 setFullWaterMark('水印名称xxx') //设置局部水印 setWaterMark() } 复制代码 视频不能自动播放

在使用videojs播放视频的过程可能会存在的问题。

报错 DOMException: play() failedbecause the user didn’t interact with the document first. (用户还没有交互,不能调用play)

在最新版的Chrome浏览器(以及所有以Chromium为内核的浏览器)中,已不再允许自动播放音频和视频。就算你为video或audio标签设置了autoplay属性也一样不能自动播放, 所以浏览器在页面没有产生用户交互时时不能进行自动播放

解决方案 : 设置muted属性为true

复制代码

关于muted属性:

muted 属性,设置或返回音频是否应该被静音(关闭声音);属性的值是true和false; muted="false" 表示视频不用静音(视频播放便有声音),但设置 muted="fasle"  的情况下,视频无法实现自动播放。 video 标签中 muted  的作用: 允许视频自动播放;(Chrome66版本开始,禁止视频和音频的自动播放) 参考 vue3 项目添加水印的实现方法 videojs中文文档详解_谢泽的网络日志-CSDN博客_video.js


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有