162 lines
4.0 KiB
TypeScript
162 lines
4.0 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'
|
|
|
|
const ICE_SERVERS: RTCIceServer[] = [
|
|
{
|
|
urls: 'stun:stun.relay.metered.ca:80',
|
|
},
|
|
{
|
|
urls: 'turn:global.relay.metered.ca:80',
|
|
username: '4cad09c0111f423f5283814c',
|
|
credential: 'B1dO8AGehex4o3pt',
|
|
},
|
|
{
|
|
urls: 'turn:global.relay.metered.ca:80?transport=tcp',
|
|
username: '4cad09c0111f423f5283814c',
|
|
credential: 'B1dO8AGehex4o3pt',
|
|
},
|
|
{
|
|
urls: 'turn:global.relay.metered.ca:443',
|
|
username: '4cad09c0111f423f5283814c',
|
|
credential: 'B1dO8AGehex4o3pt',
|
|
},
|
|
{
|
|
urls: 'turns:global.relay.metered.ca:443?transport=tcp',
|
|
username: '4cad09c0111f423f5283814c',
|
|
credential: 'B1dO8AGehex4o3pt',
|
|
},
|
|
]
|
|
|
|
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,
|
|
iceServers: [
|
|
...ICE_SERVERS,
|
|
...(params.iceServers ?? []),
|
|
],
|
|
})
|
|
|
|
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,
|
|
iceServers: [
|
|
...ICE_SERVERS,
|
|
...(params.iceServers ?? []),
|
|
],
|
|
})
|
|
|
|
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,
|
|
}
|
|
})
|