123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- import consola from 'consola';
- import { computed, nextTick, ref, unref } from 'vue';
- import TRTC from 'trtc-js-sdk';
- import type { LocalStream, Client, RemoteStream } from 'trtc-js-sdk';
- import { useRtcStore } from '/@/store/modules/rtc';
- // import Dialog from '/@/components/basic/dialog';
- import { useI18n } from './useI18n';
- import { useMiniApp } from './useMiniApp';
- import { useRoom } from './useRoom';
- let localClient: Client;
- let localStream: LocalStream;
- const invitedRemoteStreams = ref<RemoteStream[]>([]);
- const muteAudioLeader = ref(false);
- const muteVideoLeader = ref(false);
- const { isUsingMiniApp } = useMiniApp();
- const globalVideoEnable = computed(
- () => Number(import.meta.env.VITE_ENABLE_VIDEO) === 1 && unref(isUsingMiniApp),
- );
- export const checkDevice = async () => {
- try {
- const rtcStore = useRtcStore();
- const microphoneItems = await TRTC.getMicrophones();
- console.log('microphoneItems', microphoneItems);
- microphoneItems.forEach((item) => {
- item['value'] = item.deviceId;
- });
- if (microphoneItems?.length) {
- rtcStore.setAudioDeviceId(
- microphoneItems[0].deviceId || microphoneItems[0].groupId || 'default',
- );
- } else {
- rtcStore.setAudioDeviceId('');
- }
- const camerasItems = await TRTC.getCameras();
- console.log('camerasItems', camerasItems);
- camerasItems.forEach((item) => {
- item['value'] = item.deviceId;
- });
- if (camerasItems?.length) {
- rtcStore.setVideoDeviceId(camerasItems[0].deviceId || camerasItems[0].groupId || 'default');
- } else {
- rtcStore.setVideoDeviceId('');
- }
- } catch (error) {
- console.log('error', error);
- }
- };
- const checkSystemRequirements = async () => {
- const result = await TRTC.checkSystemRequirements();
- console.log('result', result);
- const isSmallStreamSupported = await TRTC.isSmallStreamSupported();
- console.log('isSmallStreamSupported', isSmallStreamSupported);
- };
- // interface UseRtcSdkType {
- // createRTCSocket: () => Promise<void>
- // }
- async function createLocalStream() {
- try {
- const rtcStore = useRtcStore();
- const enableVideo =
- rtcStore.isLeader && rtcStore.videoDeviceId?.length > 0 && unref(globalVideoEnable);
- console.warn('enableVideo', enableVideo, unref(globalVideoEnable));
- localStream = TRTC.createStream({
- userId: rtcStore.userId,
- audio: true,
- video: enableVideo,
- cameraId: rtcStore.videoDeviceId,
- microphoneId: rtcStore.audioDeviceId,
- });
- //开大小流
- const isSmallStreamSupported = TRTC.isSmallStreamSupported();
- if (isSmallStreamSupported) {
- await localClient.enableSmallStream();
- localClient.setSmallStreamProfile({
- width: 160,
- height: 90,
- bitrate: 100,
- frameRate: 15,
- });
- } else {
- localStream.setVideoProfile('360p');
- }
- //
- await localStream.initialize();
- return Promise.resolve();
- // if (rtcStore.audioMuted) {
- // localStream.muteAudio();
- // }
- } catch (error) {
- console.log(error, 'createStream');
- return Promise.reject(error);
- }
- }
- async function createRTCSocket(): Promise<void> {
- try {
- if (!unref(isUsingMiniApp)) {
- const rtcStore = useRtcStore();
- await checkSystemRequirements();
- await checkDevice();
- console.log('createRTCSocket', rtcStore.videoDeviceId);
- await handleJoin();
- } else {
- console.log('小程序关闭rtc入口');
- }
- } catch (error) {
- consola.error({
- tag: 'createRTCSocket',
- message: error,
- });
- }
- }
- async function handleJoin() {
- const rtcStore = useRtcStore();
- try {
- const { getSign } = useRoom();
- const res = await getSign(rtcStore.userId);
- console.warn('sign', res);
- localClient = TRTC.createClient({
- mode: 'rtc',
- sdkAppId: res.sdkAppId || parseInt(rtcStore.sdkAppId, 10),
- userId: rtcStore.userId,
- userSig: res.sign || rtcStore.genUserSig,
- useStringRoomId: true,
- enableAutoPlayDialog: false,
- });
- installEventHandlers();
- await localClient.join({ roomId: rtcStore.roomId });
- } catch (error) {
- console.error(error, 'error-----------');
- }
- await createLocalStream();
- await handlePublish();
- await nextTick();
- //
- // setTimeout(() => {
- const playLocal = () => {
- const playId = 'camera_box_' + rtcStore.userId;
- localStream
- .play(playId)
- .then(() => {
- consola.info({
- message: '本地采集成功!',
- tag: 'rtc:audio',
- });
- rtcStore.setIsRTCJoined(true);
- })
- .catch((error) => {
- consola.info({
- message: '本地采集失败!' + error,
- tag: 'rtc:audio',
- });
- setTimeout(() => {
- console.log('再次播放');
- playLocal();
- }, 500);
- });
- };
- playLocal();
- // }, 1000);
- // if (!rtcStore.isLeader) {
- localStream.muteAudio();
- console.log('参加者默认-muteAudio');
- // }
- localStream.on('error', (error) => {
- if (error.getCode() === 0x4043) {
- // 自动播放受限导致播放失败,此时引导用户点击页面。
- // 在点击事件的回调函数中,执行 stream.resume();
- const rtcStore = useRtcStore();
- const { t } = useI18n();
- rtcStore.showBaseDialog(
- {
- title: t('base.tips'),
- desc: t('base.audioPermission'),
- okTxt: t('base.confirm'),
- closeTxt: t('base.cancel'),
- },
- () => {
- localStream.resume();
- },
- );
- }
- });
- }
- async function handlePublish() {
- const rtcStore = useRtcStore();
- if (!rtcStore.isJoined) {
- return;
- }
- if (rtcStore.isPublished) {
- return;
- }
- // if (!rtcStore.isLeader) {
- // return;
- // }
- try {
- await localClient.unpublish(localStream);
- await localClient.publish(localStream);
- rtcStore.setIsPublished(true);
- } catch (error) {
- console.error(error, '---------------handlePublish--------------------');
- }
- }
- // async function handleStartShare() {
- // shareClient = new ShareClient({
- // sdkAppId: parseInt(store.getters["rtc/sdkAppId"], 10),
- // userId: `share${store.getters["rtc/userId"]}`,
- // roomId: store.getters["rtc/roomId"],
- // secretKey: store.getters["rtc/secretKey"],
- // useStringRoomId: true,
- // });
- // try {
- // await shareClient.join();
- // await shareClient.publish();
- // console.log("Start share screen success");
- // store.isShared = true;
- // } catch (error) {
- // console.error(`Start share error: ${error.message_}`);
- // }
- // }
- async function handleUnpublish() {
- const rtcStore = useRtcStore();
- if (!rtcStore.isJoined) {
- return;
- }
- if (!rtcStore.isPublished) {
- return;
- }
- try {
- await localClient.unpublish(localStream);
- // store.commit("rtc/setIsPublished", false);
- rtcStore.setIsPublished(false);
- } catch (error) {
- console.error(error, '-----------handleUnpublish--------------');
- }
- }
- async function handleLeave() {
- const rtcStore = useRtcStore();
- if (rtcStore.isPublished) {
- await handleUnpublish();
- }
- try {
- uninstallEventHandlers();
- localClient && (await localClient.leave());
- localClient && localClient.destroy();
- // localClient = null;
- invitedRemoteStreams.value.forEach((item) => {
- item.stop();
- });
- invitedRemoteStreams.value = [];
- rtcStore.setVideoDeviceId('');
- rtcStore.setAudioDeviceId('');
- // store.commit("rtc/setVideoDeviceId", "");
- // store.commit("rtc/setAudioDeviceId", "");
- if (localStream) {
- localStream.stop();
- localStream.close();
- // localStream = null;
- console.log('有执行到这里-------------');
- }
- } catch (error) {
- console.error(error, '-----------handleLeave--------------');
- }
- }
- function installEventHandlers() {
- if (!localClient) {
- return;
- }
- localClient.on('error', handleError);
- localClient.on('client-banned', handleBanned);
- localClient.on('peer-join', handlePeerJoin);
- localClient.on('peer-leave', handlePeerLeave);
- localClient.on('stream-added', handleStreamAdded);
- localClient.on('stream-subscribed', handleStreamSubscribed);
- localClient.on('stream-removed', handleStreamRemoved);
- localClient.on('stream-updated', handleStreamUpdated);
- localClient.on('mute-video', handleMuteVideo);
- localClient.on('mute-audio', handleMuteAudio);
- localClient.on('unmute-video', handleUnmuteVideo);
- localClient.on('unmute-audio', handleUnmuteAudio);
- }
- function uninstallEventHandlers() {
- if (!localClient) {
- return;
- }
- localClient.off('error', handleError);
- localClient.off('client-banned', handleBanned);
- localClient.off('peer-join', handlePeerJoin);
- localClient.off('peer-leave', handlePeerLeave);
- localClient.off('stream-added', handleStreamAdded);
- localClient.off('stream-subscribed', handleStreamSubscribed);
- localClient.off('stream-removed', handleStreamRemoved);
- localClient.off('stream-updated', handleStreamUpdated);
- localClient.off('mute-video', handleMuteVideo);
- localClient.off('mute-audio', handleMuteAudio);
- localClient.off('unmute-video', handleUnmuteVideo);
- localClient.off('unmute-audio', handleUnmuteAudio);
- }
- function handleMuteVideo(event) {
- console.log(`[${event.userId}] mute video`);
- const rtcStore = useRtcStore();
- const roomLeader = rtcStore.getRoomLeader();
- if (event.userId === roomLeader?.UserId) {
- muteVideoLeader.value = true;
- }
- }
- function handleMuteAudio(event) {
- if (event.userId.indexOf('leader') > -1) {
- muteAudioLeader.value = true;
- }
- console.log(event, `[] mute audio`);
- }
- function handleUnmuteVideo(event) {
- console.log(`[${event.userId}] unmute video`);
- const rtcStore = useRtcStore();
- const roomLeader = rtcStore.getRoomLeader();
- if (event.userId === roomLeader?.UserId) {
- muteVideoLeader.value = false;
- }
- }
- function handleUnmuteAudio(event) {
- console.log(`[${event.userId}] unmute audio`);
- if (event.userId.indexOf('leader') > -1) {
- muteAudioLeader.value = false;
- }
- }
- function handleError(error) {
- console.log(`LocalClient error: ${error.message_}`);
- }
- function handleBanned(error) {
- console.log(`Client has been banned for ${error.message_}`);
- }
- function handlePeerJoin(event) {
- const { userId } = event;
- if (userId !== 'local-screen') {
- console.log(`Peer Client [${userId}] joined`);
- }
- }
- function handlePeerLeave(event) {
- const { userId } = event;
- if (userId !== 'local-screen') {
- console.log(`[${userId}] leave`);
- }
- }
- function handleStreamAdded(event) {
- const remoteStream = event.stream;
- const id = remoteStream.getId();
- const userId = remoteStream.getUserId();
- const rtcStore = useRtcStore();
- console.log(remoteStream, '-------------remoteStream');
- if (remoteStream.getUserId() === rtcStore.userId) {
- // don't need to screen shared by us
- localClient.unsubscribe(remoteStream).catch((error) => {
- console.info(`unsubscribe failed: ${error.message_}`);
- });
- } else {
- console.log(`remote stream added: [${userId}] ID: ${id} type: ${remoteStream.getType()}`);
- localClient.subscribe(remoteStream).catch((error) => {
- console.info(`subscribe failed: ${error.message_}`);
- });
- }
- }
- async function handleStreamSubscribed(event) {
- const remoteStream = event.stream;
- const rtcStore = useRtcStore();
- // const { t } = useI18n();
- // debugger;
- const remoteUserId = remoteStream.getUserId();
- const remoteId = remoteStream.getId();
- if (remoteUserId == rtcStore.userId) {
- return;
- }
- if (!rtcStore.isIdInRemoteStream(remoteId)) {
- consola.info({
- message: remoteId,
- tag: 'rtc:audio',
- });
- rtcStore.pushRemoteStreams(remoteStream);
- // debugger
- }
- await nextTick();
- const playRemote = () => {
- // const playId = 'camera_remote_box_' + rtcStore.userId;
- const playId = 'cameraRemoteBox';
- remoteStream
- .play(playId)
- .then(() => {
- consola.info({
- message: '远端采集成功 !playId: ' + playId + ' remoteId:' + remoteId,
- tag: 'rtc:audio',
- });
- })
- .catch((error) => {
- consola.info({
- message: '远端采集失败!' + error,
- tag: 'rtc:audio',
- });
- setTimeout(() => {
- console.log('远端再次播放' + remoteId);
- playRemote();
- }, 500);
- });
- };
- playRemote();
- remoteStream.on('error', (error) => {
- if (error.getCode() === 0x4043) {
- // 自动播放受限导致播放失败,此时引导用户点击页面。
- // 在点击事件的回调函数中,执行 stream.resume();
- const rtcStore = useRtcStore();
- const { t } = useI18n();
- rtcStore.showBaseDialog(
- {
- title: t('base.tips'),
- desc: t('base.audioPermission'),
- okTxt: t('base.confirm'),
- closeTxt: t('base.cancel'),
- },
- () => {
- console.log('手机端', rtcStore.remoteStreams);
- rtcStore.remoteStreams.forEach((item) => {
- item.resume();
- });
- remoteStream.resume();
- },
- );
- }
- });
- // setTimeout(async () => {
- // try {
- // consola.info({
- // message: '客音源-->' + remoteId,
- // tag: 'rtc:audio',
- // });
- // consola.info({
- // message: rtcStore.remoteStreams,
- // tag: 'rtc:audio',
- // });
- // await remoteStream.play(remoteId);
- // } catch (error) {}
- // }, 200);
- }
- function handleStreamRemoved(event) {
- const remoteStream = event.stream;
- const userId = remoteStream.getUserId();
- const remoteStreamId = remoteStream.getId();
- consola.info({
- message: `远端流删除: [${userId},${remoteStreamId}]`,
- tag: 'rtc:audio',
- });
- const rtcStore = useRtcStore();
- rtcStore.removeRemoteStreams(remoteStreamId);
- const node = document.getElementById(`player_` + remoteStreamId);
- consola.info({
- message: `远端流删除:` + node,
- tag: 'rtc:audio',
- });
- if (node) {
- console.log('node', node);
- }
- }
- function handleStreamUpdated(event) {
- const remoteStream = event.stream;
- const userId = remoteStream.getUserId();
- console.log(
- `RemoteStream updated: [${userId}] audio:${remoteStream.hasAudio()} video:${remoteStream.hasVideo()}`,
- );
- }
- // const switchDevice = async ({ videoId, audioId }) => {
- // const rtcStore = useRtcStore();
- // if (!rtcStore.isJoined) {
- // return;
- // }
- // if (videoId) {
- // try {
- // await localStream.switchDevice('video', videoId);
- // } catch (error) {}
- // }
- // if (audioId) {
- // try {
- // await localStream.switchDevice('audio', audioId);
- // } catch (error) {}
- // }
- // };
- export function useRtcSdk() {
- return {
- createRTCSocket,
- handleJoin,
- handleLeave,
- localStream,
- muteVideoLeader,
- invitedRemoteStreams,
- client: localClient,
- globalVideoEnable,
- };
- }
|