Add audio input support utilities

This commit is contained in:
2026-04-16 22:01:45 +02:00
parent 88c5e5c5dd
commit 1a250c8c2d

85
src/audioInput.js Normal file
View File

@@ -0,0 +1,85 @@
export const AUDIO_INPUT_ENABLED_KEY = 'audioInputEnabled'
export const AUDIO_INPUT_DEVICE_ID_KEY = 'audioInputDeviceId'
const AUDIO_RECORDER_MIME_CANDIDATES = [
'audio/webm;codecs=opus',
'audio/webm',
'audio/mp4',
'audio/ogg;codecs=opus',
'',
]
export function supportsAudioInputCapture() {
return (
typeof navigator !== 'undefined' &&
typeof window !== 'undefined' &&
typeof window.MediaRecorder !== 'undefined' &&
Boolean(navigator.mediaDevices?.getUserMedia) &&
Boolean(navigator.mediaDevices?.enumerateDevices)
)
}
export function getAudioInputConstraints(deviceId = '') {
const audio = {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true,
}
if (deviceId) {
audio.deviceId = { exact: deviceId }
}
return { audio }
}
export function stopMediaStream(stream) {
stream?.getTracks?.().forEach(track => track.stop())
}
export async function ensureAudioInputPermission() {
if (!supportsAudioInputCapture()) {
throw new Error('Microphone capture is not available in this environment.')
}
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
stopMediaStream(stream)
}
export async function listAudioInputDevices() {
if (!supportsAudioInputCapture()) {
return []
}
const devices = await navigator.mediaDevices.enumerateDevices()
return devices
.filter(device => device.kind === 'audioinput')
.map((device, index) => {
const label = String(device.label || '').trim()
return {
deviceId: device.deviceId || `audio-input-${index + 1}`,
label: label || `Microphone ${index + 1}`,
hasLabel: Boolean(label),
}
})
}
export function getPreferredAudioRecorderMimeType() {
if (typeof window === 'undefined' || typeof window.MediaRecorder === 'undefined') {
return ''
}
for (const mimeType of AUDIO_RECORDER_MIME_CANDIDATES) {
if (!mimeType) {
return ''
}
if (
typeof window.MediaRecorder.isTypeSupported !== 'function' ||
window.MediaRecorder.isTypeSupported(mimeType)
) {
return mimeType
}
}
return ''
}