Commit 71f659d33b87af183e2fae772fe8f80062252de1

Authored by loveumiko
1 parent 416f565c

fix: 修改直播视频流的一些问题

@@ -135,7 +135,7 @@ @@ -135,7 +135,7 @@
135 jessibuca?.on('play', () => { 135 jessibuca?.on('play', () => {
136 console.log('播放'); 136 console.log('播放');
137 }); 137 });
138 - jessibuca.on('pause', () => { 138 + jessibuca?.on('pause', () => {
139 console.log('暂停'); 139 console.log('暂停');
140 }); 140 });
141 141
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 import { isNumber } from 'lodash'; 2 import { isNumber } from 'lodash';
3 - import videoJs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js'; 3 + // import videoJs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js';
4 import 'video.js/dist/video-js.css'; 4 import 'video.js/dist/video-js.css';
5 - import { computed, CSSProperties, onMounted, onUnmounted, ref, unref } from 'vue'; 5 + import { onMounted, onUnmounted, ref, unref } from 'vue';
6 import { useDesign } from '/@/hooks/web/useDesign'; 6 import { useDesign } from '/@/hooks/web/useDesign';
7 - import { getJwtToken, getShareJwtToken } from '/@/utils/auth';  
8 - import { isShareMode } from '/@/views/sys/share/hook'; 7 + // import { getJwtToken, getShareJwtToken } from '/@/utils/auth';
  8 + // import { isShareMode } from '/@/views/sys/share/hook';
9 import 'videojs-flvjs-es6'; 9 import 'videojs-flvjs-es6';
10 import { 10 import {
11 CaretUpOutlined, 11 CaretUpOutlined,
@@ -18,73 +18,42 @@ @@ -18,73 +18,42 @@
18 } from '@ant-design/icons-vue'; 18 } from '@ant-design/icons-vue';
19 import { Button } from 'ant-design-vue'; 19 import { Button } from 'ant-design-vue';
20 import { nextTick } from 'vue'; 20 import { nextTick } from 'vue';
21 - import Jessibuca from '../types/jessibuca'; 21 + import { useMessage } from '/@/hooks/web/useMessage';
  22 + import Jessibuca from './types/jessibuca';
22 // import JessibucaDemo from './components/JessibucaDemo.vue'; 23 // import JessibucaDemo from './components/JessibucaDemo.vue';
23 24
24 const { prefixCls } = useDesign('basic-video-play'); 25 const { prefixCls } = useDesign('basic-video-play');
25 26
26 - const props = defineProps<{  
27 - options?: VideoJsPlayerOptions;  
28 - withToken?: boolean;  
29 - }>(); 27 + // const props = defineProps<{
  28 + // options?: VideoJsPlayerOptions;
  29 + // withToken?: boolean;
  30 + // }>();
30 31
31 - const emit = defineEmits<{  
32 - (event: 'ready', instance?: Nullable<VideoJsPlayer>): void;  
33 - (event: 'onUnmounted'): void;  
34 - }>();  
35 -  
36 - const videoPlayEl = ref<HTMLVideoElement>(); 32 + // const emit = defineEmits<{
  33 + // (event: 'ready', instance?: Nullable<VideoJsPlayer>): void;
  34 + // (event: 'onUnmounted'): void;
  35 + // }>();
37 36
38 const JessibucaRef = ref(); 37 const JessibucaRef = ref();
39 38
40 - const videoPlayInstance = ref<Nullable<VideoJsPlayer>>();  
41 -  
42 - const getOptions = computed(() => {  
43 - const { options, withToken } = props;  
44 -  
45 - const defaultOptions: VideoJsPlayerOptions & Recordable = {  
46 - language: 'zh',  
47 - muted: true,  
48 - liveui: true,  
49 - controls: true,  
50 - techOrder: ['html5', 'flvjs'],  
51 - flvjs: {  
52 - mediaDataSource: {  
53 - isLive: true,  
54 - cors: true,  
55 - hasAudio: false,  
56 - withCredentials: false,  
57 - },  
58 - config: {  
59 - headers: {  
60 - ...(withToken  
61 - ? {  
62 - 'X-Authorization': `Bearer ${isShareMode() ? getShareJwtToken() : getJwtToken()}`,  
63 - }  
64 - : {}),  
65 - },  
66 - autoCleanupSourceBuffer: true,  
67 - },  
68 - },  
69 - };  
70 - return videoJs.mergeOptions(defaultOptions, options);  
71 - }); 39 + // const videoPlayInstance = ref<Nullable<VideoJsPlayer>>();
72 40
73 const playUrl = ref('http://flv.bdplay.nodemedia.cn/live/bbb.flv'); 41 const playUrl = ref('http://flv.bdplay.nodemedia.cn/live/bbb.flv');
74 42
  43 + const { createMessage } = useMessage();
  44 +
