基于WebSocket与Audio APIs的iOS实时音频流播放异常问题
iOS上实时音频流播放异常问题
我正在开发一款基于WebSocket与音频API的实时音频流应用,该应用通过WebSocket接收ElevenLabs API返回的音频分片并顺序播放。该应用在多数平台运行正常,但在iOS设备上,音频要么无法播放,要么存在明显延迟。
已尝试方案:
- 使用Web Audio API:尝试直接通过AudioContext播放音频分片,但iOS对实时流存在兼容性问题。
- 转换为Blob:将接收的音频分片转换为Blob,通过
<audio>元素播放,虽能运行但分片间延迟过高,不符合实时要求。
let connectButton = null; let disconnectButton = null; let sendButton = null; let receiveBox = null; let inputText = null; let audioPlayer = document.getElementById("audioPlayer"); let ws = null; let audioQueue = []; let isPlaying = false; const ELEVENLABS_WS_URL = "wss://api.elevenlabs.io/v1/text-to-speech/XrExE9yKIg1WjnnlVkGX/stream-input?model_id=eleven_multilingual_v1&inactivity_timeout=30&language=English_American"; function startup() { connectButton = document.getElementById("connectButton"); disconnectButton = document.getElementById("disconnectButton"); sendButton = document.getElementById("sendButton"); receiveBox = document.getElementById("receive-box"); inputText = document.getElementById("inputText"); audioPlayer = document.getElementById("audioPlayer"); connectButton.addEventListener("click", initializeWebSocket, false); disconnectButton.addEventListener("click", closeWebSocket, false); sendButton.addEventListener("click", sendMessage, false); } function initializeWebSocket() { if (!ws || ws.readyState === WebSocket.CLOSED) { ws = new WebSocket(ELEVENLABS_WS_URL); ws.onopen = () => { console.log("Connected to ElevenLabs WebSocket."); connectButton.disabled = true; disconnectButton.disabled = false; }; ws.onmessage = handleWebSocketMessage; ws.onerror = (error) => console.error("WebSocket error:", error); ws.onclose = () => { console.log("Disconnected from ElevenLabs WebSocket."); connectButton.disabled = false; disconnectButton.disabled = true; }; } } function closeWebSocket() { if (ws) { ws.close(); console.log("WebSocket connection closed."); } } function sendMessage() { const text = inputText.value.trim(); if (text) { const message = { text: text, voice_settings: { stability: 1, similarity_boost: true, optimize_streaming_latency: 0 }, flush: true, xi_api_key: "", streaming: true }; if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify(message)); } else { console.error("WebSocket is not connected."); } } } function handleWebSocketMessage(event) { const audioData = JSON.parse(event.data); console.log('audioData: ', typeof audioData); if (audioData && audioData.audio) { const base64Audio = audioData.audio; addAudioChunkToQueue(base64Audio); } else { console.error("No audio data received."); } } function addAudioChunkToQueue(base64Audio) { const audioBuffer = base64ToArrayBuffer(base64Audio); audioQueue.push(audioBuffer); if (!isPlaying) { playNextChunk(); } } function playNextChunk() { if (audioQueue.length > 0) { isPlaying = true; const audioBuffer = audioQueue.shift(); const audioBlob = new Blob([audioBuffer], { type: 'audio/mpeg' }); const audioUrl = URL.createObjectURL(audioBlob); audioPlayer.src = audioUrl; audioPlayer.play() .then(() => { console.log("Playing audio chunk..."); audioPlayer.onended = () => { isPlaying = false; playNextChunk(); }; }) .catch((error) => { console.error("Error playing audio:", error); isPlaying = false; }); } else { isPlaying = false; } } function base64ToArrayBuffer(base64) { console.log('Converting to arraybuffer'); const binaryString = window.atob(base64); const len = binaryString.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes.buffer; } window.addEventListener("load", startup);
内容的提问来源于stack exchange,提问作者b_encora
相关产品推荐
相关产品推荐

