| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- import { getRandomString } from 'billd-utils';
- import { nextTick, onUnmounted, ref, watch } from 'vue';
- import { useRoute } from 'vue-router';
- import { commentAuthTip, loginTip } from '@/hooks/use-login';
- import { useFlvPlay, useHlsPlay } from '@/hooks/use-play';
- import { useWebsocket } from '@/hooks/use-websocket';
- import {
- DanmuMsgTypeEnum,
- LiveLineEnum,
- LiveRenderEnum,
- WsMessageContentTypeEnum,
- WsMessageMsgIsFileEnum,
- } from '@/interface';
- import { useAppStore } from '@/store/app';
- import { usePiniaCacheStore } from '@/store/cache';
- import { useNetworkStore } from '@/store/network';
- import {
- ILiveRoom,
- LiveRoomTypeEnum,
- LiveRoomUseCDNEnum,
- } from '@/types/ILiveRoom';
- import { WsMessageType, WsMsgTypeEnum } from '@/types/websocket';
- import { videoFullBox, videoToCanvas } from '@/utils';
- export function usePull(roomId: string) {
- const route = useRoute();
- const networkStore = useNetworkStore();
- const cacheStore = usePiniaCacheStore();
- const appStore = useAppStore();
- const danmuStr = ref('');
- const msgIsFile = ref(WsMessageMsgIsFileEnum.no);
- const danmuMsgType = ref<DanmuMsgTypeEnum>(DanmuMsgTypeEnum.danmu);
- const autoplayVal = ref(false);
- const videoLoading = ref(false);
- const isPlaying = ref(false);
- const showPlayBtn = ref(false);
- const flvurl = ref('');
- const hlsurl = ref('');
- const videoWrapRef = ref<HTMLDivElement>();
- const videoResolution = ref();
- const isRemoteDesk = ref(false);
- const videoElArr = ref<HTMLVideoElement[]>([]);
- const remoteVideo = ref<HTMLElement[]>([]);
- const { mySocketId, initWs, roomLiving, anchorInfo, liveUserList, damuList } =
- useWebsocket();
- const { flvVideoEl, flvIsPlaying, startFlvPlay, destroyFlv } = useFlvPlay();
- const { hlsVideoEl, hlsIsPlaying, startHlsPlay, destroyHls } = useHlsPlay();
- const stopDrawingArr = ref<any[]>([]);
- let changeWrapSizeFn;
- onUnmounted(() => {
- handleStopDrawing();
- });
- function handleStopDrawing() {
- destroyFlv();
- destroyHls();
- changeWrapSizeFn = undefined;
- stopDrawingArr.value.forEach((cb) => cb());
- stopDrawingArr.value = [];
- remoteVideo.value.forEach((el) => el.remove());
- remoteVideo.value = [];
- if (isRemoteDesk.value && videoWrapRef.value) {
- videoWrapRef.value.removeAttribute('style');
- }
- }
- function handleVideoWrapResize() {
- nextTick(() => {
- if (videoWrapRef.value) {
- const rect = videoWrapRef.value.getBoundingClientRect();
- changeWrapSizeFn?.({ width: rect.width, height: rect.height });
- }
- });
- }
- function videoPlay(videoEl: HTMLVideoElement) {
- stopDrawingArr.value = [];
- stopDrawingArr.value.forEach((cb) => cb());
- if (appStore.videoControls.renderMode === LiveRenderEnum.canvas) {
- if (videoEl && videoWrapRef.value) {
- const rect = videoWrapRef.value.getBoundingClientRect();
- const { canvas, stopDrawing, changeWrapSize } = videoToCanvas({
- wrapSize: {
- width: rect.width,
- height: rect.height,
- },
- videoEl,
- videoResize: ({ w, h }) => {
- videoResolution.value = `${w}x${h}`;
- },
- });
- changeWrapSizeFn = changeWrapSize;
- stopDrawingArr.value.push(stopDrawing);
- remoteVideo.value.push(canvas);
- videoElArr.value.push(videoEl);
- videoLoading.value = false;
- }
- } else if (appStore.videoControls.renderMode === LiveRenderEnum.video) {
- if (videoEl && videoWrapRef.value) {
- const rect = videoWrapRef.value.getBoundingClientRect();
- const { changeWrapSize } = videoFullBox({
- wrapSize: {
- width: rect.width,
- height: rect.height,
- },
- videoEl,
- videoResize: ({ w, h }) => {
- videoResolution.value = `${w}x${h}`;
- },
- });
- changeWrapSizeFn = changeWrapSize;
- remoteVideo.value.push(videoEl);
- videoElArr.value.push(videoEl);
- videoLoading.value = false;
- }
- }
- }
- watch(hlsVideoEl, (newval) => {
- if (newval) {
- videoPlay(newval);
- }
- });
- watch(flvVideoEl, (newval) => {
- if (newval) {
- videoPlay(newval);
- }
- });
- watch(
- () => appStore.videoControlsValue.pageFullMode,
- () => {
- handleVideoWrapResize();
- }
- );
- watch(
- () => appStore.videoControls.renderMode,
- () => {
- if (appStore.liveRoomInfo) {
- handlePlay(appStore.liveRoomInfo);
- }
- }
- );
- watch(
- () => networkStore.rtcMap,
- (newVal) => {
- if (newVal.size) {
- roomLiving.value = true;
- videoLoading.value = false;
- appStore.playing = true;
- // cacheStore.muted = false;
- }
- if (
- isRemoteDesk.value ||
- appStore.liveRoomInfo?.type === LiveRoomTypeEnum.wertc_meeting_one ||
- appStore.liveRoomInfo?.type === LiveRoomTypeEnum.wertc_live ||
- appStore.liveRoomInfo?.type === LiveRoomTypeEnum.pk ||
- appStore.liveRoomInfo?.type === LiveRoomTypeEnum.tencent_css_pk
- ) {
- newVal.forEach((item) => {
- if (appStore.allTrack.find((v) => v.mediaName === item.receiver)) {
- return;
- }
- const rect = videoWrapRef.value?.getBoundingClientRect();
- if (rect) {
- videoFullBox({
- wrapSize: {
- width: rect.width,
- height: rect.height,
- },
- videoEl: item.videoEl,
- videoResize: ({ w, h }) => {
- videoResolution.value = `${w}x${h}`;
- },
- });
- remoteVideo.value.push(item.videoEl);
- videoElArr.value.push(item.videoEl);
- }
- });
- nextTick(() => {
- if (isRemoteDesk.value && videoWrapRef.value) {
- if (newVal.size) {
- videoWrapRef.value.style.display = 'inline-block';
- } else {
- videoWrapRef.value.style.removeProperty('display');
- }
- }
- });
- }
- },
- {
- deep: true,
- immediate: true,
- }
- );
- watch(
- () => remoteVideo.value,
- (newval) => {
- newval.forEach((videoEl) => {
- videoWrapRef.value?.appendChild(videoEl);
- });
- },
- {
- deep: true,
- immediate: true,
- }
- );
- function handleHlsPlay() {
- console.log('handleHlsPlay', hlsurl.value);
- handleStopDrawing();
- videoLoading.value = true;
- appStore.setLiveLine(LiveLineEnum.hls);
- startHlsPlay({
- hlsurl: hlsurl.value,
- });
- }
- function handleFlvPlay() {
- console.log('handleFlvPlay', flvurl.value);
- handleStopDrawing();
- videoLoading.value = true;
- appStore.setLiveLine(LiveLineEnum.flv);
- startFlvPlay({
- flvurl: flvurl.value,
- });
- }
- function handlePlay(data: ILiveRoom) {
- roomLiving.value = true;
- flvurl.value =
- data.cdn === LiveRoomUseCDNEnum.yes &&
- [LiveRoomTypeEnum.tencent_css, LiveRoomTypeEnum.tencent_css_pk].includes(
- data.type!
- )
- ? data.cdn_flv_url!
- : data.flv_url!;
- hlsurl.value =
- data.cdn === LiveRoomUseCDNEnum.yes &&
- [LiveRoomTypeEnum.tencent_css, LiveRoomTypeEnum.tencent_css_pk].includes(
- data.type!
- )
- ? data.cdn_hls_url!
- : data.hls_url!;
- function play() {
- if (appStore.liveLine === LiveLineEnum.flv) {
- handleFlvPlay();
- } else if (appStore.liveLine === LiveLineEnum.hls) {
- handleHlsPlay();
- }
- }
- if (LiveRoomTypeEnum.pk === data.type && !route.query.pkKey) {
- play();
- } else if (
- [
- LiveRoomTypeEnum.system,
- LiveRoomTypeEnum.srs,
- LiveRoomTypeEnum.obs,
- LiveRoomTypeEnum.msr,
- LiveRoomTypeEnum.pk,
- LiveRoomTypeEnum.forward_bilibili,
- LiveRoomTypeEnum.forward_huya,
- LiveRoomTypeEnum.forward_all,
- LiveRoomTypeEnum.tencent_css,
- LiveRoomTypeEnum.tencent_css_pk,
- ].includes(data.type!)
- ) {
- play();
- } else if (
- [
- LiveRoomTypeEnum.wertc_live,
- LiveRoomTypeEnum.wertc_meeting_one,
- LiveRoomTypeEnum.wertc_meeting_two,
- ].includes(data.type!)
- ) {
- appStore.setLiveLine(LiveLineEnum.rtc);
- }
- }
- watch(
- [() => roomLiving.value, () => appStore.liveRoomInfo],
- ([val, liveRoomInfo]) => {
- if (val && liveRoomInfo) {
- showPlayBtn.value = false;
- if (
- [
- LiveRoomTypeEnum.system,
- LiveRoomTypeEnum.msr,
- LiveRoomTypeEnum.srs,
- LiveRoomTypeEnum.obs,
- LiveRoomTypeEnum.tencent_css,
- LiveRoomTypeEnum.tencent_css_pk,
- LiveRoomTypeEnum.forward_bilibili,
- LiveRoomTypeEnum.forward_huya,
- LiveRoomTypeEnum.forward_all,
- ].includes(liveRoomInfo.type!)
- ) {
- handlePlay(liveRoomInfo!);
- } else if (LiveRoomTypeEnum.pk === liveRoomInfo.type!) {
- if (!route.query.pkKey) {
- handlePlay(liveRoomInfo!);
- }
- }
- }
- if (!roomLiving.value) {
- closeRtc();
- handleStopDrawing();
- }
- },
- {
- deep: true,
- immediate: true,
- }
- );
- watch(
- () => appStore.liveLine,
- (newVal) => {
- console.log('liveLine变了', newVal);
- if (!roomLiving.value) {
- return;
- }
- switch (newVal) {
- case LiveLineEnum.flv:
- handleFlvPlay();
- break;
- case LiveLineEnum.hls:
- handleHlsPlay();
- break;
- case LiveLineEnum.rtc:
- break;
- }
- }
- );
- watch(
- () => cacheStore.muted,
- (newVal) => {
- videoElArr.value.forEach((el) => {
- el.muted = newVal;
- });
- if (!newVal) {
- cacheStore.volume = cacheStore.volume || appStore.normalVolume;
- } else {
- cacheStore.volume = 0;
- }
- }
- );
- watch(
- () => cacheStore.volume,
- (newVal) => {
- videoElArr.value.forEach((el) => {
- el.volume = newVal / 100;
- });
- if (!newVal) {
- cacheStore.muted = true;
- } else {
- cacheStore.muted = false;
- }
- }
- );
- watch(
- () => appStore.playing,
- (newVal) => {
- videoElArr.value.forEach((el) => {
- if (newVal) {
- el.play();
- } else {
- el.pause();
- }
- });
- }
- );
- watch(
- () => hlsIsPlaying.value,
- (newVal) => {
- isPlaying.value = newVal;
- }
- );
- watch(
- () => flvIsPlaying.value,
- (newVal) => {
- isPlaying.value = newVal;
- }
- );
- watch(
- () => appStore.remoteDesk.isClose,
- (newval) => {
- if (newval) {
- handleStopDrawing();
- }
- }
- );
- function initPull(data: { autolay?: boolean; isRemoteDesk?: boolean }) {
- if (data.autolay === undefined) {
- autoplayVal.value = true;
- } else {
- autoplayVal.value = data.autolay;
- }
- if (autoplayVal.value) {
- videoLoading.value = true;
- }
- isRemoteDesk.value = !!data.isRemoteDesk;
- initWs({
- isRemoteDesk: data.isRemoteDesk,
- roomId,
- isAnchor: false,
- });
- }
- function closeWs() {
- networkStore.wsMap.forEach((ws) => {
- networkStore.removeWs(ws.roomId);
- });
- }
- function closeRtc() {
- networkStore.rtcMap.forEach((rtc) => {
- networkStore.removeRtc(rtc.receiver);
- });
- }
- function keydownDanmu(event: KeyboardEvent) {
- const key = event.key.toLowerCase();
- if (key === 'enter') {
- event.preventDefault();
- sendDanmuTxt(danmuStr.value);
- }
- }
- function sendDanmuTxt(txt: string) {
- if (!loginTip()) {
- return;
- }
- if (!commentAuthTip()) {
- return;
- }
- if (!txt.trim().length) {
- window.$message.warning('请输入弹幕内容!');
- return;
- }
- const instance = networkStore.wsMap.get(roomId);
- if (!instance) return;
- const messageData: WsMessageType['data'] = {
- content: txt,
- content_type: WsMessageContentTypeEnum.txt,
- msg_type: DanmuMsgTypeEnum.danmu,
- live_room_id: Number(roomId),
- isBilibili: false,
- };
- instance.send({
- requestId: getRandomString(8),
- msgType: WsMsgTypeEnum.message,
- data: messageData,
- });
- }
- function sendDanmuImg(url: string) {
- if (!loginTip()) {
- return;
- }
- if (!commentAuthTip()) {
- return;
- }
- if (!url.trim().length) {
- window.$message.warning('图片不能为空!');
- return;
- }
- const instance = networkStore.wsMap.get(roomId);
- if (!instance) return;
- const requestId = getRandomString(8);
- const messageData: WsMessageType['data'] = {
- content: url,
- content_type: WsMessageContentTypeEnum.img,
- msg_type: DanmuMsgTypeEnum.danmu,
- live_room_id: Number(roomId),
- isBilibili: false,
- };
- instance.send({
- requestId,
- msgType: WsMsgTypeEnum.message,
- data: messageData,
- });
- }
- return {
- initWs,
- videoWrapRef,
- handlePlay,
- handleStopDrawing,
- initPull,
- closeWs,
- closeRtc,
- keydownDanmu,
- sendDanmuTxt,
- sendDanmuImg,
- showPlayBtn,
- danmuMsgType,
- isPlaying,
- msgIsFile,
- mySocketId,
- videoResolution,
- remoteVideo,
- roomLiving,
- autoplayVal,
- videoLoading,
- damuList,
- liveUserList,
- danmuStr,
- anchorInfo,
- };
- }
|