技术研究之前端视频播放

标签: 无 分类: 未分类 创建时间:2024-09-29 01:05:28 更新时间:2024-11-15 10:49:44

1.HLS.js

使用:pnpm add hls.js 安装了hls.js,然后通过导入 hls 可以使用这个东西。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<template>
<div class="monitor-dialog" v-if="dataState.currentMonitor">
<div class="header">
<div class="title">{{ dataState.deviceName }}</div>
<div class="close" @click="closeHandle">
<CloseOutlined />
</div>
</div>
<div class="content">
<video
class="monitor-video"
controls="controls"
autoplay="autoplay"
x-webkit-airplay="true"
x5-video-player-fullscreen="true"
preload="auto"
playsinline="true"
webkit-playsinline
x5-video-player-typ="h5"
ref="monitorVideo"
>
</video>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, shallowReactive, defineEmits,ref,onBeforeUnmount } from 'vue';
import eventBus from '/@/utils/map/eventBus'; // 事件总线
import { CloseOutlined } from '@ant-design/icons-vue';
import { getChannels } from '../api/map.ts';
import hlsjs from 'hls.js'

const dataState = shallowReactive({
currentMonitor: null,
deviceName: '', // 设备名称
channelUrl: '', // 隧道地址
});

const emit = defineEmits(['close']);

const monitorVideo=ref(null); // dom 引用
let hlsjsVideo =null ; // 视频播放组件

/**
* 显示视频对话框
*/
const showMonitor = (item) => {
dataState.currentMonitor = item;
dataState.deviceName = item.deviceName;

// 获取播放通道
getMonitorChannels();
};

/**
*
*/
const closeHandle = () => {
dataState.currentMonitor = null;
dataState.channelUrl = '';
dataState.deviceName = '';

// 取消视频播放
if(monitorVideo.value){
monitorVideo.value.pause();
hlsjsVideo.destroy();
hlsjsVideo = null;
}
emit('close');
};

function getMonitorChannels() {
let device = dataState.currentMonitor;
let deviceId = device.deviceId;
getChannels({
deviceId: deviceId,
}).then((res) => {
let channels = res[0];
dataState.channelUrl = channels.hls;

// 显示视频
showChannel();
});
}

/**
* 显示视频隧道
*/
function showChannel(){
if (hlsjs.isSupported()) {
hlsjsVideo = new hlsjs();
hlsjsVideo.loadSource(dataState.channelUrl);//设置播放路径
hlsjsVideo.attachMedia(monitorVideo.value);//解析到video标签上

hlsjsVideo.on(hlsjs.Events.MANIFEST_PARSED, () => {
monitorVideo.value.play();
});
hlsjsVideo.on(hlsjs.Events.ERROR, (event, data) => {
console.log(event, data);
// 监听出错事件
console.log("加载失败");
});
}
}

onMounted(() => {
eventBus.on('showMonitor', showMonitor);
});

onBeforeUnmount(()=>{
closeHandle();
})
</script>
<style lang="less" scoped>
.monitor-dialog {
position: fixed;
left: 50%;
transform: translateX(-50%);
top: 120px;
width: 500px;
height: 400px;
border: 1px solid #aaa;
border-radius: 8px;
background: rgba(9, 62, 122, 0.9);
padding: 10px 20px 20px 20px;
display: flex;
flex-direction: column;

.header {
font-size: 18px;
color: #fff;
padding: 0 0 10px 0;

.close {
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
}
}
.content {
flex: 1;

video {
width: 100%;
height: 100%;
object-fit: fill
}
}
}
</style>
参考文章:
1.Vue 之 视频流 - Hls.js
2.实时视频流库 hls.js 重载切换资源的方式 hls 播放需要先 attachMedia,然后 loadSource。如果切换 resource,需要先执行 hls.destroy(),否则会出现混乱。destroy 之后再依次进行 hls 实例化、attach、load 操作。

问题

(1)”Failed to execute ‘appendBuffer’ on ‘SourceBuffer’: This SourceBuffer has been removed from the parent media source.”
我在执行 m3u8 文件播放的时候,出现了这个问题,就是后端已经请求了 ts ,无论切片大小,都是无法播放的。

2.Xgplay

西瓜视频播放器
(1)安装

1
pnpm add xgplay xgplay-hls

(2)使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 引入样式
import 'xgplayer/dist/index.min.css'

// 主要代码
let videoUrl = item || this.videoUrl
let m3u8Url = BASE_API_URL + '/drone/api/v1/files/getM3U8File?filename=' + videoUrl + '&x-auth-token=' + sessionStorage.getItem('droneToken')
let player
if (document.createElement('video').canPlayType('application/vnd.apple.mpegurl')) {
// 原生支持 hls 播放
player = new Player({
el: this.$el.querySelector('.player'),
url: m3u8Url
})
} else if (HlsPlugin.isSupported()) {
// 第一步
player = new Player({
el: this.$el.querySelector('.player'),
isLive: false,
url: m3u8Url, // hls 流地址
plugins: [HlsPlugin] // 第二步
})
}
player.on('error', event => {
console.log(event)
})
参考文章:
【1】.xgplayer-hls.js v2.32播放hls m3u8直播流 西瓜视频网页播放器 demo 示例教程
【2】.快速上手
【3】.xgplayer-hls
【4】.西瓜播放器 这是一个播放器的示例代码
【5】.配置 西瓜视频配置

问题

(1)”CHUNK_DEMUXER_ERROR_APPEND_FAILED: Unsupported VisualSampleEntry type mp4v”

参考文章:
1.MP4V File Extension

(2)没有样式信息
我用的是 xgplay 3.0.11 版本,结果样式全部错误了。

【引入样式】

1
import 'xgplayer/dist/index.min.css'

3.Jswebrtc

使用 jswebrtc 播放 rtmp 我在上面其实已经写过了,关键就是这个地址,因为我用的是改造后的 jswebrtc.min.js,所以要注意端口号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let url = "webrtc://" + window.location.hostname + "xxx";
let videoDom = document.getElementById('webrtc');
// url 是一个 webrtc 开头的地址 webrtc://xxx
this.player = new JSWebrtc.Player(url, {
video: videoDom,// 用于播放视频的 HTML Video 元素
autoplay: true,// 是否自动播放,默认 false
onPlay: () => {// onPlay(player),播放后回调
videoDom.addEventListener('canplay', function () {
// .play() – 开始 .pause() – 暂停 .stop() – 停止
// .destroy() – 停止播放并清理相关的播放资源 .paused – 只读,是否暂停播放
videoDom.play();
})
}
// onPause(player),暂停后回调
})

参考文章:
【1】.vue使用JSWebrtc播放webrtc视频流
【2】.『前端日记』—— 基于WebRTC的浏览器跨端传输
【3】.jswebrtc 拉流 webrtc://xxx
【4】.jswebrtc播放无人机直播视频
【5】.H5播放Rtmp之videojs播放 我们看到了HLS播放视频实时性非常差,好的在6-7s,差点的就要10-12s了,也就是人走了,估计视频上还能看到,这对观感效果造成了很大的影响!但是好处就是它是基于http协议文件下载的,所以不需要任何插件,到处播放,处处兼容,所以rtmp和hls在web端的特点如下
【6】.Web端rtmp视频流的预览 方案1:基于video.min@5.4.3.js。方案2:基于Aliplayer。
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。