From 1ad44cba31ab42829af88d338e5292591618134d Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Mon, 20 Jan 2025 15:48:37 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=E3=82=B9=E3=83=94=E3=83=BC=E3=82=AB?= =?UTF-8?q?=E3=83=BC=E3=83=9F=E3=83=A5=E3=83=BC=E3=83=88=E3=81=AE=E5=AE=9F?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/composables/qall/useLiveKitSDK.ts | 44 +++++++++++++++++++++++---- src/composables/qall/useQall.ts | 17 ++++++++++- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/composables/qall/useLiveKitSDK.ts b/src/composables/qall/useLiveKitSDK.ts index 288be36ce..f2cf5390b 100644 --- a/src/composables/qall/useLiveKitSDK.ts +++ b/src/composables/qall/useLiveKitSDK.ts @@ -12,15 +12,24 @@ import type { LocalTrackPublication, LocalParticipant, Participant, - TrackPublication + TrackPublication, + LocalTrack } from 'livekit-client' import { ref, type Ref } from 'vue' import { useToastStore } from '/@/store/ui/toast' const { addErrorToast } = useToastStore() -type TrackInfo = { - trackPublication: TrackPublication | undefined +type TrackInfo = ( + | { + isRemote: true + trackPublication: RemoteTrackPublication + } + | { + isRemote: false + trackPublication: LocalTrackPublication | undefined + } +) & { participantIdentity: string } @@ -36,6 +45,7 @@ function handleTrackSubscribed( if (track.kind === Track.Kind.Video || track.kind === Track.Kind.Audio) { // attach it to a new HTMLVideoElement or HTMLAudioElement tracksMap.value.set(publication.trackSid, { + isRemote: true, trackPublication: publication, participantIdentity: participant.identity }) @@ -66,6 +76,7 @@ function handleLocalTrackPublished( // when local tracks are ended, update UI to remove them from rendering if (!publication.track || publication.track.kind === Track.Kind.Audio) return tracksMap.value.set(publication.trackSid, { + isRemote: false, trackPublication: publication, participantIdentity: participant.identity }) @@ -83,13 +94,17 @@ function handleDisconnect() { const joinRoom = async (roomName: string, userName: string) => { try { const res = await fetch( - `http://localhost:3000/getToken?roomName=${roomName}&participantName=${userName}` + `https://easy-livekit-token-publisher.trap.show/token` ) - const token = await res.text() + const json = await res.json() + const token = json.token // pre-warm connection, this can be called as early as your page is loaded //room.prepareConnection("https://livekit-test.trap.show:39357", token); room.value = new Room() - await room.value.prepareConnection('ws://localhost:7880', token) + await room.value.prepareConnection( + 'wss://livekit.qall-dev.trapti.tech', + token + ) console.log(token) // set up event listeners @@ -158,11 +173,28 @@ const addScreenShareTrack = async () => { } } +const setLocalTrackMute = async (track: LocalTrack, muted: boolean) => { + if (muted) { + await track.mute() + } else { + await track.unmute() + } +} + +const setTrackEnabled = ( + publication: RemoteTrackPublication, + muted: boolean +) => { + publication.setEnabled(!muted) +} + export const useLiveKitSDK = () => { return { joinRoom, leaveRoom, addScreenShareTrack, + setTrackEnabled, + setLocalTrackMute, tracksMap } } diff --git a/src/composables/qall/useQall.ts b/src/composables/qall/useQall.ts index ba7152909..d0abb9475 100644 --- a/src/composables/qall/useQall.ts +++ b/src/composables/qall/useQall.ts @@ -2,11 +2,26 @@ import { ref } from 'vue' import { useLiveKitSDK } from '/@/composables/qall/useLiveKitSDK' import { useMeStore } from '/@/store/domain/me' import { useToastStore } from '/@/store/ui/toast' +import type { LocalAudioTrack, LocalVideoTrack } from 'livekit-client' const isCalling = ref(false) -const { joinRoom, leaveRoom, addScreenShareTrack, tracksMap } = useLiveKitSDK() +const { + joinRoom, + leaveRoom, + addScreenShareTrack, + setLocalTrackMute, + tracksMap +} = useLiveKitSDK() const { myId } = useMeStore() const { addErrorToast } = useToastStore() + +const setSpeakerMute = (track: LocalAudioTrack, muted: boolean) => { + setLocalTrackMute(track, muted) +} + +const setVideoMute = (track: LocalVideoTrack, muted: boolean) => { + setLocalTrackMute(track, muted) +} export const useQall = () => { const toggleCalling = (channelName: string) => { if (isCalling.value) { From 43126a8d4b16a8aa8e09620b075841df9742c292 Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Mon, 20 Jan 2025 17:04:21 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E9=9F=B3=E9=87=8F=E8=AA=BF=E6=95=B4?= =?UTF-8?q?=E3=81=AE=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/MainView/QallView/AudioTrack.vue | 10 ++++++- .../Main/MainView/QallView/QallView.vue | 8 +++++- .../Main/MainView/QallView/VideoTrack.vue | 18 ++++++++++-- src/composables/qall/useLiveKitSDK.ts | 28 +++++++++++++++---- src/composables/qall/useQall.ts | 1 + 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/components/Main/MainView/QallView/AudioTrack.vue b/src/components/Main/MainView/QallView/AudioTrack.vue index 6dd392a3f..eeaec4f62 100644 --- a/src/components/Main/MainView/QallView/AudioTrack.vue +++ b/src/components/Main/MainView/QallView/AudioTrack.vue @@ -1,11 +1,18 @@ diff --git a/src/composables/qall/useLiveKitSDK.ts b/src/composables/qall/useLiveKitSDK.ts index c30896175..a0f7f4139 100644 --- a/src/composables/qall/useLiveKitSDK.ts +++ b/src/composables/qall/useLiveKitSDK.ts @@ -20,7 +20,7 @@ import apis from '/@/lib/apis' const { addErrorToast } = useToastStore() -type TrackInfo = ( +export type TrackInfo = ( | { isRemote: true trackPublication: RemoteTrackPublication @@ -93,20 +93,23 @@ function handleDisconnect() { const joinRoom = async (roomName: string, userName: string) => { try { - const traQtoken = (await apis.getMyQRCode(true)).data - console.log(traQtoken) - const res = await fetch( - `https://easy-livekit-token-publisher.trap.show/token`, - { - method: 'GET', - headers: { - Authorization: `Bearer ${traQtoken}`, - 'Content-Type': 'application/json' - } - } - ) - const json = await res.json() - const token = json.token + // const traQtoken = (await apis.getMyQRCode(true)).data + // console.log(traQtoken) + // const res = await fetch( + // `https://easy-livekit-token-publisher.trap.show/token`, + // { + // method: 'GET', + // headers: { + // Authorization: `Bearer ${traQtoken}`, + // 'Content-Type': 'application/json' + // } + // } + // ) + // const json = await res.json() + // const token = json.token + const token = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzc0NDI5MDksImlzcyI6IkFQSTdUZWZvc1FoaWdXUiIsIm5hbWUiOiJub2M3dCIsIm5iZiI6MTczNzM1NjUwOSwic3ViIjoibm9jN3QiLCJ2aWRlbyI6eyJyb29tIjoibXktcm9vbSIsInJvb21Kb2luIjp0cnVlfX0.7AAPmZlHMgXHtZ1FwhLn_zW5k038pFWSx3JBHcUc-hs' + // pre-warm connection, this can be called as early as your page is loaded //room.prepareConnection("https://livekit-test.trap.show:39357", token); room.value = new Room() @@ -145,9 +148,7 @@ const joinRoom = async (roomName: string, userName: string) => { dtx: false } ) - await room.value.localParticipant.setScreenShareEnabled(true, { - audio: true - }) + await room.value.localParticipant.setAttributes({}) } catch { addErrorToast('Qallの接続に失敗しました') await leaveRoom() @@ -173,10 +174,23 @@ const addScreenShareTrack = async () => { addErrorToast('ルームが存在しません') return } - const localTracks = await createLocalScreenTracks({}) - localTracks.map(async t => { - await room.value?.localParticipant.publishTrack(t) + const localTracks = await createLocalScreenTracks({ + audio: true }) + + await Promise.all( + localTracks.map(async t => { + await room.value?.localParticipant.publishTrack(t) + }) + ) + const videoSid = localTracks.find(t => t.kind === Track.Kind.Video)?.sid + const audioSid = localTracks.find(t => t.kind === Track.Kind.Audio)?.sid + if (audioSid && videoSid) { + await room.value.localParticipant.setAttributes({ + ...room.value.localParticipant.attributes, + [videoSid]: audioSid + }) + } } catch { addErrorToast('スクリーン共有に失敗しました') } @@ -186,8 +200,31 @@ const removeScreenShareTrack = async ( localpublication: LocalTrackPublication ) => { if (localpublication.track) { - room.value?.localParticipant.unpublishTrack(localpublication.track) - localpublication.track.stop() + if (!room.value) { + addErrorToast('ルームが存在しません') + return + } + + const { [localpublication.trackSid]: audioSid, ...newAttributes } = + room.value.localParticipant.attributes + room.value.localParticipant.unpublishTrack(localpublication.track) + room.value.localParticipant.setAttributes(newAttributes) + if (!audioSid) { + return + } + + const audioTrack = tracksMap.value.get(audioSid) + if ( + !audioTrack || + audioTrack.isRemote || + !audioTrack.trackPublication?.track + ) { + return + } + + room.value.localParticipant.unpublishTrack( + audioTrack.trackPublication.track + ) } } @@ -211,6 +248,7 @@ export const useLiveKitSDK = () => { joinRoom, leaveRoom, addScreenShareTrack, + removeScreenShareTrack, setTrackEnabled, setLocalTrackMute, tracksMap diff --git a/src/composables/qall/useQall.ts b/src/composables/qall/useQall.ts index 683212b7b..8577104b4 100644 --- a/src/composables/qall/useQall.ts +++ b/src/composables/qall/useQall.ts @@ -9,6 +9,7 @@ const { joinRoom, leaveRoom, addScreenShareTrack, + removeScreenShareTrack, setLocalTrackMute, tracksMap } = useLiveKitSDK() @@ -39,6 +40,7 @@ export const useQall = () => { isCalling, toggleCalling, addScreenShareTrack, + removeScreenShareTrack, tracksMap } } From 04c35b67b7b8396c6f5828ce9529efc5bd1a5f6d Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Mon, 20 Jan 2025 21:12:07 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=E7=94=BB=E9=9D=A2=E5=85=B1=E6=9C=89?= =?UTF-8?q?=E3=81=8C=E5=81=9C=E6=AD=A2=E3=81=97=E3=81=9F=E3=81=A8=E3=81=8D?= =?UTF-8?q?=E3=81=AB=E3=80=81=E3=81=99=E3=81=B9=E3=81=A6=E3=81=AEstream?= =?UTF-8?q?=E3=82=92stop=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/MainView/QallView/AudioTrack.vue | 2 +- .../Main/MainView/QallView/QallView.vue | 8 ++- src/composables/qall/useLiveKitSDK.ts | 56 ++++++++++++------- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/components/Main/MainView/QallView/AudioTrack.vue b/src/components/Main/MainView/QallView/AudioTrack.vue index 3104fa209..3c99214b5 100644 --- a/src/components/Main/MainView/QallView/AudioTrack.vue +++ b/src/components/Main/MainView/QallView/AudioTrack.vue @@ -27,5 +27,5 @@ onUnmounted(() => { diff --git a/src/components/Main/MainView/QallView/QallView.vue b/src/components/Main/MainView/QallView/QallView.vue index b1050f6eb..e6ebe6e3a 100644 --- a/src/components/Main/MainView/QallView/QallView.vue +++ b/src/components/Main/MainView/QallView/QallView.vue @@ -10,7 +10,7 @@ const { tracksMap, addScreenShareTrack } = useQall()

Qall View

-
+
@@ -31,12 +31,16 @@ const { tracksMap, addScreenShareTrack } = useQall()