Commit 71f659d33b87af183e2fae772fe8f80062252de1

Authored by loveumiko
1 parent 416f565c

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

... ... @@ -135,7 +135,7 @@
135 135 jessibuca?.on('play', () => {
136 136 console.log('播放');
137 137 });
138   - jessibuca.on('pause', () => {
  138 + jessibuca?.on('pause', () => {
139 139 console.log('暂停');
140 140 });
141 141
... ...
1 1 <script lang="ts" setup>
2 2 import { isNumber } from 'lodash';
3   - import videoJs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js';
  3 + // import videoJs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js';
4 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 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 9 import 'videojs-flvjs-es6';
10 10 import {
11 11 CaretUpOutlined,
... ... @@ -18,73 +18,42 @@
18 18 } from '@ant-design/icons-vue';
19 19 import { Button } from 'ant-design-vue';
20 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 23 // import JessibucaDemo from './components/JessibucaDemo.vue';
23 24
24 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 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 41 const playUrl = ref('http://flv.bdplay.nodemedia.cn/live/bbb.flv');
74 42
  43 + const { createMessage } = useMessage();
  44 +
75 45 let jessibuca: Jessibuca | null = null;
76 46 const container = ref(null);
77 47 const createJessibuca = () => {
78 48 jessibuca = new (window as any).Jessibuca({
79   - container: container.value,
  49 + decoder: '/jessibuca/decoder.js',
  50 + container: container.value, //播放器容器
80 51 videoBuffer: 0.2, // 缓存时长
81 52 isResize: true,
82 53 isFullResize: true,
83 54 text: '',
84   - debug: false,
85   - // background: "bg.jpg",
86 55 loadingText: '加载中',
87   - // hasAudio:false,
  56 + hasAudio: false,
88 57 debug: true,
89 58 showBandwidth: true, // 显示网速
90 59 operateBtns: {
... ... @@ -93,32 +62,25 @@
93 62 play: true,
94 63 audio: true,
95 64 },
96   - controlAutoHide: true,
  65 + controlAutoHide: true, // 底部控制台是否自动隐藏
97 66 ifFlv: false,
98   - forceNoOffscreen: true,
99   - isNotMute: false,
100   - decoder: '/jessibuca/decoder.js',
  67 + forceNoOffscreen: true, //是否不使用离屏模式(提升渲染能力)
  68 + isNotMute: false, // 是否开启声音,默认是关闭声音播放的。
101 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 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 86 const handleTopClick = async () => {
... ... @@ -153,89 +115,63 @@
153 115
154 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 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 128 createJessibuca();
208 129 await nextTick();
209 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 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 164 onUnmounted(() => {
224   - // unref(videoPlayInstance)?.dispose();
225   - // videoPlayInstance.value = null;
226   - // emit('onUnmounted');
227   -
228 165 jessibuca && jessibuca.destroy();
229 166 });
230 167
231 168 defineExpose({
232   - reloadPlayer: init,
233   - getInstance: () => unref(videoPlayInstance),
  169 + handleDestroy: destroy,
234 170 });
235 171 </script>
236 172
237 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 175 <!-- <video
240 176 ref="videoPlayEl"
241 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 13 <div class="flex items-center justify-center w-full h-full min-h-96 video-container">
14 14 <Video
15 15 v-if="showVideo"
  16 + ref="jessibucaREF"
16 17 :options="(options as any)"
17 18 :withToken="withToken"
18 19 @on-unmounted="handleCloseFlvPlayUrl"
... ... @@ -41,6 +42,8 @@
41 42
42 43 const withToken = ref(false);
43 44
  45 + const jessibucaREF = ref();
  46 +
44 47 const fingerprintResult = ref<Nullable<GetResult>>(null);
45 48
46 49 const options = reactive<VideoJsPlayerOptions>({
... ... @@ -92,6 +95,7 @@
92 95 };
93 96
94 97 const handleCancel = () => {
  98 + unref(jessibucaREF)?.handleDestroy();
95 99 showVideo.value = false;
96 100 withToken.value = false;
97 101 };
... ...