|
@@ -1,14 +1,31 @@
|
|
|
|
|
|
import consola from "consola";
|
|
import consola from "consola";
|
|
|
|
+import { watch, nextTick, onMounted, onUnmounted, ref } from 'vue'
|
|
import TRTC from "trtc-js-sdk";
|
|
import TRTC from "trtc-js-sdk";
|
|
|
|
+import type { LocalStream, Client, RemoteStream } from "trtc-js-sdk";
|
|
import { useRtcStore } from "/@/store/modules/rtc";
|
|
import { useRtcStore } from "/@/store/modules/rtc";
|
|
import Dialog from '/@/components/basic/dialog'
|
|
import Dialog from '/@/components/basic/dialog'
|
|
|
|
+
|
|
|
|
+let localClient: Client;
|
|
|
|
+let localStream: LocalStream;
|
|
|
|
+const invitedRemoteStreams = ref<RemoteStream[]>([]);
|
|
|
|
+const muteAudioLeader = ref(false);
|
|
|
|
+const muteVideoLeader = ref(false);
|
|
|
|
+
|
|
|
|
+
|
|
export const updateDevice = async () => {
|
|
export const updateDevice = async () => {
|
|
console.log("updateDevice");
|
|
console.log("updateDevice");
|
|
|
|
+ const rtcStore = useRtcStore()
|
|
const microphoneItems = await TRTC.getMicrophones();
|
|
const microphoneItems = await TRTC.getMicrophones();
|
|
microphoneItems.forEach((item) => {
|
|
microphoneItems.forEach((item) => {
|
|
- console.log('item', item)
|
|
|
|
|
|
+ item['value'] = item.deviceId;
|
|
});
|
|
});
|
|
|
|
+ if (microphoneItems?.length) {
|
|
|
|
+ rtcStore.setAudioDeviceId(microphoneItems[0].deviceId)
|
|
|
|
+ } else {
|
|
|
|
+ rtcStore.setAudioDeviceId('')
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -21,24 +38,39 @@ const checkoutIsExistAudioInput = async () => {
|
|
// createRTCSocket: () => Promise<void>
|
|
// createRTCSocket: () => Promise<void>
|
|
// }
|
|
// }
|
|
|
|
|
|
|
|
+async function createLocalStream() {
|
|
|
|
+ try {
|
|
|
|
+ const rtcStore = useRtcStore()
|
|
|
|
+ localStream = TRTC.createStream({
|
|
|
|
+ userId: rtcStore.userId,
|
|
|
|
+ audio: true,
|
|
|
|
+ video: false,
|
|
|
|
+ microphoneId: rtcStore.audioDeviceId,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ await localStream.initialize();
|
|
|
|
+
|
|
|
|
+ if (rtcStore.audioMuted) {
|
|
|
|
+ localStream.muteAudio();
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.log(error, "createStream");
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
async function createRTCSocket(): Promise<void> {
|
|
async function createRTCSocket(): Promise<void> {
|
|
try {
|
|
try {
|
|
- console.log('Dialog', Dialog)
|
|
|
|
const rtcStore = useRtcStore()
|
|
const rtcStore = useRtcStore()
|
|
await checkoutIsExistAudioInput();
|
|
await checkoutIsExistAudioInput();
|
|
- const microphoneItems = await TRTC.getMicrophones();
|
|
|
|
- // debugger
|
|
|
|
- if (microphoneItems?.length) {
|
|
|
|
- const localStream = TRTC.createStream({
|
|
|
|
- userId: rtcStore.userId,
|
|
|
|
- audio: true,
|
|
|
|
- video: false,
|
|
|
|
- // microphoneId: store.getters["rtc/audioDeviceId"],
|
|
|
|
- microphoneId: rtcStore.audioDeviceId
|
|
|
|
- });
|
|
|
|
- console.log('localStream', localStream)
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ await updateDevice()
|
|
|
|
+ // const microphoneItems = await TRTC.getMicrophones();
|
|
|
|
+
|
|
|
|
+ // if (microphoneItems?.length) {
|
|
|
|
+
|
|
|
|
+ // }
|
|
|
|
+ await handleJoin();
|
|
|
|
+
|
|
} catch (error) {
|
|
} catch (error) {
|
|
consola.error({
|
|
consola.error({
|
|
tag: 'createRTCSocket',
|
|
tag: 'createRTCSocket',
|
|
@@ -46,10 +78,375 @@ async function createRTCSocket(): Promise<void> {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+async function handleJoin() {
|
|
|
|
+ try {
|
|
|
|
+ // let res = await apis.getSign({ userId: store.getters["rtc/userId"] });
|
|
|
|
+ const rtcStore = useRtcStore()
|
|
|
|
+ localClient = TRTC.createClient({
|
|
|
|
+ mode: "rtc",
|
|
|
|
+ sdkAppId: parseInt(rtcStore.sdkAppId, 10),
|
|
|
|
+ userId: rtcStore.userId,
|
|
|
|
+ userSig: rtcStore.genUserSig,
|
|
|
|
+ useStringRoomId: true,
|
|
|
|
+ enableAutoPlayDialog: false,
|
|
|
|
+ });
|
|
|
|
+ installEventHandlers();
|
|
|
|
+
|
|
|
|
+ await localClient.join({ roomId: rtcStore.roomId });
|
|
|
|
+ // store.commit("rtc/setIsJoined", true);
|
|
|
|
+ rtcStore.setIsJoined(true)
|
|
|
|
+ // inviteLink.value = store.commit("rtc/createShareLink");
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(error, "error-----------");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ await createLocalStream();
|
|
|
|
+ await handlePublish();
|
|
|
|
+ localStream
|
|
|
|
+ .play("local")
|
|
|
|
+ .then(() => {
|
|
|
|
+ consola.info({
|
|
|
|
+ message: "音采源",
|
|
|
|
+ tag: 'rtc:audio'
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ .catch((e) => {
|
|
|
|
+ console.log(localStream);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ localStream.on("error", (error) => {
|
|
|
|
+ if (error.getCode() === 0x4043) {
|
|
|
|
+ // 自动播放受限导致播放失败,此时引导用户点击页面。
|
|
|
|
+ // 在点击事件的回调函数中,执行 stream.resume();
|
|
|
|
+ Dialog.confirm({
|
|
|
|
+ showCloseIcon: false,
|
|
|
|
+ okText: "确定",
|
|
|
|
+ content:
|
|
|
|
+ "<span style='font-size: 16px; line-height: 1.5;'>在用户与网页产生交互(例如点击、触摸页面等)之前,网页将被禁止播放带有声音的媒体。点击恢复播放<span/>",
|
|
|
|
+ title: "隐私条款:",
|
|
|
|
+ single: true,
|
|
|
|
+ func: (state) => {
|
|
|
|
+ if (state == "ok") {
|
|
|
|
+ localStream.resume();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function handlePublish() {
|
|
|
|
+ const rtcStore = useRtcStore()
|
|
|
|
+
|
|
|
|
+ if (!rtcStore.isJoined) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (rtcStore.isPublished) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (!rtcStore.isLeader) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ try {
|
|
|
|
+ await localClient.publish(localStream);
|
|
|
|
+ // store.commit("rtc/setIsPublished", true);
|
|
|
|
+ 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();
|
|
|
|
+ await localClient.leave();
|
|
|
|
+ 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("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`);
|
|
|
|
+ if (event.userId.indexOf("leader") > -1) {
|
|
|
|
+ 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`);
|
|
|
|
+ if (event.userId.indexOf("leader") > -1) {
|
|
|
|
+ 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 remoteUserId = remoteStream.getUserId()
|
|
|
|
+ const remoteId = remoteStream.getId()
|
|
|
|
+ if (remoteUserId == rtcStore.userId) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!rtcStore.isUserInRemoteStream(remoteUserId)) {
|
|
|
|
+ rtcStore.pushRemoteStreams(remoteStream)
|
|
|
|
+ // debugger
|
|
|
|
+ }
|
|
|
|
+ await nextTick();
|
|
|
|
+ setTimeout(async () => {
|
|
|
|
+ try {
|
|
|
|
+ await remoteStream
|
|
|
|
+ .play(remoteId)
|
|
|
|
+ consola.info({
|
|
|
|
+ message: "客音源",
|
|
|
|
+ tag: 'rtc:audio'
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ } catch (error) {
|
|
|
|
+
|
|
|
|
+ Dialog.confirm({
|
|
|
|
+ showCloseIcon: false,
|
|
|
|
+ okText: "确定",
|
|
|
|
+ content:
|
|
|
|
+ "<span style='font-size: 16px; line-height: 1.5;'>在用户与网页产生交互(例如点击、触摸页面等)之前,网页将被禁止播放带有声音的媒体。点击恢复播放<span/>",
|
|
|
|
+ title: "隐私条款:",
|
|
|
|
+ single: true,
|
|
|
|
+ func: (state) => {
|
|
|
|
+ if (state == "ok") {
|
|
|
|
+ remoteStream.resume();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }, 200);
|
|
|
|
+ // console.info(
|
|
|
|
+ // remoteStream.userId_,
|
|
|
|
+ // rtcStore,
|
|
|
|
+ // "handleStreamSubscribedhandleStreamSubscribed.value"
|
|
|
|
+ // );
|
|
|
|
+
|
|
|
|
+ // if (
|
|
|
|
+ // !invitedRemoteStreams.value.some(
|
|
|
|
+ // (item) => item.userId_ == remoteStream.userId_
|
|
|
|
+ // )
|
|
|
|
+ // ) {
|
|
|
|
+ // debugger
|
|
|
|
+ // invitedRemoteStreams.value.push(remoteStream);
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // console.log(invitedRemoteStreams.value, "invitedRemoteStreams.value");
|
|
|
|
+
|
|
|
|
+ // await nextTick();
|
|
|
|
+ // setTimeout(() => {
|
|
|
|
+ // console.log(remoteStream.userId_, "remoteStream.getId()");
|
|
|
|
+ // remoteStream
|
|
|
|
+ // .play(remoteStream.userId_)
|
|
|
|
+ // .then(() => {
|
|
|
|
+ // console.log(`RemoteStream play success`, 88888888888888888888);
|
|
|
|
+ // })
|
|
|
|
+ // .catch((error) => {
|
|
|
|
+ // console.log(`RemoteStream play failed: error: ${error.message_}`);
|
|
|
|
+ // });
|
|
|
|
+ // }, 100);
|
|
|
|
+
|
|
|
|
+ // const remoteStream = event.stream;
|
|
|
|
+ // const userId = remoteStream.getUserId();
|
|
|
|
+ // console.log(`RemoteStream subscribed: [${userId}]`);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function handleStreamRemoved(event) {
|
|
|
|
+ const remoteStream = event.stream;
|
|
|
|
+ const userId = remoteStream.getUserId();
|
|
|
|
+ console.log(`RemoteStream removed: [${userId}]`);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function handleStreamUpdated(event) {
|
|
|
|
+ const remoteStream = event.stream;
|
|
|
|
+ const userId = remoteStream.getUserId();
|
|
|
|
+ console.log(
|
|
|
|
+ `RemoteStream updated: [${userId}] audio:${remoteStream.hasAudio()} video:${remoteStream.hasVideo()}`
|
|
|
|
+ );
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+let 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() {
|
|
export function useRtcSdk() {
|
|
return {
|
|
return {
|
|
- createRTCSocket
|
|
|
|
|
|
+ createRTCSocket,
|
|
|
|
+ handleJoin,
|
|
|
|
+ handleLeave,
|
|
|
|
+ localStream,
|
|
|
|
+ client: localClient
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|