Files
chad/client/app/composables/use-audio-context.ts
2025-12-25 07:21:30 +06:00

63 lines
1.3 KiB
TypeScript

import { useEventListener } from '@vueuse/core'
export default function useAudioContext(audioTrack: Ref<MediaStreamTrack | undefined>) {
const ctx = new (window.AudioContext || window.webkitAudioContext)()
const stream = new MediaStream()
const audioEl = new Audio()
const sourceNode = shallowRef<MediaStreamAudioSourceNode>()
const gainNode = ctx.createGain()
watch(audioTrack, async (track, prevTrack) => {
if (prevTrack)
stream.removeTrack(prevTrack)
if (!track)
return
stream.addTrack(track)
if (!audioEl.srcObject) {
audioEl.srcObject = stream
audioEl.muted = true
}
sourceNode.value = ctx.createMediaStreamSource(stream)
await connect()
}, { immediate: true })
useEventListener(document, 'click', async () => {
if (ctx.state === 'suspended') {
await ctx.resume()
}
await connect()
}, { once: true })
onScopeDispose(() => {
audioEl.pause()
audioEl.srcObject = null
ctx.close()
})
async function connect() {
if (!sourceNode.value || ctx.state === 'suspended')
return
sourceNode.value.connect(gainNode)
gainNode.connect(ctx.destination)
ctx.resume()
}
function setGain(value: number) {
gainNode.gain.value = value
}
return {
setGain,
}
}