| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- 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 { useWebRtcRtmpToRtc } from '@/hooks/webrtc/rtmpToRtc';
- import {
- DanmuMsgTypeEnum,
- LiveLineEnum,
- LiveRenderEnum,
- WsMessageContentTypeEnum,
- WsMessageMsgIsFileEnum,
- } from '@/interface';
- import { useAppStore } from '@/store/app';
- import { useCacheStore } from '@/store/cache';
- import { useNetworkStore } from '@/store/network';
- import {
- ILiveRoom,
- LiveRoomTypeEnum,
- LiveRoomUseCDNEnum,
- } from '@/types/ILiveRoom';
- import { WsMessageType, WsMsgTypeEnum } from '@/types/websocket';
- import { createVideo, videoFullBox, videoToCanvas } from '@/utils';
- export function usePull() {
- const route = useRoute();
- const networkStore = useNetworkStore();
- const cacheStore = useCacheStore();
- const appStore = useAppStore();
- const danmuStr = ref('');
- const roomId = ref('');
- const msgIsFile = ref(WsMessageMsgIsFileEnum.no);
- const danmuMsgType = ref<DanmuMsgTypeEnum>(DanmuMsgTypeEnum.danmu);
- const liveRoomInfo = ref<ILiveRoom>();
- 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 remoteVideo = ref<Array<HTMLVideoElement | HTMLCanvasElement>>([]);
- const remoteStream = ref<MediaStream[]>([]);
- const { mySocketId, initWs, roomLiving, anchorInfo, liveUserList, damuList } =
- useWebsocket();
- const { updateWebRtcRtmpToRtcConfig, webRtcRtmpToRtc } = useWebRtcRtmpToRtc();
- const { flvVideoEl, flvIsPlaying, startFlvPlay, destroyFlv } = useFlvPlay();
- const { hlsVideoEl, hlsIsPlaying, startHlsPlay, destroyHls } = useHlsPlay();
- const stopDrawingArr = ref<any[]>([]);
- const rtcVideo = ref<HTMLVideoElement[]>([]);
- let changeWrapSizeFn;
- onUnmounted(() => {
- handleStopDrawing();
- destroyFlv();
- destroyHls();
- });
- function handleStopDrawing() {
- changeWrapSizeFn = undefined;
- stopDrawingArr.value.forEach((cb) => cb());
- stopDrawingArr.value = [];
- remoteVideo.value.forEach((el) => el.remove());
- remoteVideo.value = [];
- }
- function handleVideoWrapResize() {
- nextTick(() => {
- if (videoWrapRef.value) {
- const rect = videoWrapRef.value.getBoundingClientRect();
- changeWrapSizeFn?.({ width: rect.width, height: rect.height });
- }
- });
- }
- function videoPlay(videoEl: HTMLVideoElement) {
- stopDrawingArr.value.forEach((cb) => cb());
- stopDrawingArr.value = [];
- 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);
- 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);
- videoLoading.value = false;
- }
- }
- }
- watch(
- () => hlsVideoEl.value,
- (newval) => {
- if (newval) {
- // @ts-ignore
- remoteStream.value.push(newval.captureStream());
- }
- }
- );
- watch(
- () => flvVideoEl.value,
- (newval) => {
- if (newval) {
- // @ts-ignore
- remoteStream.value.push(newval.captureStream());
- }
- }
- );
- watch(
- () => appStore.videoControlsValue.pageFullMode,
- () => {
- handleVideoWrapResize();
- }
- );
- watch(
- [() => appStore.videoControls.renderMode, () => remoteStream.value],
- () => {
- handleStopDrawing();
- remoteStream.value.forEach((v) => {
- const el = createVideo({});
- el.srcObject = v;
- videoPlay(el);
- });
- },
- {
- deep: true,
- }
- );
- watch(
- () => remoteVideo.value,
- (newval) => {
- newval.forEach((videoEl) => {
- videoWrapRef.value?.appendChild(videoEl);
- });
- },
- {
- deep: true,
- immediate: true,
- }
- );
- watch(
- () => cacheStore.muted,
- (newVal) => {
- appStore.pageIsClick = true;
- rtcVideo.value.forEach((v) => {
- v.muted = newVal;
- });
- if (!newVal) {
- cacheStore.volume = cacheStore.volume || appStore.normalVolume;
- } else {
- cacheStore.volume = 0;
- }
- }
- );
- watch(
- () => cacheStore.volume,
- (newVal) => {
- rtcVideo.value.forEach((v) => {
- v.volume = newVal / 100;
- });
- if (!newVal) {
- cacheStore.muted = true;
- } else {
- cacheStore.muted = false;
- }
- },
- {
- immediate: true,
- }
- );
- function handleRtmpToRtcPlay() {
- console.log('handleRtmpToRtcPlay');
- handleStopDrawing();
- videoLoading.value = true;
- appStore.liveLine = LiveLineEnum['rtmp-rtc'];
- updateWebRtcRtmpToRtcConfig({
- isPk: false,
- roomId: roomId.value,
- });
- const videoEl = createVideo({
- appendChild: true,
- muted: appStore.pageIsClick ? cacheStore.muted : true,
- });
- rtcVideo.value.push(videoEl);
- webRtcRtmpToRtc.newWebRtc({
- sender: mySocketId.value,
- receiver: 'rtmpToRtc',
- videoEl,
- sucessCb: (stream) => {
- remoteStream.value.push(stream);
- },
- });
- webRtcRtmpToRtc.sendOffer({
- sender: mySocketId.value,
- receiver: 'rtmpToRtc',
- });
- }
- function handleHlsPlay() {
- console.log('handleHlsPlay', hlsurl.value);
- handleStopDrawing();
- videoLoading.value = true;
- appStore.liveLine = LiveLineEnum.hls;
- startHlsPlay({
- hlsurl: hlsurl.value,
- });
- }
- function handleFlvPlay() {
- console.log('handleFlvPlay', flvurl.value);
- handleStopDrawing();
- videoLoading.value = true;
- appStore.liveLine = 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.liveLine = 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);
- handleStopDrawing();
- destroyFlv();
- destroyHls();
- remoteStream.value = [];
- if (!roomLiving.value) {
- return;
- }
- switch (newVal) {
- case LiveLineEnum.flv:
- handleFlvPlay();
- break;
- case LiveLineEnum.hls:
- handleHlsPlay();
- break;
- case LiveLineEnum.rtc:
- break;
- case LiveLineEnum['rtmp-rtc']:
- handleRtmpToRtcPlay();
- break;
- }
- }
- );
- watch(
- () => hlsIsPlaying.value,
- (newVal) => {
- isPlaying.value = newVal;
- }
- );
- watch(
- () => flvIsPlaying.value,
- (newVal) => {
- isPlaying.value = newVal;
- }
- );
- function initRoomId(id: string) {
- roomId.value = id;
- }
- function initPull(data: { autolay?: boolean }) {
- if (data.autolay === undefined) {
- autoplayVal.value = true;
- } else {
- autoplayVal.value = data.autolay;
- }
- initWs({
- roomId: roomId.value,
- 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 sendDanmuReward(txt: string) {
- if (!loginTip()) {
- return;
- }
- if (!commentAuthTip()) {
- return;
- }
- if (!txt.trim().length) {
- window.$message.warning('请输入弹幕内容!');
- return;
- }
- const instance = networkStore.wsMap.get(roomId.value);
- if (!instance) return;
- const messageData: WsMessageType['data'] = {
- content: txt,
- content_type: WsMessageContentTypeEnum.txt,
- msg_type: DanmuMsgTypeEnum.reward,
- live_room_id: Number(roomId.value),
- isBilibili: false,
- };
- instance.send({
- requestId: getRandomString(8),
- msgType: WsMsgTypeEnum.message,
- data: messageData,
- });
- }
- function sendDanmuTxt(txt: string) {
- if (!loginTip()) {
- return;
- }
- if (!commentAuthTip()) {
- return;
- }
- if (!txt.trim().length) {
- window.$message.warning('请输入弹幕内容!');
- return;
- }
- const instance = networkStore.wsMap.get(roomId.value);
- if (!instance) return;
- const messageData: WsMessageType['data'] = {
- content: txt,
- content_type: WsMessageContentTypeEnum.txt,
- msg_type: DanmuMsgTypeEnum.danmu,
- live_room_id: Number(roomId.value),
- isBilibili: false,
- };
- instance.send({
- requestId: getRandomString(8),
- msgType: WsMsgTypeEnum.message,
- data: messageData,
- });
- danmuStr.value = '';
- }
- function sendDanmuImg(url: string) {
- if (!loginTip()) {
- return;
- }
- if (!commentAuthTip()) {
- return;
- }
- if (!url.trim().length) {
- window.$message.warning('图片不能为空!');
- return;
- }
- const instance = networkStore.wsMap.get(roomId.value);
- 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.value),
- isBilibili: false,
- };
- instance.send({
- requestId,
- msgType: WsMsgTypeEnum.message,
- data: messageData,
- });
- }
- return {
- initWs,
- videoWrapRef,
- handlePlay,
- handleStopDrawing,
- initPull,
- closeWs,
- closeRtc,
- keydownDanmu,
- sendDanmuReward,
- sendDanmuTxt,
- sendDanmuImg,
- showPlayBtn,
- danmuMsgType,
- isPlaying,
- msgIsFile,
- mySocketId,
- videoResolution,
- remoteVideo,
- roomLiving,
- autoplayVal,
- videoLoading,
- damuList,
- liveUserList,
- danmuStr,
- liveRoomInfo,
- anchorInfo,
- initRoomId,
- };
- }
|