import { useMediasoup } from '@shared/composables/use-mediasoup' import { useSignaling } from '@shared/composables/use-signaling' import { Device } from 'mediasoup-client' import { markRaw, watch } from 'vue' const ICE_SERVERS: RTCIceServer[] = [ { urls: 'stun:stunserver2025.stunprotocol.org:3478' }, { urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:stun.l.google.com:5349' }, { urls: 'stun:stun1.l.google.com:3478' }, { urls: 'stun:stun1.l.google.com:5349' }, { urls: 'stun:stun2.l.google.com:19302' }, { urls: 'stun:stun2.l.google.com:5349' }, { urls: 'stun:stun3.l.google.com:3478' }, { urls: 'stun:stun3.l.google.com:5349' }, { urls: 'stun:stun4.l.google.com:19302' }, { urls: 'stun:stun4.l.google.com:5349' }, ] export default function () { const { socket } = useSignaling() const ms = useMediasoup() watch(socket, (socket) => { if (!socket) return socket.on('initialized', async (initData) => { ms.device.value = new Device() await ms.device.value.load({ routerRtpCapabilities: initData.rtpCapabilities }) const sendInfo = await socket.emitWithAck('create-transport', { producing: true, consuming: false }) const sendTransport = ms.device.value.createSendTransport({ ...sendInfo, iceServers: [...ICE_SERVERS, ...(sendInfo.iceServers ?? [])], }) ms.sendTransport.value = sendTransport await ms.transports.add({ id: sendTransport.id, ref: markRaw(sendTransport), }) sendTransport.on('connect', async ({ dtlsParameters }, callback, errback) => { try { await socket.emitWithAck('connect-transport', { transportId: sendTransport.id, dtlsParameters }) callback() } catch (error) { if (error instanceof Error) errback(error) } }) sendTransport.on('produce', async ({ kind, rtpParameters, appData }, callback, errback) => { try { const { id } = await socket.emitWithAck('produce', { transportId: sendTransport.id, kind, rtpParameters, appData, }) callback({ id }) } catch (error) { if (error instanceof Error) errback(error) } }) const recvInfo = await socket.emitWithAck('create-transport', { producing: false, consuming: true }) const recvTransport = ms.device.value.createRecvTransport({ ...recvInfo, iceServers: [...ICE_SERVERS, ...(recvInfo.iceServers ?? [])], }) ms.recvTransport.value = recvTransport await ms.transports.add({ id: recvTransport.id, ref: markRaw(recvTransport), }) recvTransport.on('connect', async ({ dtlsParameters }, callback, errback) => { try { await socket.emitWithAck('connect-transport', { transportId: recvTransport.id, dtlsParameters }) callback() } catch (error) { if (error instanceof Error) errback(error) } }) }) socket.on('new-consumer', async ({ id, producerId, kind, rtpParameters, socketId, appData, producerPaused }, cb) => { const rt = ms.recvTransport.value if (!rt) return const consumer = await rt.consume({ id, producerId, kind, rtpParameters, streamId: `${socketId}-${appData.source ?? 'stream'}`, appData: { ...appData, socketId }, }) if (producerPaused) consumer.pause() await ms.consumers.add({ id: consumer.id, paused: consumer.paused, kind: consumer.kind, appData: consumer.appData as Record, track: consumer.track, ref: markRaw(consumer), }) cb() }) socket.on('consumer-closed', ({ consumerId }) => { ms.consumers.get(consumerId)?.ref.close() }) socket.on('consumer-paused', ({ consumerId }) => { ms.consumers.get(consumerId)?.ref.pause() }) socket.on('consumer-resumed', ({ consumerId }) => { ms.consumers.get(consumerId)?.ref.resume() }) socket.on('disconnect', () => { ms.clearAll() }) }, { immediate: true }) }