Commit cce054dc8eb63d825e5daeb353f581958d795570
Merge branch 'feat/device-new-protocol' of http://git.yunteng.com/yunteng/things…
…kit-front into feat/device-new-protocol
Showing
3 changed files
with
72 additions
and
132 deletions
| 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 | }; | ... | ... |