75 let jessibuca: Jessibuca | null = null; 45 let jessibuca: Jessibuca | null = null;
76 const container = ref(null); 46 const container = ref(null);
77 const createJessibuca = () => { 47 const createJessibuca = () => {
78 jessibuca = new (window as any).Jessibuca({ 48 jessibuca = new (window as any).Jessibuca({
79 - container: container.value, 49 + decoder: '/jessibuca/decoder.js',
  50 + container: container.value, //播放器容器
80 videoBuffer: 0.2, // 缓存时长 51 videoBuffer: 0.2, // 缓存时长
81 isResize: true, 52 isResize: true,
82 isFullResize: true, 53 isFullResize: true,
83 text: '', 54 text: '',
84 - debug: false,  
85 - // background: "bg.jpg",  
86 loadingText: '加载中', 55 loadingText: '加载中',
87 - // hasAudio:false, 56 + hasAudio: false,
88 debug: true, 57 debug: true,
89 showBandwidth: true, // 显示网速 58 showBandwidth: true, // 显示网速
90 operateBtns: { 59 operateBtns: {
@@ -93,32 +62,25 @@ @@ -93,32 +62,25 @@
93 play: true, 62 play: true,
94 audio: true, 63 audio: true,
95 }, 64 },
96 - controlAutoHide: true, 65 + controlAutoHide: true, // 底部控制台是否自动隐藏
97 ifFlv: false, 66 ifFlv: false,
98 - forceNoOffscreen: true,  
99 - isNotMute: false,  
100 - decoder: '/jessibuca/decoder.js', 67 + forceNoOffscreen: true, //是否不使用离屏模式(提升渲染能力)
  68 + isNotMute: false, // 是否开启声音,默认是关闭声音播放的。
101 }) as Jessibuca; 69 }) as Jessibuca;
102 }; 70 };
103 71
104 - const getWidthHeight = computed(() => {  
105 - let { width = 640, height = 360 } = unref(getOptions);  
106 - width = isNumber(width) ? (`${width}px` as unknown as number) : width;  
107 - height = isNumber(height) ? (`${height}px` as unknown as number) : height;  
108 - return { width, height } as CSSProperties; 72 + const videoInfo = ref<{ width: string | number; height: string | number }>({
  73 + width: 640,
  74 + height: 360,
109 }); 75 });
110 -  
111 - const init = () => {  
112 - if (unref(videoPlayInstance)) unref(videoPlayInstance)?.dispose();  
113 - videoPlayInstance.value = videoJs(unref(videoPlayEl)!, unref(getOptions), () => {  
114 - emit('ready', unref(videoPlayInstance));  
115 - });  
116 - };  
117 - //播放/暂停s 76 + //播放/暂停
118 const handleClick = () => { 77 const handleClick = () => {
119 - console.log('播放/暂停');  
120 - unref(isPlay) && unref(videoPlayInstance)?.pause();  
121 - !unref(isPlay) && unref(videoPlayInstance)?.play(); 78 + console.log('播放/暂停', unref(isPlay));
  79 + if (unref(isPlay)) {
  80 + jessibuca?.pause();
  81 + } else {
  82 + jessibuca?.play();
  83 + }
122 }; 84 };
123 85
124 const handleTopClick = async () => { 86 const handleTopClick = async () => {
@@ -153,89 +115,63 @@ @@ -153,89 +115,63 @@
153 115
154 const isPlay = ref<Boolean | null | undefined>(true); 116 const isPlay = ref<Boolean | null | undefined>(true);
155 117
156 - // 播放  
157 - // const play = () => {  
158 - // if (playUrl.value) {  
159 - // jessibuca?.play(playUrl.value);  
160 - // }  
161 - // };  
162 -  
163 - // // 暂停  
164 - // const pause = () => {  
165 - // jessibuca?.pause();  
166 - // playing.value = false;  
167 - // };  
168 -  
169 // // 关闭视频 118 // // 关闭视频
170 - // const destroy = () => {  
171 - // if (jessibuca) {  
172 - // jessibuca.destroy();  
173 - // }  
174 - // createJessibuca();  
175 - // playing.value = false;  
176 - // loaded.value = false;  
177 - // }; 119 + const destroy = () => {
  120 + if (jessibuca) {
  121 + jessibuca.destroy();
  122 + }
  123 + createJessibuca();
  124 + isPlay.value = false;
  125 + };
178 126
179 onMounted(async () => { 127 onMounted(async () => {
180 - // init();  
181 - // await nextTick();  
182 - // // isPlay.value = unref(videoPlayInstance)?.paused();  
183 - // videoPlayInstance.value?.on('loadedmetadata', () => {  
184 - // console.log('视频长度');  
185 - // });  
186 - // videoPlayInstance.value?.on('waiting', () => {  
187 - // isPlay.value = false;  
188 - // console.log('视频加载中');  
189 - // });  
190 - // videoPlayInstance.value?.on('play', () => {  
191 - // isPlay.value = true;  
192 - // console.log('视频开始播放');  
193 - // });  
194 - // videoPlayInstance.value?.on('playing', () => {  
195 - // isPlay.value = true;  
196 - // console.log('正在播放');  
197 - // });  
198 - // videoPlayInstance.value?.on('pause', () => {  
199 - // isPlay.value = false;  
200 - // console.log('暂停播放');  
201 - // });  
202 - // videoPlayInstance.value?.on('ended', () => {  
203 - // isPlay.value = false;  
204 - // console.log('结束播放');  
205 - // });  
206 -  
207 createJessibuca(); 128 createJessibuca();
208 await nextTick(); 129 await nextTick();
209 jessibuca?.play(playUrl.value); 130 jessibuca?.play(playUrl.value);
  131 + isPlay.value = jessibuca?.isPlaying();
210 132
211 - jessibuca?.on('play', () => {  
212 - console.log('播放'); 133 + // 是否播放
  134 + jessibuca?.on('play', function () {
  135 + isPlay.value = true;
213 }); 136 });
214 - jessibuca.on('pause', () => {  
215 - console.log('暂停'); 137 +
  138 + // 是否暂停
  139 + jessibuca?.on('pause', () => {
  140 + isPlay.value = false;
216 }); 141 });
217 142
218 jessibuca?.on('videoInfo', (data) => { 143 jessibuca?.on('videoInfo', (data) => {
219 - console.log(data, 'data'); 144 + let { width, height } = data || {};
  145 + width = isNumber(width) ? (`${width}px` as unknown as number) : width;
  146 + height = isNumber(height) ? (`${height}px` as unknown as number) : height;
  147 + videoInfo.value = {
  148 + width,
  149 + height,
  150 + };
  151 + });
  152 +
  153 + // 播放报错事件
  154 + jessibuca?.on('error', (error) => {
  155 + error == 'playError' && createMessage.warning('播放错误');
  156 + error == 'fetchError' && createMessage.warning('http请求失败');
  157 + error == 'websocketError' && createMessage.warning('websocket 请求失败');
  158 + error == 'webcodecsH265NotSupport' && createMessage.warning('webcodecs 解码失败');
  159 + error == 'mediaSourceH265NotSupport' && createMessage.warning('mediaSource 解码失败');
  160 + error == 'wasmDecodeError' && createMessage.warning('wasm 解码失败');
220 }); 161 });
221 }); 162 });
222 163
223 onUnmounted(() => { 164 onUnmounted(() => {
224 - // unref(videoPlayInstance)?.dispose();  
225 - // videoPlayInstance.value = null;  
226 - // emit('onUnmounted');  
227 -  
228 jessibuca && jessibuca.destroy(); 165 jessibuca && jessibuca.destroy();
229 }); 166 });
230 167
231 defineExpose({ 168 defineExpose({
232 - reloadPlayer: init,  
233 - getInstance: () => unref(videoPlayInstance), 169 + handleDestroy: destroy,
234 }); 170 });
235 </script> 171 </script>
236 172
237 <template> 173 <template>
238 - <div :class="prefixCls" class="!w-full h-full flex" :style="getWidthHeight"> 174 + <div :class="prefixCls" class="!w-full h-full flex" :style="videoInfo">
239 <!-- <video 175 <!-- <video
240 ref="videoPlayEl" 176 ref="videoPlayEl"
241 class="video-js vjs-big-play-centered vjs-show-big-play-button-on-pause !w-8/10 !h-full" 177 class="video-js vjs-big-play-centered vjs-show-big-play-button-on-pause !w-8/10 !h-full"
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 <div class="flex items-center justify-center w-full h-full min-h-96 video-container"> 13 <div class="flex items-center justify-center w-full h-full min-h-96 video-container">
14 <Video 14 <Video
15 v-if="showVideo" 15 v-if="showVideo"
  16 + ref="jessibucaREF"
16 :options="(options as any)" 17 :options="(options as any)"
17 :withToken="withToken" 18 :withToken="withToken"
18 @on-unmounted="handleCloseFlvPlayUrl" 19 @on-unmounted="handleCloseFlvPlayUrl"
@@ -41,6 +42,8 @@ @@ -41,6 +42,8 @@
41 42
42 const withToken = ref(false); 43 const withToken = ref(false);
43 44
  45 + const jessibucaREF = ref();
  46 +
44 const fingerprintResult = ref<Nullable<GetResult>>(null); 47 const fingerprintResult = ref<Nullable<GetResult>>(null);
45 48
46 const options = reactive<VideoJsPlayerOptions>({ 49 const options = reactive<VideoJsPlayerOptions>({
@@ -92,6 +95,7 @@ @@ -92,6 +95,7 @@
92 }; 95 };
93 96
94 const handleCancel = () => { 97 const handleCancel = () => {
  98 + unref(jessibucaREF)?.handleDestroy();
95 showVideo.value = false; 99 showVideo.value = false;
96 withToken.value = false; 100 withToken.value = false;
97 }; 101 };