chad/client/app/composables/use-mediasoup.ts
Никита Круглицкий 6110a17533
All checks were successful
Deploy / server (push) Successful in 15s
#2 update
2025-10-01 20:50:08 +06:00

124 lines
3.1 KiB
TypeScript

import type { Socket } from 'socket.io-client'
import { createGlobalState } from '@vueuse/core'
import * as mediasoupClient from 'mediasoup-client'
import { io } from 'socket.io-client'
export const useMediasoup = createGlobalState(() => {
const socket: Socket = io('https://api.koptilnya.xyz', {
path: '/chad/ws/',
transports: ['websocket'],
})
const initializing = ref(false)
const connected = ref(false)
const streams = shallowRef<MediaStream[]>([])
let device: mediasoupClient.Device
let sendTransport: mediasoupClient.types.Transport
let recvTransport: mediasoupClient.types.Transport
socket.on('newProducer', async ({ producerId }) => {
const params = await socket.emitWithAck('consume', {
producerId,
transportId: recvTransport.id,
rtpCapabilities: device.rtpCapabilities,
})
if (params?.error) {
console.error('consume error:', params.error)
return
}
const consumer = await recvTransport.consume(params)
const stream = new MediaStream([consumer.track])
streams.value.push(stream)
triggerRef(streams)
})
async function loadDevice() {
device = new mediasoupClient.Device()
const rtpCapabilities = await socket.emitWithAck('getRtpCapabilities')
await device.load({ routerRtpCapabilities: rtpCapabilities })
}
async function createSendTransport() {
const params = await socket.emitWithAck('createTransport')
sendTransport = device.createSendTransport(params)
sendTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
await socket.emitWithAck('connectTransport', {
transportId: sendTransport.id,
dtlsParameters,
})
callback()
}
catch (err) {
errback(err)
}
})
sendTransport.on('produce', async ({ kind, rtpParameters }, callback, errback) => {
try {
const { id } = await socket.emitWithAck('produce', {
transportId: sendTransport.id,
kind,
rtpParameters,
})
callback({ id })
}
catch (err) {
errback(err)
}
})
}
async function publishMic() {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
const track = stream.getAudioTracks()[0]
await sendTransport.produce({ track })
}
async function createRecvTransport() {
const params = await socket.emitWithAck('createTransport')
recvTransport = device.createRecvTransport(params)
recvTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
try {
await socket.emitWithAck('connectTransport', {
transportId: recvTransport.id,
dtlsParameters,
})
callback()
}
catch (err) {
errback(err)
}
})
}
(async () => {
if (initializing.value || connected.value)
return
initializing.value = true
connected.value = false
await loadDevice()
await createSendTransport()
await createRecvTransport()
await publishMic()
initializing.value = false
connected.value = true
})()
return {
connected,
streams,
}
})