@crestapps/ai-chat-ui 2.0.0-preview.154 → 2.0.0-preview.162
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-widget.js +4 -1
- package/dist/ai-chat-widget.js.map +1 -1
- package/dist/ai-chat-widget.min.js +1 -1
- package/dist/ai-chat-widget.min.js.map +1 -1
- package/dist/ai-chat.js +638 -320
- package/dist/ai-chat.js.map +1 -1
- package/dist/ai-chat.min.js +1 -1
- package/dist/ai-chat.min.js.map +1 -1
- package/dist/chat-interaction.js +323 -77
- package/dist/chat-interaction.js.map +1 -1
- package/dist/chat-interaction.min.js +1 -1
- package/dist/chat-interaction.min.js.map +1 -1
- package/dist/realtime-audio.js +2236 -0
- package/dist/realtime-audio.js.map +1 -0
- package/dist/realtime-audio.min.js +2 -0
- package/dist/realtime-audio.min.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["realtime-audio.js"],"names":["window","document","REALTIME_SAMPLE_RATE","REALTIME_GATE_LOOKAHEAD_MS","coreAiGateDecide","state","input","micDb","assistantDb","nowMs","mode","dtMs","lastMs","Math","max","min","assistantUntil","assistantSpeaking","assistantPeakDb","floorDb","open","sustained","openSince","risingPerMs","pushToTalk","erl","echoReturnDb","warm","echoLearnedMs","ratePerMs","expectedEchoDb","openThreshold","holdThreshold","hangoverMs","speechHangoverMs","aboveSince","speakUntil","userActive","wasAssistantSpeaking","listenGraceUntil","pttActive","bargeIn","createGateState","coreAiRmsDb","block","length","sum","i","rms","sqrt","log10","REALTIME_GATE_WORKLET_SOURCE","toString","join","createMicGate","rawStream","rawTrack","getAudioTracks","ctx","node","micSource","remoteSource","dest","timer","level","fallback","track","stopped","gate","usingWorklet","getLevel","setMode","next","port","postMessage","e","attachAssistantStream","remoteStream","attachAssistant","stop","clearInterval","onmessage","disconnect","close","AudioCtor","AudioContext","webkitAudioContext","Promise","resolve","resume","err","blobUrl","audioWorklet","addModule","URL","createObjectURL","Blob","type","buildFallbackGate","then","revokeObjectURL","AudioWorkletNode","numberOfInputs","numberOfOutputs","outputChannelCount","processorOptions","lookaheadMs","data","CoreAIRealtime","lastGateLevel","createMediaStreamSource","connect","createMediaStreamDestination","pendingRemoteStream","stream","console","warn","src","analyser","createAnalyser","fftSize","remoteAnalyser","remoteData","Float32Array","source","gain","createGain","value","f","gateState","setInterval","getFloatTimeDomainData","performance","now","Date","target","setTargetAtTime","currentTime","routeOutputToPreferredDevice","el","chosenDeviceId","setSinkId","navigator","mediaDevices","enumerateDevices","devices","outputs","filter","d","kind","deviceId","defaultEntry","groupId","j","ensurePlayback","onBlocked","play","played","attach","opts","connection","sel","selectors","realtimeVoiceName","voiceName","realtimeCapableDeployments","capableDeployments","map","n","toLowerCase","isRealtimeMode","realtimeEnabled","noop","onActivate","onDeactivate","onEnterRealtimeMode","onUserTurnPending","onUserTurnDropped","strings","localize","key","ensureConnected","sendStart","getVoiceName","sendStartWebRtc","webRtcEnabled","RTCPeerConnection","webRtcIceServers","Array","isArray","DEFAULT_ICE_SERVERS","urls","onStateChange","realtimeState","q","name","s","querySelector","isRealtimeActive","realtimeLifecycleBound","realtimeSessionReady","realtimeEndedNotice","realtimeCompatibilityNoticeEl","realtimeStatusEl","realtimeStream","realtimeAudioCtx","realtimeSubject","realtimeProcessor","realtimeMicSource","realtimeZeroGain","realtimeGain","realtimePlayHead","realtimeSources","realtimeIsWebRtc","realtimePc","realtimeRemoteAudioEl","realtimeWebRtcHandlersBound","realtimeRemoteDescriptionSet","realtimePendingIce","realtimeWebRtcConnected","realtimeWebRtcConnectTimer","realtimeFellBack","REALTIME_WEBRTC_CONNECT_TIMEOUT_MS","REALTIME_WEBRTC_NO_RELAY_TIMEOUT_MS","REALTIME_WEBRTC_JITTER_BUFFER_TARGET_MS","REALTIME_WEBRTC_BLOCKED_KEY","realtimeSawRelayCandidate","realtimeWebRtcMicTrack","realtimeGate","realtimeGatePendingRemoteStream","realtimeBargeIn","realtimePushToTalk","realtimePttActive","realtimePttBound","realtimePttKeyDown","realtimePttKeyUp","realtimePttButton","realtimePttUiEl","realtimeVolume","realtimeMicDeviceId","realtimeOutputDeviceId","realtimeLanguage","realtimeAudioSettingsBuilt","REALTIME_WS_ECHO_HANGOVER_SEC","REALTIME_PREFS_VERSION","loadRealtimeAudioPrefs","prefs","volume","micDeviceId","outputDeviceId","language","version","raw","localStorage","getItem","parsed","JSON","parse","isFinite","repairRealtimeAudioPrefs","saveRealtimeAudioPrefs","setItem","stringify","applyRealtimeAudioPrefs","syncRealtimeGateMode","isEditableTarget","tagName","tag","isContentEditable","attachRealtimePushToTalk","code","preventDefault","repeat","setRealtimePttActive","addEventListener","detachRealtimePushToTalk","removeEventListener","active","classList","toggle","innerHTML","buildRealtimePttUi","realtimeBtn","coarse","matchMedia","matches","bar","createElement","className","btn","hint","appendChild","row","parentElement","insertAdjacentElement","removeRealtimePttUi","remove","setupRealtimeAudioSettings","wrap","id","style","position","display","gear","title","setAttribute","langs","langOptions","l","panel","cssText","round","bargeInput","pttInput","volInput","volVal","micSelect","outSelect","outPickButton","langSelect","persist","checked","parseInt","pushRealtimeSettingsToServer","populateDevices","options","forEach","label","push","replace","outs","outOptions","stillThere","some","endRealtimeSessionFromServer","constrainPanel","right","left","panelRect","getBoundingClientRect","rect","boundaryTop","body","documentElement","getComputedStyle","overflowY","top","maxHeight","stopPropagation","showing","textContent","applyRealtimeOutputDevice","selectAudioOutput","device","option","setRealtimeButtonHtml","button","html","DOMPurify","sanitize","replaceChildren","RETURN_DOM_FRAGMENT","text","trim","createTextNode","updateRealtimeButton","add","getAttribute","blur","applyRealtimeMode","enable","micBtn","conversationBtn","inputEl","sendBtn","audioSettings","getElementById","hidden","stopRealtimeConversation","removeCompatibilityModeNotice","clearRealtimeStatus","send","REALTIME_STATE_TEXT","setRealtimeState","detail","showRealtimeStatus","transport","bindRealtimeLifecycleHandlers","on","identifier","payload","flushRealtimePlayback","fallbackToWebSocket","onclose","onreconnecting","reason","info","offerResume","startRealtimeConversation","resolveIceServers","invoke","servers","isWebRtcKnownBlocked","sessionStorage","rememberWebRtcBlocked","showCompatibilityModeNotice","note","startRealtimeWebRtcConversation","startRealtimeWebSocketConversation","focusedBtn","audioConstraints","channelCount","echoCancellation","ideal","noiseSuppression","autoGainControl","echoCancellationType","voiceIsolation","exact","getUserMedia","audio","AudioContextCtor","sampleRate","destination","signalR","Subject","ctxAtStart","processor","createScriptProcessor","monitorDest","setupMicGate","micTrack","gatedStream","MediaStream","onaudioprocess","event","inputBuffer","getChannelData","muted","pcm","Int16Array","bytes","Uint8Array","buffer","binary","b","String","fromCharCode","btoa","zeroGain","voice","getTracks","error","micConstraints","iceServers","pc","audioEl","autoplay","routeRealtimeOutputToDefaultDevice","ontrack","receiver","jitterBufferTarget","streams","srcObject","ensureRealtimePlayback","attachWebRtcAssistantAnalyser","onicecandidate","candidate","indexOf","sdpMid","sdpMLineIndex","clearTimeout","setTimeout","onconnectionstatechange","connectionState","markWebRtcConnected","oniceconnectionstatechange","iceConnectionState","bindWebRtcSignalingHandlers","micTrackToSend","addTrack","createOffer","offer","setLocalDescription","sdp","t","setRemoteDescription","pending","init","addIceCandidate","stopRealtimeWebRtc","stopWebRtcEchoGuard","REALTIME_GATE_HANGOVER_MS","realtimeGateModeMessage","complete","toggleRealtime","getTransportStats","getStats","report","result","inbound","codec","sinkId","jitterBufferTargetMs","r","getReceivers","x","stat","packetsReceived","packetsLost","packetsDiscarded","jitterMs","jitter","jitterBufferDelayMs","jitterBufferDelay","jitterBufferEmittedCount","totalSamplesReceived","concealedSamples","concealmentEvents","silentConcealedSamples","insertedSamplesForDeceleration","removedSamplesForAcceleration","audioLevel","codecId","get","mimeType","clockRate","channels","sdpFmtpLine","playRealtimePcm","sampleCount","floor","byteOffset","f32","createBuffer","copyToChannel","createBufferSource","start","duration","onended","isRealtimeDeployment","deploymentName","deploymentSelect","controller","applyMode","receivePcm","isActive","getState","getGateLevel","activeController","decideGate","rmsDb"],"mappings":"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","file":"realtime-audio.js","sourcesContent":["/*\n * Shared realtime (speech-to-speech) audio controller for interaction-style chat surfaces.\n *\n * Encapsulates the browser side of a realtime voice conversation: PCM16 mic capture and streaming,\n * PCM playback with volume, the half-duplex echo guard, push-to-talk, the per-device audio settings\n * popover, and switching the input between text and audio-only when a realtime deployment is selected.\n *\n * It is host-agnostic: the host (an MVC inline script or the Blazor chat-interaction Vue app) supplies the\n * SignalR connection, a sendStart callback (so each surface can address its own hub method/identifier),\n * element selectors, and a few display hooks. Reused so realtime lives in one place, not one copy per host.\n *\n * Usage:\n * var controller = window.CoreAIRealtime.attach({\n * connection: conn,\n * ensureConnected: function () { return startPromise; }, // () => Promise<any>\n * sendStart: function (subject, voice, language, silenceMs, vadThreshold) { ... },\n * voiceName: 'alloy',\n * capableDeployments: ['gpt-realtime'],\n * realtimeEnabled: true,\n * selectors: { realtimeButton, input, sendButton, micButton, conversationButton, deploymentSelect },\n * onActivate: function () { ... }, // realtime session started (host: show transcripts)\n * onDeactivate: function () { ... }, // realtime session stopped\n * onEnterRealtimeMode: function () { ... } // switched to audio-only (host: stop any STT recording)\n * });\n * // then route audio to it: controller.receivePcm(bytes) // from ReceiveAudioChunk 'audio/pcm'\n */\n(function (window, document) {\n 'use strict';\n\n var REALTIME_SAMPLE_RATE = 24000;\n\n // --- Microphone gate --------------------------------------------------------------------------------------\n //\n // The outbound mic is silenced unless the user is genuinely speaking, so the model never receives silence,\n // room noise, or the assistant's echo — which is what stopped it answering itself and stopped the input\n // transcriber hallucinating phantom \"Thank you\" turns.\n //\n // - push-to-talk: open only while the key is held;\n // - barge-in on: open whenever the user speaks — even over the assistant (interrupts);\n // - barge-in off: open only when the user speaks and the assistant is silent (wait your turn).\n //\n // There are no user-facing modes or thresholds: everything the gate needs it measures for itself. It tracks\n // the room's noise floor, and — the part that makes open speakers work — it learns how loud the assistant's\n // own voice comes back into the microphone after echo cancellation (the echo return level). While the\n // assistant is audible, only a voice clearly louder than that expected echo counts as the user interrupting;\n // with a headset the expected echo is the room floor and interruptions are cheap, with loud speakers next to\n // the microphone it is high and the gate simply waits its turn. Echo cancellation is still the first line of\n // defence; this is what keeps the model from hearing itself when cancellation is not enough.\n //\n // It runs in an AudioWorklet rather than on a requestAnimationFrame loop. rAF is paused for hidden documents,\n // so the old gate froze in whatever state it held the moment the user switched tabs: stuck closed meant they\n // were never heard again. The audio thread keeps running regardless of visibility, sees every sample instead\n // of a 10 ms window sampled 60 times a second, and can hold a look-ahead delay so the gate is already open\n // when the first consonant arrives.\n //\n // Exported as window.CoreAIRealtime.createMicGate so both chat clients share one implementation.\n var REALTIME_GATE_LOOKAHEAD_MS = 80;\n\n /*\n * The gate's decision, as a pure function of the current state and one block of measurements.\n *\n * It lives on its own for two reasons. It has to run inside an AudioWorklet, which cannot close over module\n * scope — so it is stringified into the worklet below rather than duplicated there. And it is the part worth\n * testing exhaustively: every one of this gate's historical failures (a quiet microphone never opening it, a\n * loud room's echo opening it, one sentence chopped into several turns) is a rule in here, and each is far\n * easier to pin down with numbers than with audio.\n *\n * `state` is mutated and returned. Callers create it with createGateState().\n *\n * input: { micDb, assistantDb, nowMs, mode }\n * mode: { pushToTalk, pttActive, bargeIn, speechHangoverMs }\n */\n function coreAiGateDecide(state, input) {\n var micDb = input.micDb;\n var assistantDb = (typeof input.assistantDb === 'number') ? input.assistantDb : -100;\n var nowMs = input.nowMs;\n var mode = input.mode || {};\n\n // Elapsed time since the previous decision, so the time constants below mean the same thing whether the\n // gate runs per 128-sample block on the audio thread or on a 20 ms timer.\n var dtMs = state.lastMs === null ? 0 : Math.max(0, Math.min(50, nowMs - state.lastMs));\n state.lastMs = nowMs;\n\n // \"The assistant is speaking\" must survive the gaps between its words. Without this hangover the\n // half-duplex gate re-opened in every inter-word pause and fed the echo tail straight back to the model.\n if (assistantDb > -50) {\n state.assistantUntil = nowMs + 400;\n }\n\n var assistantSpeaking = nowMs < state.assistantUntil;\n\n // Peak-held assistant level. The echo of a word reaches the microphone 50-200 ms after the word was played,\n // so the expected echo has to be judged against what the assistant was doing a moment ago, not against the\n // instantaneous level (which is silent between its words). Decays at 20 dB/s.\n if (assistantDb > state.assistantPeakDb) {\n state.assistantPeakDb = assistantDb;\n } else {\n state.assistantPeakDb = Math.max(-100, state.assistantPeakDb - 0.02 * dtMs);\n }\n\n // Adaptive noise floor. It falls to a quieter room quickly, and rises only while the gate is shut and the\n // assistant is silent — that is, only from audio we have judged is neither speech nor echo.\n //\n // Letting it rise during speech makes the gate close on the talker: the estimate climbs towards their own\n // voice, the level stops clearing floor + margin, and the sentence is cut part-way through.\n //\n // Cold start. Digital silence is not a measurement: a capture pipeline delivers a few empty blocks before\n // the microphone is live (and noise suppression emits exact zeros in a quiet headset), and seeding on\n // those anchored the floor at the clamp and made the room itself look like speech. The first real block\n // is not trustworthy either — it may well be the user already talking, and a floor seeded at their own\n // level meant the gate never opened for them at all. So the seed is the first real block capped at a\n // typical quiet-room level; the fast downward adaptation below then finds the real floor within a few\n // hundred milliseconds. (Seeding from the quietest block instead was tried and rejected: block-to-block\n // level varies by several dB even on steady room noise, so a floor set at the minimum let ordinary noise\n // peaks open the gate.)\n if (micDb <= -95) {\n if (state.floorDb === null) {\n state.open = false;\n\n return state;\n }\n } else if (state.floorDb === null) {\n state.floorDb = Math.min(micDb, -50);\n }\n\n if (micDb < state.floorDb) {\n state.floorDb += (micDb - state.floorDb) * Math.min(1, 0.0075 * dtMs);\n } else if (!assistantSpeaking) {\n // Rising. While the gate is shut this is responsive (~2 s). While it is open the audio is presumed to\n // be speech and the floor moves slowly (~10 s), because learning from the talker's own voice is what\n // closed the gate part-way through their sentence — but not so slowly that a steady sound could hold\n // the gate open indefinitely. Past 10 s the assumption is abandoned altogether: nobody speaks\n // continuously for that long, so it is ambient noise and the floor tracks it normally.\n var sustained = state.openSince !== null && (nowMs - state.openSince) > 10000;\n var risingPerMs = (state.open && !sustained) ? 0.0001 : 0.00056;\n state.floorDb += (micDb - state.floorDb) * Math.min(1, risingPerMs * dtMs);\n }\n\n if (state.floorDb < -75) {\n state.floorDb = -75;\n }\n\n // Echo return level: how loud the assistant comes back into the microphone, relative to its own level,\n // after echo cancellation has done what it can. Learned only while the assistant is audible and the gate\n // is shut, i.e. from audio we have judged is not the user. It warms up fast for the first second so the\n // very first reply is protected, then follows slowly so a user interrupting cannot be mistaken for echo\n // in the time it takes to confirm them (below). It falls slowly too, so turning the volume down is\n // noticed within a couple of seconds.\n if (assistantSpeaking && !state.open && assistantDb > -50 && !mode.pushToTalk) {\n var erl = micDb - state.assistantPeakDb;\n if (state.echoReturnDb === null) {\n state.echoReturnDb = erl;\n } else {\n var warm = state.echoLearnedMs < 1000;\n var ratePerMs = erl > state.echoReturnDb ? (warm ? 0.02 : 0.0012) : 0.0006;\n state.echoReturnDb += (erl - state.echoReturnDb) * Math.min(1, ratePerMs * dtMs);\n }\n state.echoLearnedMs += dtMs;\n }\n\n // Where the assistant's echo is expected to sit right now, or far below anything if it has never been\n // heard (a headset).\n var expectedEchoDb = state.echoReturnDb === null ? -100 : (state.assistantPeakDb + state.echoReturnDb);\n\n var openThreshold, holdThreshold;\n if (assistantSpeaking) {\n // Interrupting: the voice must clearly beat both the room and the expected echo, and be real speech\n // in absolute terms — echo residual can sit well above a very quiet room's floor without being\n // anywhere near a voice.\n openThreshold = Math.max(state.floorDb + 12, expectedEchoDb + 8, -45);\n holdThreshold = Math.max(state.floorDb + 3, expectedEchoDb + 3);\n } else {\n openThreshold = state.floorDb + 9;\n holdThreshold = state.floorDb + 3;\n }\n\n var hangoverMs = mode.speechHangoverMs || 2000;\n\n if (micDb > openThreshold) {\n if (assistantSpeaking && !state.open) {\n // An interruption has to be sustained for a moment before it counts. A single loud block over the\n // assistant is far more often a click, a cough or an echo peak than the user; the look-ahead delay\n // keeps the opening of a genuine interruption from being lost while we wait.\n if (state.aboveSince === null) { state.aboveSince = nowMs; }\n if (nowMs - state.aboveSince >= 250) { state.speakUntil = nowMs + hangoverMs; }\n } else {\n // The hangover must outlast the provider's end-of-turn detection. The gate emits digital silence\n // when it closes, so whichever of the two expires first is what actually ends the user's turn —\n // and a gate that closes first cuts people off mid-sentence and answers half a question.\n state.speakUntil = nowMs + hangoverMs;\n }\n } else {\n state.aboveSince = null;\n if (state.open && micDb > holdThreshold) {\n // Hysteresis: once open, stay open until the level really settles back towards the floor, so one\n // sentence is not chopped into several provider turns.\n state.speakUntil = Math.max(state.speakUntil, nowMs + 250);\n }\n }\n\n var userActive = nowMs < state.speakUntil;\n\n if (!assistantSpeaking && state.wasAssistantSpeaking) {\n state.listenGraceUntil = nowMs + 1500;\n }\n\n state.wasAssistantSpeaking = assistantSpeaking;\n state.assistantSpeaking = assistantSpeaking;\n\n if (mode.pushToTalk) {\n state.open = !!mode.pttActive;\n } else if (mode.bargeIn) {\n state.open = userActive;\n } else {\n state.open = !assistantSpeaking && (userActive || nowMs < state.listenGraceUntil);\n }\n\n if (state.open && state.openSince === null) {\n state.openSince = nowMs;\n } else if (!state.open) {\n state.openSince = null;\n }\n\n return state;\n }\n\n function createGateState() {\n return {\n // Null until the first measurement, so the floor starts from the room rather than from a guess.\n floorDb: null,\n lastMs: null,\n speakUntil: 0,\n assistantUntil: 0,\n assistantPeakDb: -100,\n // Null until the assistant has been heard while the gate was shut (never, with a headset).\n echoReturnDb: null,\n echoLearnedMs: 0,\n aboveSince: null,\n listenGraceUntil: 0,\n wasAssistantSpeaking: false,\n assistantSpeaking: false,\n open: false,\n openSince: null\n };\n }\n\n // Root-mean-square of a block, in dBFS. RMS (not peak) tracks perceived loudness, and dB is the only scale on\n // which a fixed \"N above the noise floor\" rule behaves the same in a quiet room and a loud one.\n function coreAiRmsDb(block) {\n if (!block || !block.length) { return -100; }\n var sum = 0;\n for (var i = 0; i < block.length; i++) { sum += block[i] * block[i]; }\n var rms = Math.sqrt(sum / block.length);\n\n return rms > 1e-7 ? 20 * Math.log10(rms) : -100;\n }\n\n // The gate decision itself, as an AudioWorkletProcessor. Registered from a Blob URL so it needs no separate\n // asset file (and no host-specific path configuration). The decision and level functions are stringified in\n // rather than rewritten, so the worklet and the fallback below can never disagree.\n var REALTIME_GATE_WORKLET_SOURCE = [\n 'var decide = ' + coreAiGateDecide.toString() + ';',\n 'var newState = ' + createGateState.toString() + ';',\n 'var rmsDb = ' + coreAiRmsDb.toString() + ';',\n 'class CoreAiMicGateProcessor extends AudioWorkletProcessor {',\n ' constructor(options) {',\n ' super();',\n ' var o = (options && options.processorOptions) || {};',\n // The gate reads the live signal but emits it delayed, so by the time a word's first sample leaves here\n // the gate has already seen it and opened. Without this the initial consonant of every utterance was\n // clipped, which is exactly what degrades transcription and the model's understanding.\n ' this.delay = new Float32Array(Math.max(1, Math.round(sampleRate * (o.lookaheadMs || 80) / 1000)));',\n ' this.delayPos = 0;',\n ' this.gain = 0;',\n ' this.mode = o.mode || {};',\n ' this.state = newState();',\n ' this.lastPost = 0;',\n ' this.port.onmessage = function (e) { this.mode = e.data || {}; }.bind(this);',\n ' }',\n ' process(inputs, outputs) {',\n ' var mic = (inputs[0] && inputs[0][0]) || null;',\n ' var assistant = (inputs[1] && inputs[1][0]) || null;',\n ' var out = (outputs[0] && outputs[0][0]) || null;',\n ' if (!out) { return true; }',\n ' var micDb = rmsDb(mic);',\n ' decide(this.state, { micDb: micDb, assistantDb: rmsDb(assistant), nowMs: currentTime * 1000, mode: this.mode });',\n ' var target = this.state.open ? 1 : 0;',\n // Ramp over ~10 ms rather than switching instantly, so opening and closing never clicks.\n ' var step = 1 / (sampleRate * 0.01);',\n ' var delay = this.delay;',\n ' var pos = this.delayPos;',\n ' var len = delay.length;',\n ' for (var i = 0; i < out.length; i++) {',\n ' var delayed = delay[pos];',\n ' delay[pos] = mic ? mic[i] : 0;',\n ' pos = (pos + 1) % len;',\n ' if (this.gain < target) { this.gain = Math.min(target, this.gain + step); }',\n ' else if (this.gain > target) { this.gain = Math.max(target, this.gain - step); }',\n ' out[i] = delayed * this.gain;',\n ' }',\n ' this.delayPos = pos;',\n ' if (currentTime * 1000 - this.lastPost > 100) {',\n ' this.lastPost = currentTime * 1000;',\n ' this.port.postMessage({ micDb: micDb, floorDb: this.state.floorDb, echoReturnDb: this.state.echoReturnDb, open: this.state.open, assistantSpeaking: this.state.assistantSpeaking });',\n ' }',\n ' return true;',\n ' }',\n '}',\n 'registerProcessor(\"coreai-mic-gate\", CoreAiMicGateProcessor);'\n ].join('\\n');\n\n /*\n * Builds a microphone gate for a captured stream.\n *\n * createMicGate(stream, mode) => Promise<{\n * track, // the gated track to send (or the raw mic when Web Audio is missing)\n * setMode(mode), // { pushToTalk, pttActive, bargeIn, speechHangoverMs }\n * attachAssistantStream(stream),// so the gate knows when the assistant is audible\n * getLevel(), // last measurement, for a mic meter\n * stop()\n * }>\n */\n function createMicGate(rawStream, mode) {\n var rawTrack = (rawStream && rawStream.getAudioTracks && rawStream.getAudioTracks()[0]) || null;\n var state = {\n ctx: null,\n node: null,\n micSource: null,\n remoteSource: null,\n dest: null,\n timer: 0,\n level: null,\n fallback: null,\n track: rawTrack,\n stopped: false\n };\n\n var gate = {\n track: rawTrack,\n // True when the gate is running on the audio thread. The fallback still gates, but on a timer that a\n // hidden tab throttles, so hosts and tests can tell the two apart.\n usingWorklet: false,\n getLevel: function () { return state.level; },\n setMode: function (next) {\n mode = next || mode;\n if (state.node && state.node.port) {\n try { state.node.port.postMessage(mode); } catch (e) { }\n }\n if (state.fallback) { state.fallback.mode = mode; }\n },\n attachAssistantStream: function (remoteStream) {\n attachAssistant(state, remoteStream);\n },\n stop: function () {\n state.stopped = true;\n if (state.timer) { try { window.clearInterval(state.timer); } catch (e) { } state.timer = 0; }\n if (state.node) {\n try { state.node.port.onmessage = null; state.node.disconnect(); } catch (e) { }\n state.node = null;\n }\n if (state.micSource) { try { state.micSource.disconnect(); } catch (e) { } state.micSource = null; }\n if (state.remoteSource) { try { state.remoteSource.disconnect(); } catch (e) { } state.remoteSource = null; }\n if (state.dest) { try { state.dest.disconnect(); } catch (e) { } state.dest = null; }\n if (state.ctx) { try { state.ctx.close(); } catch (e) { } state.ctx = null; }\n state.fallback = null;\n }\n };\n\n var AudioCtor = window.AudioContext || window.webkitAudioContext;\n if (!AudioCtor || !rawTrack) {\n return Promise.resolve(gate);\n }\n\n try {\n state.ctx = new AudioCtor();\n // A context created under a strict autoplay policy starts suspended, and a suspended gate emits\n // nothing at all — the model would simply never hear the user.\n if (state.ctx.state === 'suspended' && typeof state.ctx.resume === 'function') {\n state.ctx.resume().catch(function () { });\n }\n } catch (err) {\n state.ctx = null;\n\n return Promise.resolve(gate);\n }\n\n var blobUrl = null;\n if (state.ctx.audioWorklet && typeof state.ctx.audioWorklet.addModule === 'function') {\n try {\n blobUrl = URL.createObjectURL(new Blob([REALTIME_GATE_WORKLET_SOURCE], { type: 'application/javascript' }));\n } catch (err) {\n blobUrl = null;\n }\n }\n\n if (!blobUrl) {\n gate.track = buildFallbackGate(state, rawStream, rawTrack, mode);\n\n return Promise.resolve(gate);\n }\n\n return state.ctx.audioWorklet.addModule(blobUrl)\n .then(function () {\n try { URL.revokeObjectURL(blobUrl); } catch (e) { }\n if (state.stopped) { return gate; }\n\n var node = new AudioWorkletNode(state.ctx, 'coreai-mic-gate', {\n numberOfInputs: 2,\n numberOfOutputs: 1,\n outputChannelCount: [1],\n processorOptions: { lookaheadMs: REALTIME_GATE_LOOKAHEAD_MS, mode: mode }\n });\n state.node = node;\n node.port.onmessage = function (e) {\n state.level = e.data || null;\n // Also published on the module for support diagnostics (a host can read it from the console\n // without holding a reference to the gate).\n window.CoreAIRealtime.lastGateLevel = state.level;\n };\n\n state.micSource = state.ctx.createMediaStreamSource(rawStream);\n state.micSource.connect(node, 0, 0);\n\n state.dest = state.ctx.createMediaStreamDestination();\n node.connect(state.dest);\n\n if (state.pendingRemoteStream) { attachAssistant(state, state.pendingRemoteStream); }\n\n gate.track = (state.dest.stream.getAudioTracks()[0]) || rawTrack;\n gate.usingWorklet = true;\n\n return gate;\n })\n .catch(function (err) {\n try { URL.revokeObjectURL(blobUrl); } catch (e) { }\n if (window.console && console.warn) {\n console.warn('The realtime microphone gate worklet could not be loaded; using the simpler gate.', err);\n }\n gate.track = buildFallbackGate(state, rawStream, rawTrack, mode);\n\n return gate;\n });\n }\n\n function attachAssistant(state, remoteStream) {\n state.pendingRemoteStream = remoteStream || null;\n if (!state.ctx || !remoteStream || state.stopped) { return; }\n try {\n if (state.remoteSource) { try { state.remoteSource.disconnect(); } catch (e) { } }\n var src = state.ctx.createMediaStreamSource(remoteStream);\n state.remoteSource = src;\n\n if (state.node) {\n src.connect(state.node, 0, 1);\n\n return;\n }\n\n if (state.fallback) {\n var analyser = state.ctx.createAnalyser();\n analyser.fftSize = 2048;\n src.connect(analyser);\n state.fallback.remoteAnalyser = analyser;\n state.fallback.remoteData = new Float32Array(analyser.fftSize);\n }\n } catch (e) {\n // Assistant-level detection unavailable; the gate still opens on user speech.\n }\n }\n\n // Fallback for browsers without AudioWorklet: the same decision on a timer instead of the audio thread. A\n // timer is throttled in background tabs — worse than the worklet, better than nothing — and there is no\n // look-ahead here, so utterance onsets are still clipped.\n function buildFallbackGate(state, rawStream, rawTrack, mode) {\n try {\n var ctx = state.ctx;\n var source = ctx.createMediaStreamSource(rawStream);\n state.micSource = source;\n\n var analyser = ctx.createAnalyser();\n analyser.fftSize = 2048;\n source.connect(analyser);\n\n var gain = ctx.createGain();\n gain.gain.value = 0;\n source.connect(gain);\n var dest = ctx.createMediaStreamDestination();\n state.dest = dest;\n gain.connect(dest);\n\n var f = { mode: mode, remoteAnalyser: null, remoteData: null };\n state.fallback = f;\n if (state.pendingRemoteStream) { attachAssistant(state, state.pendingRemoteStream); }\n\n var data = new Float32Array(analyser.fftSize);\n\n // The same decision the worklet runs, on a timer instead of the audio thread. The floor adapts faster\n // here only because this loop runs ~50x/s rather than ~375x/s; everything else is shared.\n var gateState = createGateState();\n\n state.timer = window.setInterval(function () {\n analyser.getFloatTimeDomainData(data);\n var micDb = coreAiRmsDb(data);\n\n var assistantDb = -100;\n if (f.remoteAnalyser && f.remoteData) {\n f.remoteAnalyser.getFloatTimeDomainData(f.remoteData);\n assistantDb = coreAiRmsDb(f.remoteData);\n }\n\n var nowMs = (window.performance && performance.now) ? performance.now() : Date.now();\n coreAiGateDecide(gateState, { micDb: micDb, assistantDb: assistantDb, nowMs: nowMs, mode: f.mode || {} });\n\n state.level = {\n micDb: micDb,\n floorDb: gateState.floorDb,\n open: gateState.open,\n assistantSpeaking: gateState.assistantSpeaking\n };\n\n var target = gateState.open ? 1 : 0;\n try { gain.gain.setTargetAtTime(target, ctx.currentTime, 0.015); }\n catch (e) { gain.gain.value = target; }\n }, 20);\n\n return (dest.stream.getAudioTracks()[0]) || rawTrack;\n } catch (err) {\n // Web Audio unavailable; send the raw mic (ungated).\n return rawTrack;\n }\n }\n\n /*\n * Routes an audio element to the device the browser's echo canceller couples to, or to an explicitly chosen\n * one. Preference order:\n * 1. The caller's chosen device, when they picked one.\n * 2. The \"communications\" sink (Chromium). Rendering here doesn't just pick a device — it puts the browser's\n * audio pipeline in communications mode, which is what actually couples playback with the microphone's\n * echo canceller, and what keeps full duplex stable across turns.\n * 3. The concrete device the \"default\" alias points at, matched by groupId.\n * If neither alias exists — Firefox lists only concrete outputs — nothing is set and the browser's own default\n * stands. Guessing there routed the assistant to whatever was enumerated first (often an HDMI monitor), so it\n * appeared silent.\n */\n function routeOutputToPreferredDevice(el, chosenDeviceId) {\n if (!el || typeof el.setSinkId !== 'function') { return; }\n\n if (chosenDeviceId) {\n try { el.setSinkId(chosenDeviceId).catch(function () { }); } catch (e) { }\n\n return;\n }\n\n if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { return; }\n\n navigator.mediaDevices.enumerateDevices().then(function (devices) {\n var outputs = devices.filter(function (d) { return d.kind === 'audiooutput'; });\n if (!outputs.length) { return; }\n\n var target = '';\n\n for (var i = 0; i < outputs.length; i++) {\n if (outputs[i].deviceId === 'communications') { target = 'communications'; break; }\n }\n\n if (!target) {\n var defaultEntry = null;\n for (var d = 0; d < outputs.length; d++) {\n if (outputs[d].deviceId === 'default') { defaultEntry = outputs[d]; break; }\n }\n if (defaultEntry && defaultEntry.groupId) {\n for (var j = 0; j < outputs.length; j++) {\n if (outputs[j].deviceId !== 'default' && outputs[j].deviceId !== 'communications' && outputs[j].groupId === defaultEntry.groupId) {\n target = outputs[j].deviceId;\n break;\n }\n }\n }\n }\n\n if (target) {\n try { el.setSinkId(target).catch(function () { }); } catch (e) { }\n }\n }).catch(function () { });\n }\n\n // Autoplay policies (Firefox's \"Block audio and video\", locked-down profiles) can reject playback even after a\n // click, and a rejected play() is silent — the assistant simply never becomes audible. Ask explicitly and\n // report the failure instead of leaving the user with a mute conversation.\n function ensurePlayback(el, onBlocked) {\n if (!el || typeof el.play !== 'function') { return; }\n var played = el.play();\n if (played && typeof played.catch === 'function') {\n played.catch(function (err) {\n if (typeof onBlocked === 'function') { onBlocked(err); }\n if (window.console && console.warn) {\n console.warn('The browser blocked realtime audio playback. Interact with the page to enable audio.', err);\n }\n });\n }\n }\n\n function attach(opts) {\n opts = opts || {};\n var connection = opts.connection;\n var sel = opts.selectors || {};\n var realtimeVoiceName = opts.voiceName || '';\n var realtimeCapableDeployments = (opts.capableDeployments || []).map(function (n) { return (n || '').toLowerCase(); });\n var isRealtimeMode = !!opts.realtimeEnabled;\n var noop = function () { };\n var onActivate = opts.onActivate || noop;\n var onDeactivate = opts.onDeactivate || noop;\n var onEnterRealtimeMode = opts.onEnterRealtimeMode || noop;\n // The server tells us a user utterance was captured before it has been transcribed, so the host can show a\n // placeholder in the right position; onUserTurnDropped removes it when the utterance produced nothing.\n var onUserTurnPending = opts.onUserTurnPending || noop;\n var onUserTurnDropped = opts.onUserTurnDropped || noop;\n // Hosts are localizable elsewhere, so let them override the handful of strings this module renders.\n // Anything not supplied falls back to the English default.\n var strings = opts.strings || {};\n\n function localize(key, fallback) {\n return (typeof strings[key] === 'string') ? strings[key] : fallback;\n }\n var ensureConnected = opts.ensureConnected || function () { return Promise.resolve(true); };\n var sendStart = opts.sendStart || noop;\n // Optional: resolve the assistant voice live at session start (e.g. from a settings picker) so it\n // reflects the current selection rather than the value captured when the controller was attached.\n var getVoiceName = opts.getVoiceName || null;\n // Optional server-relay WebRTC transport: when the server advertises it and the callback is supplied, the\n // controller uses WebRTC (real acoustic echo cancellation) instead of the PCM-over-SignalR path.\n var sendStartWebRtc = opts.sendStartWebRtc || null;\n var webRtcEnabled = opts.webRtcEnabled === true && typeof window.RTCPeerConnection === 'function' && !!sendStartWebRtc;\n // A host-supplied override; normally the servers are fetched from the hub right before the peer is created\n // (see resolveIceServers) so configured TURN relays — and their short-lived credentials — are actually used.\n var webRtcIceServers = Array.isArray(opts.webRtcIceServers) && opts.webRtcIceServers.length\n ? opts.webRtcIceServers\n : null;\n var DEFAULT_ICE_SERVERS = [{ urls: 'stun:stun.l.google.com:19302' }];\n // Optional: notified on every state transition so the host can render \"Connecting…\", \"Listening\", etc.\n var onStateChange = opts.onStateChange || noop;\n var realtimeState = 'idle';\n\n function q(name) { var s = sel[name]; return s ? document.querySelector(s) : null; }\n\n var isRealtimeActive = false;\n // Server-driven session lifecycle (see bindRealtimeLifecycleHandlers): the server tells us when the\n // provider session is live, when the user interrupted, and when the session ended for any reason.\n var realtimeLifecycleBound = false, realtimeSessionReady = false, realtimeEndedNotice = null,\n realtimeCompatibilityNoticeEl = null, realtimeStatusEl = null;\n var realtimeStream = null, realtimeAudioCtx = null, realtimeSubject = null, realtimeProcessor = null,\n realtimeMicSource = null, realtimeZeroGain = null, realtimeGain = null, realtimePlayHead = 0, realtimeSources = [];\n // WebRTC transport state.\n var realtimeIsWebRtc = false, realtimePc = null, realtimeRemoteAudioEl = null, realtimeWebRtcHandlersBound = false,\n realtimeRemoteDescriptionSet = false, realtimePendingIce = [];\n // WebRTC connect-time fallback state: we decide WebRTC-vs-WebSocket only at connect time (never mid-session).\n var realtimeWebRtcConnected = false, realtimeWebRtcConnectTimer = null, realtimeFellBack = false;\n // How long to wait for the WebRTC peer to connect before dropping to the WebSocket transport. Once ICE\n // gathering has finished without producing a relay candidate there is nothing left to wait for on a\n // network that blocks UDP, so the wait is cut short rather than run to the full timeout.\n var REALTIME_WEBRTC_CONNECT_TIMEOUT_MS = 8000;\n var REALTIME_WEBRTC_NO_RELAY_TIMEOUT_MS = 5000;\n // Fixed receive-side cushion for assistant audio (see pc.ontrack). The server paces the stream on a\n // 20 ms clock, so this only has to cover network jitter, not provider burstiness.\n var REALTIME_WEBRTC_JITTER_BUFFER_TARGET_MS = 150;\n // Remembering a failed attempt for the rest of the browser session matters: without it, a user on a\n // network where WebRTC cannot work pays the full connection timeout — and a second microphone prompt —\n // at the start of every single conversation.\n var REALTIME_WEBRTC_BLOCKED_KEY = 'coreai.realtime.webrtcBlocked';\n var realtimeSawRelayCandidate = false;\n // WebRTC half-duplex echo guard: the shared microphone gate (see createMicGate) watches both the mic and\n // the assistant's remote audio and silences the outbound track unless the user is genuinely speaking, so\n // the model cannot hear itself even when AEC underperforms against loud open-room speakers. It also\n // enforces push-to-talk on the WebRTC mic track.\n var realtimeWebRtcMicTrack = null, realtimeGate = null, realtimeGatePendingRemoteStream = null;\n\n // Per-device audio preferences (interruptions, push-to-talk, volume, devices, language). They live in\n // localStorage because they depend on the listener's hardware, not on the interaction.\n var realtimeBargeIn = true, realtimePushToTalk = false, realtimePttActive = false,\n realtimePttBound = false, realtimePttKeyDown = null, realtimePttKeyUp = null, realtimePttButton = null, realtimePttUiEl = null,\n realtimeVolume = 1, realtimeMicDeviceId = '', realtimeOutputDeviceId = '', realtimeLanguage = '',\n realtimeAudioSettingsBuilt = false;\n\n // The half-duplex echo tail on the WebSocket transport: how long the microphone stays muted after the\n // scheduled end of the assistant's playback, covering the room's reverberation.\n var REALTIME_WS_ECHO_HANGOVER_SEC = 0.5;\n\n // Version 3 dropped the audio-setup presets, the voice-gate modes and the turn-detection sliders — all of\n // that is measured or decided automatically now — and, the part that matters to anyone who used version 2,\n // restores interruptions. The removed device-label guess had switched them off for every microphone whose\n // name merely looked like a room microphone, and the earlier repair deliberately left that alone, so users\n // found interruptions \"off by default\" with no idea why.\n var REALTIME_PREFS_VERSION = 3;\n\n function loadRealtimeAudioPrefs() {\n var prefs = { bargeIn: true, pushToTalk: false, volume: 1, micDeviceId: '', outputDeviceId: '', language: '', version: 0 };\n try {\n var raw = window.localStorage.getItem('coreai.realtime.audioPrefs');\n if (raw) {\n var parsed = JSON.parse(raw);\n if (typeof parsed.bargeIn === 'boolean') { prefs.bargeIn = parsed.bargeIn; }\n if (typeof parsed.pushToTalk === 'boolean') { prefs.pushToTalk = parsed.pushToTalk; }\n if (typeof parsed.volume === 'number' && isFinite(parsed.volume)) { prefs.volume = Math.min(1, Math.max(0, parsed.volume)); }\n if (typeof parsed.micDeviceId === 'string') { prefs.micDeviceId = parsed.micDeviceId; }\n if (typeof parsed.outputDeviceId === 'string') { prefs.outputDeviceId = parsed.outputDeviceId; }\n if (typeof parsed.language === 'string') { prefs.language = parsed.language; }\n if (typeof parsed.version === 'number') { prefs.version = parsed.version; }\n }\n } catch (err) { /* storage unavailable or blocked */ }\n\n return repairRealtimeAudioPrefs(prefs);\n }\n\n function repairRealtimeAudioPrefs(prefs) {\n if (prefs.version === REALTIME_PREFS_VERSION) { return prefs; }\n\n prefs.version = REALTIME_PREFS_VERSION;\n prefs.bargeIn = true;\n prefs.pushToTalk = false;\n saveRealtimeAudioPrefs(prefs);\n\n return prefs;\n }\n\n function saveRealtimeAudioPrefs(prefs) {\n try { window.localStorage.setItem('coreai.realtime.audioPrefs', JSON.stringify(prefs)); } catch (err) { }\n }\n\n function applyRealtimeAudioPrefs(prefs) {\n realtimeBargeIn = prefs.bargeIn !== false;\n realtimePushToTalk = !!prefs.pushToTalk;\n realtimeVolume = (typeof prefs.volume === 'number') ? prefs.volume : 1;\n realtimeMicDeviceId = prefs.micDeviceId || '';\n realtimeOutputDeviceId = prefs.outputDeviceId || '';\n realtimeLanguage = prefs.language || '';\n // The gate runs on the audio thread and cannot see these variables; push the change to it.\n syncRealtimeGateMode();\n if (realtimeGain) { realtimeGain.gain.value = realtimeVolume; }\n // On WebRTC the assistant plays through the hidden <audio> element, so the volume slider must drive its\n // volume directly. Lowering it also cuts the acoustic echo into the mic, which helps AEC with barge-in on.\n if (realtimeRemoteAudioEl) { realtimeRemoteAudioEl.volume = Math.max(0, Math.min(1, realtimeVolume)); }\n }\n\n // The push-to-talk handlers below run in the capture phase and swallow Space, which would otherwise eat\n // every space character the user types elsewhere on the page while a voice session is active.\n function isEditableTarget(target) {\n if (!target || !target.tagName) { return false; }\n var tag = target.tagName.toLowerCase();\n\n return tag === 'input' || tag === 'textarea' || tag === 'select' || target.isContentEditable === true;\n }\n\n // Push-to-talk: hold Space to open the mic. Bound only while a realtime session is active so it never\n // interferes with normal typing. Capture phase + preventDefault so Space never scrolls the page or\n // activates a focused button (Space-up on a focused button fires a click that would toggle the session).\n function attachRealtimePushToTalk() {\n if (realtimePttBound) { return; }\n realtimePttBound = true;\n realtimePttActive = false;\n realtimePttKeyDown = function (e) {\n if (realtimePushToTalk && !isEditableTarget(e.target) && (e.code === 'Space' || e.key === ' ')) {\n e.preventDefault();\n if (!e.repeat) { setRealtimePttActive(true); }\n }\n };\n realtimePttKeyUp = function (e) {\n if (realtimePushToTalk && !isEditableTarget(e.target) && (e.code === 'Space' || e.key === ' ')) {\n e.preventDefault();\n setRealtimePttActive(false);\n }\n };\n document.addEventListener('keydown', realtimePttKeyDown, true);\n document.addEventListener('keyup', realtimePttKeyUp, true);\n }\n\n function detachRealtimePushToTalk() {\n if (!realtimePttBound) { return; }\n realtimePttBound = false;\n realtimePttActive = false;\n try { document.removeEventListener('keydown', realtimePttKeyDown, true); } catch (err) { }\n try { document.removeEventListener('keyup', realtimePttKeyUp, true); } catch (err) { }\n }\n\n function setRealtimePttActive(active) {\n realtimePttActive = active;\n // The gate lives on the audio thread and cannot read this variable.\n syncRealtimeGateMode();\n if (realtimePttButton) {\n realtimePttButton.classList.toggle('btn-danger', active);\n realtimePttButton.classList.toggle('btn-outline-primary', !active);\n realtimePttButton.innerHTML = active\n ? '<i class=\"bi bi-mic-fill me-1\"></i> Listening…'\n : '<i class=\"bi bi-mic me-1\"></i> Hold to talk';\n }\n }\n\n // Shows a \"hold to talk\" control + hint while a push-to-talk realtime session is active.\n function buildRealtimePttUi() {\n var realtimeBtn = q('realtimeButton');\n if (!realtimeBtn || realtimePttUiEl) { return; }\n var coarse = window.matchMedia && window.matchMedia('(pointer: coarse)').matches;\n var bar = document.createElement('div');\n bar.className = 'text-center mt-2';\n var btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'btn btn-outline-primary btn-sm';\n btn.innerHTML = '<i class=\"bi bi-mic me-1\"></i> Hold to talk';\n var hint = document.createElement('div');\n hint.className = 'form-text mt-1 mb-0';\n hint.innerHTML = coarse\n ? 'Push-to-talk is on — press and hold the button to speak.'\n : 'Push-to-talk is on — hold <kbd>Space</kbd> or this button to speak.';\n bar.appendChild(btn);\n bar.appendChild(hint);\n var row = realtimeBtn.parentElement;\n if (row && row.parentElement) { row.parentElement.appendChild(bar); }\n else { realtimeBtn.insertAdjacentElement('afterend', bar); }\n realtimePttButton = btn;\n realtimePttUiEl = bar;\n btn.addEventListener('pointerdown', function (e) { e.preventDefault(); setRealtimePttActive(true); });\n btn.addEventListener('pointerup', function () { setRealtimePttActive(false); });\n btn.addEventListener('pointerleave', function () { setRealtimePttActive(false); });\n btn.addEventListener('pointercancel', function () { setRealtimePttActive(false); });\n setRealtimePttActive(false);\n }\n\n function removeRealtimePttUi() {\n realtimePttButton = null;\n if (realtimePttUiEl) { try { realtimePttUiEl.remove(); } catch (err) { } realtimePttUiEl = null; }\n }\n\n // Builds a gear-triggered popover next to the realtime button with the per-device audio settings.\n //\n // It is deliberately short: a microphone, a speaker, the volume, the language, and two switches. Everything\n // that used to be a knob here — echo margins, gate modes, turn-detection timing, audio-setup presets, an\n // echo self-test — is measured or decided automatically now. A user should be able to press \"Start\n // speaking\" and talk, in any room, without first understanding acoustics.\n function setupRealtimeAudioSettings() {\n var realtimeBtn = q('realtimeButton');\n if (!realtimeBtn || realtimeAudioSettingsBuilt) { return; }\n realtimeAudioSettingsBuilt = true;\n\n var prefs = loadRealtimeAudioPrefs();\n applyRealtimeAudioPrefs(prefs);\n\n var wrap = document.createElement('span');\n wrap.id = 'realtime-audio-settings';\n wrap.style.position = 'relative';\n wrap.style.display = 'inline-flex';\n\n var gear = document.createElement('button');\n gear.type = 'button';\n gear.className = 'btn btn-outline-secondary';\n gear.title = localize('settingsTitle', 'Voice settings');\n gear.setAttribute('aria-label', localize('settingsTitle', 'Voice settings'));\n gear.innerHTML = '<i class=\"bi bi-gear\"></i>';\n\n var langs = [['en', 'English'], ['es', 'Spanish'], ['fr', 'French'], ['de', 'German'], ['it', 'Italian'], ['pt', 'Portuguese'], ['nl', 'Dutch'], ['zh', 'Chinese'], ['ja', 'Japanese'], ['ko', 'Korean'], ['ar', 'Arabic'], ['hi', 'Hindi'], ['ru', 'Russian']];\n var langOptions = '<option value=\"\"' + (prefs.language === '' ? ' selected' : '') + '>' + localize('languageAuto', 'Automatic') + '</option>' +\n langs.map(function (l) { return '<option value=\"' + l[0] + '\"' + (prefs.language === l[0] ? ' selected' : '') + '>' + l[1] + '</option>'; }).join('');\n\n var panel = document.createElement('div');\n panel.className = 'card shadow-sm';\n panel.style.cssText = 'position:absolute;bottom:calc(100% + 6px);right:0;z-index:1080;width:290px;max-height:70vh;overflow:auto;display:none;';\n panel.innerHTML =\n '<div class=\"card-body p-3\">' +\n '<div class=\"fw-semibold mb-2\" style=\"font-size:0.85rem;\">' + localize('settingsTitle', 'Voice settings') + '</div>' +\n '<label class=\"form-label mb-1 d-block\" style=\"font-size:0.8rem;\">' + localize('microphone', 'Microphone') + '</label>' +\n '<select class=\"form-select form-select-sm js-mic mb-2\"><option value=\"\">' + localize('defaultMicrophone', 'Default microphone') + '</option></select>' +\n '<label class=\"form-label mb-1 d-block\" style=\"font-size:0.8rem;\">' + localize('speaker', 'Speaker') + '</label>' +\n '<select class=\"form-select form-select-sm js-out mb-1\"><option value=\"\">' + localize('automatic', 'Automatic') + '</option></select>' +\n '<button type=\"button\" class=\"btn btn-outline-secondary btn-sm mb-2 js-pick-out\" style=\"display:none;\">' + localize('chooseSpeaker', 'Choose speaker…') + '</button>' +\n '<div class=\"form-text mb-2 js-out-help\">' + localize('speakerHelp', 'Automatic uses the device your system uses for calls. If you cannot hear the assistant, pick the speakers you are actually listening to.') + '</div>' +\n '<label class=\"form-label mb-1 d-block\" style=\"font-size:0.8rem;\">' + localize('assistantVolume', 'Assistant volume') + ': <strong class=\"js-vol-val\">' + Math.round(prefs.volume * 100) + '</strong>%</label>' +\n '<input type=\"range\" class=\"form-range js-vol mb-2\" min=\"0\" max=\"100\" step=\"5\" value=\"' + Math.round(prefs.volume * 100) + '\">' +\n '<label class=\"form-label mb-1 d-block\" style=\"font-size:0.8rem;\">' + localize('language', 'Language') + '</label>' +\n '<select class=\"form-select form-select-sm js-lang mb-2\">' + langOptions + '</select>' +\n '<div class=\"form-check form-switch mb-1\">' +\n '<input class=\"form-check-input js-barge\" type=\"checkbox\" id=\"realtime-setting-barge\"' + (prefs.bargeIn ? ' checked' : '') + '>' +\n '<label class=\"form-check-label\" for=\"realtime-setting-barge\">' + localize('allowInterruptions', 'Allow interruptions') + '</label>' +\n '</div>' +\n '<div class=\"form-text mb-2\">' + localize('allowInterruptionsHelp', 'Talk over the assistant to interrupt it. Turn this off if the assistant keeps hearing itself through your speakers.') + '</div>' +\n '<div class=\"form-check form-switch mb-1\">' +\n '<input class=\"form-check-input js-ptt\" type=\"checkbox\" id=\"realtime-setting-ptt\"' + (prefs.pushToTalk ? ' checked' : '') + '>' +\n '<label class=\"form-check-label\" for=\"realtime-setting-ptt\">' + localize('pushToTalk', 'Push-to-talk') + '</label>' +\n '</div>' +\n '<div class=\"form-text\">' + localize('pushToTalkHelp', 'Hold <kbd>Space</kbd> (or the button) to talk. For very noisy places.') + '</div>' +\n '</div>';\n\n wrap.appendChild(gear);\n wrap.appendChild(panel);\n realtimeBtn.insertAdjacentElement('afterend', wrap);\n\n var bargeInput = panel.querySelector('.js-barge');\n var pttInput = panel.querySelector('.js-ptt');\n var volInput = panel.querySelector('.js-vol');\n var volVal = panel.querySelector('.js-vol-val');\n var micSelect = panel.querySelector('.js-mic');\n var outSelect = panel.querySelector('.js-out');\n var outPickButton = panel.querySelector('.js-pick-out');\n var langSelect = panel.querySelector('.js-lang');\n\n function persist() {\n var next = {\n bargeIn: bargeInput.checked,\n pushToTalk: pttInput.checked,\n volume: (parseInt(volInput.value, 10) || 0) / 100,\n micDeviceId: micSelect.value || '',\n outputDeviceId: outSelect.value || '',\n language: langSelect.value || '',\n version: REALTIME_PREFS_VERSION\n };\n applyRealtimeAudioPrefs(next);\n saveRealtimeAudioPrefs(next);\n pushRealtimeSettingsToServer();\n }\n\n function populateDevices() {\n if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { return; }\n navigator.mediaDevices.enumerateDevices().then(function (devices) {\n var options = ['<option value=\"\">' + localize('defaultMicrophone', 'Default microphone') + '</option>'];\n devices.filter(function (d) { return d.kind === 'audioinput'; }).forEach(function (d, i) {\n var label = d.label || (localize('microphone', 'Microphone') + ' ' + (i + 1));\n options.push('<option value=\"' + d.deviceId + '\"' + (d.deviceId === realtimeMicDeviceId ? ' selected' : '') + '>' + label.replace(/</g, '') + '</option>');\n });\n micSelect.innerHTML = options.join('');\n\n // Output devices are only enumerable on browsers that expose them (Chromium); elsewhere the\n // list stays on \"Automatic\" and the picker button below is the way in.\n var outs = devices.filter(function (d) { return d.kind === 'audiooutput' && d.deviceId && d.deviceId !== 'communications' && d.deviceId !== 'default'; });\n if (outs.length) {\n var outOptions = ['<option value=\"\">' + localize('automatic', 'Automatic') + '</option>'];\n outs.forEach(function (d, i) {\n var label = d.label || (localize('speaker', 'Speaker') + ' ' + (i + 1));\n outOptions.push('<option value=\"' + d.deviceId + '\"' + (d.deviceId === realtimeOutputDeviceId ? ' selected' : '') + '>' + label.replace(/</g, '') + '</option>');\n });\n outSelect.innerHTML = outOptions.join('');\n }\n }).catch(function () { });\n }\n populateDevices();\n\n // Unplugging the headset mid-conversation silently changes which devices exist. Refresh the lists, and\n // end the session if the microphone it was actually using has gone — continuing on a different device\n // without saying so is worse than stopping and letting the user restart.\n if (navigator.mediaDevices && typeof navigator.mediaDevices.addEventListener === 'function') {\n navigator.mediaDevices.addEventListener('devicechange', function () {\n populateDevices();\n if (!isRealtimeActive || !realtimeMicDeviceId) { return; }\n navigator.mediaDevices.enumerateDevices().then(function (devices) {\n var stillThere = devices.some(function (d) { return d.kind === 'audioinput' && d.deviceId === realtimeMicDeviceId; });\n if (!stillThere) { endRealtimeSessionFromServer('device_lost'); }\n }).catch(function () { });\n });\n }\n\n function constrainPanel() {\n // Keep the popover on screen horizontally. It is anchored to the button's right edge, which is\n // correct where the button sits on the right of a wide row — but in a narrow layout, or with the\n // button near the left edge, a 290px panel would otherwise hang off the side of the window.\n panel.style.right = '0px';\n panel.style.left = 'auto';\n var panelRect = panel.getBoundingClientRect();\n if (panelRect.left < 8) {\n panel.style.right = (panelRect.left - 8) + 'px';\n }\n\n // Cap its height to the space above the button up to the nearest scroll/fixed ancestor, so it\n // scrolls instead of spilling out the top.\n var rect = gear.getBoundingClientRect();\n var boundaryTop = 8;\n var node = panel.parentElement ? panel.parentElement.parentElement : null;\n while (node && node !== document.body && node !== document.documentElement) {\n var s = window.getComputedStyle(node);\n if (s.overflowY === 'auto' || s.overflowY === 'scroll' || s.overflowY === 'hidden' || s.position === 'fixed') {\n boundaryTop = Math.max(boundaryTop, node.getBoundingClientRect().top);\n break;\n }\n node = node.parentElement;\n }\n panel.style.maxHeight = Math.max(160, rect.top - boundaryTop - 10) + 'px';\n }\n gear.addEventListener('click', function (e) {\n e.stopPropagation();\n var showing = panel.style.display === 'none';\n if (showing) { panel.style.display = 'block'; constrainPanel(); populateDevices(); }\n panel.style.display = showing ? 'block' : 'none';\n });\n panel.addEventListener('click', function (e) { e.stopPropagation(); });\n document.addEventListener('click', function () { panel.style.display = 'none'; });\n bargeInput.addEventListener('change', persist);\n pttInput.addEventListener('change', persist);\n volInput.addEventListener('input', function () { volVal.textContent = volInput.value; persist(); });\n micSelect.addEventListener('change', persist);\n langSelect.addEventListener('change', persist);\n outSelect.addEventListener('change', function () {\n persist();\n // Apply live: the whole point of the picker is that a user who cannot hear the assistant can fix\n // it without ending the conversation.\n applyRealtimeOutputDevice();\n });\n\n // Firefox exposes no output device list until the user picks one through this prompt.\n if (navigator.mediaDevices && typeof navigator.mediaDevices.selectAudioOutput === 'function') {\n outPickButton.style.display = '';\n outPickButton.addEventListener('click', function () {\n navigator.mediaDevices.selectAudioOutput().then(function (device) {\n if (!device || !device.deviceId) { return; }\n var option = document.createElement('option');\n option.value = device.deviceId;\n option.textContent = device.label || localize('selectedSpeaker', 'Selected speaker');\n outSelect.appendChild(option);\n outSelect.value = device.deviceId;\n persist();\n applyRealtimeOutputDevice();\n }).catch(function () { });\n });\n }\n }\n\n // The host supplies the button's markup as a data attribute. It is sanitized when DOMPurify is present;\n // when it is not, the label falls back to text rather than injecting unsanitized markup — the module is\n // shared, and not every host that loads it also loads DOMPurify.\n function setRealtimeButtonHtml(button, html) {\n if (!html) { return; }\n\n if (window.DOMPurify && typeof window.DOMPurify.sanitize === 'function') {\n button.replaceChildren(window.DOMPurify.sanitize(html, { RETURN_DOM_FRAGMENT: true }));\n\n return;\n }\n\n // No DOMPurify: never parse the untrusted markup as HTML. Strip any tags with a plain-string pass and\n // collapse whitespace, then render the remaining label as text only.\n var text = html.replace(/<[^>]*>/g, ' ').replace(/\\s+/g, ' ').trim();\n button.replaceChildren(document.createTextNode(text));\n }\n\n function updateRealtimeButton() {\n var realtimeBtn = q('realtimeButton');\n if (!realtimeBtn) { return; }\n if (isRealtimeActive) {\n realtimeBtn.classList.add('active', 'btn-primary');\n realtimeBtn.classList.remove('btn-dark', 'btn-outline-dark', 'btn-outline-secondary');\n realtimeBtn.title = realtimeBtn.getAttribute('data-end-title') || 'End Conversation';\n setRealtimeButtonHtml(realtimeBtn, realtimeBtn.getAttribute('data-end-html'));\n } else {\n realtimeBtn.classList.remove('active', 'btn-primary', 'btn-dark', 'btn-outline-secondary');\n realtimeBtn.classList.add('btn-outline-dark');\n realtimeBtn.blur();\n realtimeBtn.title = realtimeBtn.getAttribute('data-start-title') || 'Start speaking';\n setRealtimeButtonHtml(realtimeBtn, realtimeBtn.getAttribute('data-start-html'));\n }\n }\n\n // Switches the input between text and audio-only (realtime). Called at load and whenever the selected\n // deployment changes to/from a realtime model.\n function applyRealtimeMode(enable) {\n isRealtimeMode = enable;\n\n var realtimeBtn = q('realtimeButton');\n var micBtn = q('micButton');\n var conversationBtn = q('conversationButton');\n var inputEl = q('input');\n var sendBtn = q('sendButton');\n var audioSettings = document.getElementById('realtime-audio-settings');\n\n if (enable) {\n onEnterRealtimeMode();\n if (inputEl) { inputEl.hidden = true; }\n if (sendBtn) { sendBtn.hidden = true; }\n if (micBtn) { micBtn.hidden = true; }\n if (conversationBtn) { conversationBtn.hidden = true; }\n if (realtimeBtn) { realtimeBtn.hidden = false; }\n if (audioSettings) { audioSettings.hidden = false; }\n } else {\n if (isRealtimeActive) { stopRealtimeConversation(); }\n if (realtimeBtn) { realtimeBtn.hidden = true; }\n if (audioSettings) { audioSettings.hidden = true; }\n removeCompatibilityModeNotice();\n clearRealtimeStatus();\n if (inputEl) { inputEl.hidden = false; }\n if (sendBtn) { sendBtn.hidden = false; }\n if (micBtn) { micBtn.hidden = false; }\n if (conversationBtn) { conversationBtn.hidden = false; }\n }\n\n updateRealtimeButton();\n }\n\n // Barge-in and the voice-activity knobs are enforced by three layers at once: this client's microphone\n // gate, the server's input pump, and the provider's own turn detection. Changing only this one leaves the\n // three disagreeing — the classic symptom being barge-in switched off mid-conversation while the assistant\n // still interrupts itself — so a change during a live session is sent on to the other two.\n function pushRealtimeSettingsToServer() {\n if (!isRealtimeActive || !connection || typeof connection.send !== 'function') { return; }\n try { connection.send('UpdateRealtimeSettings', realtimeBargeIn, null, null); } catch (err) { }\n }\n\n // Reports the session's state to the host so it can show something more honest than a button that flips to\n // \"End Conversation\" before anything has connected.\n // What each state says to the user. Only the states worth narrating appear here; the rest clear the line.\n var REALTIME_STATE_TEXT = {\n 'requesting-mic': localize('requestingMic', 'Waiting for microphone access…'),\n 'connecting': localize('connecting', 'Connecting…'),\n 'listening': localize('listening', 'Listening'),\n 'playback-blocked': localize('playbackBlocked', 'Audio is blocked by the browser — click the page to enable it.')\n };\n\n function setRealtimeState(state, detail) {\n if (realtimeState === state) { return; }\n realtimeState = state;\n\n var text = REALTIME_STATE_TEXT[state];\n if (text) { showRealtimeStatus(text, false); }\n else if (state === 'idle') { clearRealtimeStatus(); }\n\n try { onStateChange({ state: state, transport: realtimeIsWebRtc ? 'webrtc' : 'websocket', detail: detail || null }); }\n catch (err) { }\n }\n\n // The server owns the session's lifecycle; the browser cannot infer it from the audio it happens to\n // receive. Without these handlers a session that ended server-side (provider socket closed, session cap,\n // error, authorization failure) leaves the mic open and the button stuck on \"End Conversation\" while audio\n // is streamed into nothing.\n function bindRealtimeLifecycleHandlers() {\n if (realtimeLifecycleBound || !connection) { return; }\n realtimeLifecycleBound = true;\n\n connection.on('ReceiveRealtimeEvent', function (identifier, type, payload) {\n if (!isRealtimeActive) { return; }\n\n if (type === 'session_ready') {\n realtimeSessionReady = true;\n setRealtimeState('listening');\n } else if (type === 'session_ended') {\n endRealtimeSessionFromServer(payload || 'completed');\n } else if (type === 'speech_started') {\n // Barge-in: stop the reply that is already scheduled for playback. On WebRTC the server flushes\n // the peer itself, so this only matters for the WebSocket transport — but calling it there too\n // is harmless and keeps the two transports behaving the same.\n if (realtimeBargeIn) { flushRealtimePlayback(); }\n } else if (type === 'playback_flush') {\n flushRealtimePlayback();\n } else if (type === 'user_turn_pending') {\n onUserTurnPending(payload);\n } else if (type === 'user_turn_dropped') {\n onUserTurnDropped(payload);\n }\n });\n\n // An error while a voice session is running is terminal for that session: the server has already\n // stopped, so keep the mic open no longer.\n connection.on('ReceiveError', function () {\n if (!isRealtimeActive) { return; }\n\n // An error while the WebRTC peer is still being set up is a reason to try the other transport, not\n // to give up: the WebSocket path may well work. Treating every error as terminal is what turned a\n // recoverable server-side handshake failure into a session that silently did nothing at all.\n if (realtimeIsWebRtc && !realtimeWebRtcConnected && !realtimeFellBack) {\n fallbackToWebSocket('server reported an error before the peer connected');\n\n return;\n }\n\n // Once the session is live, an error is terminal — the server has already stopped.\n endRealtimeSessionFromServer('error');\n });\n\n if (typeof connection.onclose === 'function') {\n connection.onclose(function () {\n if (isRealtimeActive) { endRealtimeSessionFromServer('disconnected'); }\n });\n }\n\n if (typeof connection.onreconnecting === 'function') {\n connection.onreconnecting(function () {\n if (isRealtimeActive) { endRealtimeSessionFromServer('disconnected'); }\n });\n }\n }\n\n function endRealtimeSessionFromServer(reason) {\n realtimeEndedNotice = reason;\n stopRealtimeConversation();\n setRealtimeState('ended', reason);\n if (window.console && console.info) {\n console.info('The realtime voice session ended (' + reason + ').');\n }\n\n // An idle close is deliberate and recoverable, so say so and offer to pick the conversation back up\n // rather than leaving the user staring at a button that silently stopped working.\n if (reason === 'idle') {\n showRealtimeStatus(localize('endedIdle', 'Voice paused after a period of silence.'), true);\n } else if (reason === 'disconnected') {\n showRealtimeStatus(localize('endedDisconnected', 'Voice session ended — the connection dropped.'), true);\n } else if (reason === 'error') {\n showRealtimeStatus(localize('endedError', 'Voice session ended unexpectedly.'), true);\n } else if (reason === 'device_lost') {\n showRealtimeStatus(localize('endedDeviceLost', 'Voice session ended — the microphone was disconnected.'), true);\n }\n }\n\n // A single status line under the realtime button, optionally with a Resume button.\n function showRealtimeStatus(text, offerResume) {\n var realtimeBtn = q('realtimeButton');\n if (!realtimeBtn) { return; }\n\n if (!realtimeStatusEl) {\n realtimeStatusEl = document.createElement('div');\n realtimeStatusEl.className = 'form-text mt-2 mb-0 text-center';\n realtimeStatusEl.setAttribute('role', 'status');\n realtimeStatusEl.setAttribute('aria-live', 'polite');\n var row = realtimeBtn.parentElement;\n if (row && row.parentElement) { row.parentElement.appendChild(realtimeStatusEl); }\n else { realtimeBtn.insertAdjacentElement('afterend', realtimeStatusEl); }\n }\n\n realtimeStatusEl.replaceChildren();\n realtimeStatusEl.appendChild(document.createTextNode(text));\n\n if (offerResume) {\n var resume = document.createElement('button');\n resume.type = 'button';\n resume.className = 'btn btn-link btn-sm p-0 ms-2 align-baseline';\n resume.textContent = localize('resume', 'Resume');\n resume.addEventListener('click', function () {\n clearRealtimeStatus();\n startRealtimeConversation();\n });\n realtimeStatusEl.appendChild(resume);\n }\n }\n\n function clearRealtimeStatus() {\n if (!realtimeStatusEl) { return; }\n try { realtimeStatusEl.remove(); } catch (err) { }\n realtimeStatusEl = null;\n }\n\n // Resolves the ICE servers from the server immediately before creating the peer. Fetching them per session\n // (rather than embedding them at page render time) is what makes ephemeral TURN credentials usable: they\n // expire, and a page open for an hour would otherwise hand the browser a dead credential. Falls back to a\n // public STUN server so a failed call degrades to today's behavior rather than breaking the session.\n function resolveIceServers() {\n if (webRtcIceServers) { return Promise.resolve(webRtcIceServers); }\n if (!connection || typeof connection.invoke !== 'function') { return Promise.resolve(DEFAULT_ICE_SERVERS); }\n\n return connection.invoke('GetRealtimeIceServers')\n .then(function (servers) {\n return (Array.isArray(servers) && servers.length) ? servers : DEFAULT_ICE_SERVERS;\n })\n .catch(function (err) {\n if (window.console && console.warn) {\n console.warn('Could not resolve the realtime ICE servers; using the default STUN server.', err);\n }\n\n return DEFAULT_ICE_SERVERS;\n });\n }\n\n function isWebRtcKnownBlocked() {\n try { return window.sessionStorage.getItem(REALTIME_WEBRTC_BLOCKED_KEY) === '1'; }\n catch (err) { return false; }\n }\n\n function rememberWebRtcBlocked() {\n try { window.sessionStorage.setItem(REALTIME_WEBRTC_BLOCKED_KEY, '1'); } catch (err) { }\n }\n\n // A one-line, dismissible note under the realtime button. Shown once per browser session when voice falls\n // back to the WebSocket transport, because the difference is audible (weaker echo handling in an open\n // room) and users otherwise have no way to know why.\n function showCompatibilityModeNotice() {\n if (realtimeCompatibilityNoticeEl) { return; }\n var realtimeBtn = q('realtimeButton');\n if (!realtimeBtn) { return; }\n\n var note = document.createElement('div');\n note.className = 'form-text mt-2 mb-0 text-center';\n note.setAttribute('role', 'status');\n note.textContent = localize('compatibilityMode', 'Using compatibility audio mode. Echo cancellation may be weaker — headphones are recommended.');\n\n var row = realtimeBtn.parentElement;\n if (row && row.parentElement) { row.parentElement.appendChild(note); }\n else { realtimeBtn.insertAdjacentElement('afterend', note); }\n realtimeCompatibilityNoticeEl = note;\n }\n\n function removeCompatibilityModeNotice() {\n if (!realtimeCompatibilityNoticeEl) { return; }\n try { realtimeCompatibilityNoticeEl.remove(); } catch (err) { }\n realtimeCompatibilityNoticeEl = null;\n }\n\n function startRealtimeConversation() {\n if (!isRealtimeMode || isRealtimeActive || !connection) { return; }\n\n applyRealtimeAudioPrefs(loadRealtimeAudioPrefs());\n realtimeFellBack = false;\n realtimeSessionReady = false;\n realtimeEndedNotice = null;\n clearRealtimeStatus();\n bindRealtimeLifecycleHandlers();\n setRealtimeState('requesting-mic');\n\n // Prefer the WebRTC transport when the server advertises it: the browser's echo canceller references\n // the assistant's media track, so the model can ignore its own voice with the mic open (open rooms).\n // If the peer cannot connect (blocked UDP, no TURN, unsupported), we fall back to WebSocket at connect\n // time — see fallbackToWebSocket. The decision is made once, before the session starts.\n if (webRtcEnabled && !isWebRtcKnownBlocked()) {\n startRealtimeWebRtcConversation();\n\n return;\n }\n\n startRealtimeWebSocketConversation();\n }\n\n function startRealtimeWebSocketConversation() {\n if (webRtcEnabled) { showCompatibilityModeNotice(); }\n attachRealtimePushToTalk();\n // Drop focus from the just-clicked button so Space acts as push-to-talk, not a re-click.\n var focusedBtn = q('realtimeButton');\n if (focusedBtn) { try { focusedBtn.blur(); } catch (err) { } }\n\n var audioConstraints = {\n channelCount: 1,\n echoCancellation: { ideal: true },\n noiseSuppression: true,\n autoGainControl: true,\n // Ask for the strongest available acoustic echo cancellation so the model can ignore its own\n // voice in an open room (loud speakers + open mic). These are Chromium hints requested as\n // \"ideal\", so any browser that doesn't support them simply ignores them — never a hard failure.\n // echoCancellationType 'system' prefers the OS/hardware AEC over the browser's software AEC.\n echoCancellationType: { ideal: 'system' },\n voiceIsolation: { ideal: true }\n };\n if (realtimeMicDeviceId) { audioConstraints.deviceId = { exact: realtimeMicDeviceId }; }\n\n navigator.mediaDevices.getUserMedia({ audio: audioConstraints })\n .then(function (stream) {\n ensureConnected()\n .then(function () {\n realtimeStream = stream;\n isRealtimeActive = true;\n onActivate();\n updateRealtimeButton();\n setRealtimeState('connecting');\n\n var AudioContextCtor = window.AudioContext || window.webkitAudioContext;\n realtimeAudioCtx = new AudioContextCtor({ sampleRate: REALTIME_SAMPLE_RATE });\n // A context created under a strict autoplay policy starts suspended, and a suspended\n // context plays nothing at all — silently. Ask for it explicitly.\n if (realtimeAudioCtx.state === 'suspended' && typeof realtimeAudioCtx.resume === 'function') {\n realtimeAudioCtx.resume().catch(function (err) {\n setRealtimeState('playback-blocked');\n if (window.console && console.warn) {\n console.warn('The browser blocked realtime audio playback. Interact with the page to enable audio.', err);\n }\n });\n }\n realtimePlayHead = 0;\n realtimeSources = [];\n realtimeGain = realtimeAudioCtx.createGain();\n realtimeGain.gain.value = (realtimeVolume != null) ? realtimeVolume : 1;\n realtimeGain.connect(realtimeAudioCtx.destination);\n realtimeSubject = new window.signalR.Subject();\n\n var ctxAtStart = realtimeAudioCtx;\n var processor = realtimeAudioCtx.createScriptProcessor(4096, 1, 1);\n realtimeProcessor = processor;\n\n // The gate watches the assistant's playback to know when it is audible; on this\n // transport the assistant is a Web Audio graph, so tap the output gain into a stream.\n var monitorDest = realtimeAudioCtx.createMediaStreamDestination();\n realtimeGain.connect(monitorDest);\n\n // Send the gated microphone rather than the raw one, exactly as the WebRTC transport\n // does, so this fallback is not the one transport where the model hears its own echo.\n // Until the gate's worklet is ready the processor has no input and streams silence.\n setupMicGate(stream).then(function (micTrack) {\n if (!isRealtimeActive || realtimeAudioCtx !== ctxAtStart || !micTrack) { return; }\n var gatedStream = new MediaStream([micTrack]);\n var source = realtimeAudioCtx.createMediaStreamSource(gatedStream);\n realtimeMicSource = source;\n source.connect(processor);\n if (realtimeGate) { realtimeGate.attachAssistantStream(monitorDest.stream); }\n });\n\n processor.onaudioprocess = function (event) {\n var input = event.inputBuffer.getChannelData(0);\n // Always send a frame (silence when muted) so the server keeps a continuous audio\n // stream and its voice-activity detector promptly notices the pause and responds.\n // Muted cases: push-to-talk not held, or the echo guard while the assistant plays back.\n var muted;\n if (realtimePushToTalk) {\n muted = !realtimePttActive;\n } else {\n muted = !realtimeBargeIn && realtimeAudioCtx && realtimeAudioCtx.currentTime < realtimePlayHead + REALTIME_WS_ECHO_HANGOVER_SEC;\n }\n var pcm = new Int16Array(input.length);\n if (!muted) {\n for (var i = 0; i < input.length; i++) {\n var s = Math.max(-1, Math.min(1, input[i]));\n pcm[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;\n }\n }\n var bytes = new Uint8Array(pcm.buffer);\n var binary = '';\n for (var b = 0; b < bytes.length; b++) { binary += String.fromCharCode(bytes[b]); }\n try { realtimeSubject.next(btoa(binary)); } catch (err) { /* completed */ }\n };\n\n // A zero-gain node keeps the processor alive without echoing the mic to the speakers.\n var zeroGain = realtimeAudioCtx.createGain();\n zeroGain.gain.value = 0;\n realtimeZeroGain = zeroGain;\n processor.connect(zeroGain);\n zeroGain.connect(realtimeAudioCtx.destination);\n\n // \"Auto\" means auto-detect: send nothing. Sending the browser's locale instead pinned transcription\n // and the reply language to it, so a bilingual user with an English browser speaking Spanish\n // got English-forced (garbage) transcripts and an English-locked assistant.\n var language = realtimeLanguage || null;\n var voice = (getVoiceName && getVoiceName()) || realtimeVoiceName || '';\n sendStart(realtimeSubject, voice, language, null, null, realtimeBargeIn);\n if (realtimePushToTalk) { buildRealtimePttUi(); }\n })\n .catch(function (err) {\n stream.getTracks().forEach(function (track) { track.stop(); });\n isRealtimeActive = false;\n onDeactivate();\n updateRealtimeButton();\n console.error('The realtime conversation could not start because the chat connection is not available.', err);\n });\n })\n .catch(function (err) {\n console.error('Microphone access denied:', err);\n isRealtimeActive = false;\n onDeactivate();\n updateRealtimeButton();\n });\n }\n\n // --- WebRTC (server-relay) transport ---\n\n function startRealtimeWebRtcConversation() {\n // Keep the WebRTC capture constraints minimal. WebRTC's own echo canceller (AEC3) already references\n // the remote assistant track we render into the hidden <audio> element, which is the entire reason we\n // use WebRTC for open-room audio. The stronger hints we request on the WebSocket path\n // (echoCancellationType:'system' + voiceIsolation) are counterproductive here: layered on top of the\n // peer-connection AEC loop they gate the mic down to near-silence (~1-3% of full scale), so the model\n // never detects speech. Ask only for standard echo cancellation and let AEC3 do its job.\n var micConstraints = {\n // Match what ChatGPT's voice mode requests: a plain echoCancellation:true and nothing else exotic.\n // The browser still applies its default noise suppression and auto gain; we only pass those through\n // so the user's toggles can turn them off.\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true\n };\n if (realtimeMicDeviceId) { micConstraints.deviceId = { exact: realtimeMicDeviceId }; }\n\n navigator.mediaDevices.getUserMedia({ audio: micConstraints })\n .then(function (stream) {\n ensureConnected()\n .then(function () { return resolveIceServers(); })\n .then(function (iceServers) {\n realtimeStream = stream;\n isRealtimeActive = true;\n realtimeIsWebRtc = true;\n onActivate();\n updateRealtimeButton();\n setRealtimeState('connecting');\n\n realtimeRemoteDescriptionSet = false;\n realtimePendingIce = [];\n realtimeWebRtcConnected = false;\n var pc = new RTCPeerConnection({ iceServers: iceServers });\n realtimePc = pc;\n\n // Push-to-talk and the barge-in/echo guard both gate the outbound mic track. Wire the\n // same push-to-talk controls the WebSocket path uses so they work on WebRTC too.\n // Device labels only become readable after permission is granted, so this is the first\n // chance to notice a headset (safe for full duplex) or a standalone mic in front of\n // speakers (not). Only ever a suggestion: an explicit choice is never overridden.\n\n attachRealtimePushToTalk();\n var focusedBtn = q('realtimeButton');\n if (focusedBtn) { try { focusedBtn.blur(); } catch (err) { } }\n if (realtimePushToTalk) { buildRealtimePttUi(); }\n\n // Play the assistant's remote track through a hidden <audio> element. This gives the\n // browser's echo canceller a reference to remove the assistant's voice from the mic, and\n // is what the echo-guard monitor listens to for half-duplex mic muting.\n var audioEl = document.createElement('audio');\n audioEl.autoplay = true;\n audioEl.style.display = 'none';\n audioEl.volume = Math.max(0, Math.min(1, (realtimeVolume != null) ? realtimeVolume : 1));\n document.body.appendChild(audioEl);\n realtimeRemoteAudioEl = audioEl;\n // Route playback so the browser couples it with the mic's echo canceller as a proper\n // AEC reference (see routeRealtimeOutputToDefaultDevice for the preference order).\n routeRealtimeOutputToDefaultDevice(audioEl);\n pc.ontrack = function (e) {\n // Ask the browser to hold a fixed cushion of received audio before playing it,\n // rather than the adaptive minimum it would otherwise pick. Network jitter then\n // lands inside the cushion instead of making the jitter buffer stretch or speed\n // speech up to re-adapt; the audio itself is played as received. Ignored by\n // browsers without the property.\n try {\n if (e.receiver && 'jitterBufferTarget' in e.receiver) {\n e.receiver.jitterBufferTarget = REALTIME_WEBRTC_JITTER_BUFFER_TARGET_MS;\n }\n } catch (err) { }\n\n if (e.streams && e.streams[0]) {\n audioEl.srcObject = e.streams[0];\n ensureRealtimePlayback(audioEl);\n // Let the gate watch the assistant's level so it can raise the speech threshold\n // while the assistant talks (barge-in on) and stay closed until it finishes\n // (barge-in off).\n attachWebRtcAssistantAnalyser(e.streams[0]);\n }\n };\n\n realtimeSawRelayCandidate = false;\n pc.onicecandidate = function (e) {\n if (e.candidate) {\n if (e.candidate.candidate && e.candidate.candidate.indexOf(' relay ') !== -1) {\n realtimeSawRelayCandidate = true;\n }\n try { connection.send('AddRealtimeIceCandidate', e.candidate.candidate, e.candidate.sdpMid || '', e.candidate.sdpMLineIndex || 0); } catch (err) { }\n\n return;\n }\n\n // Gathering finished. With no relay candidate there is no path left for a network\n // that blocks UDP, so stop waiting the full timeout for something that cannot come.\n if (!realtimeSawRelayCandidate && !realtimeWebRtcConnected && realtimeWebRtcConnectTimer) {\n clearTimeout(realtimeWebRtcConnectTimer);\n realtimeWebRtcConnectTimer = setTimeout(function () {\n if (!realtimeWebRtcConnected && isRealtimeActive) {\n fallbackToWebSocket('no relay candidate and no direct connection');\n }\n }, REALTIME_WEBRTC_NO_RELAY_TIMEOUT_MS);\n }\n };\n pc.onconnectionstatechange = function () {\n if (pc.connectionState === 'connected') {\n markWebRtcConnected();\n } else if (pc.connectionState === 'failed') {\n // Before the peer connects, a failure means WebRTC is unusable here — fall back.\n // After it connects, a drop ends the session (we never migrate mid-session).\n if (!realtimeWebRtcConnected) { fallbackToWebSocket('connection failed'); }\n else if (isRealtimeActive) { stopRealtimeConversation(); }\n } else if (pc.connectionState === 'closed' && isRealtimeActive && realtimeWebRtcConnected) {\n stopRealtimeConversation();\n }\n };\n pc.oniceconnectionstatechange = function () {\n var s = pc.iceConnectionState;\n if (s === 'connected' || s === 'completed') {\n markWebRtcConnected();\n } else if (s === 'failed' && !realtimeWebRtcConnected) {\n fallbackToWebSocket('ICE failed');\n }\n };\n\n bindWebRtcSignalingHandlers();\n\n // Fall back to WebSocket if the peer does not connect within the timeout (blocked UDP,\n // missing TURN, etc.). Cleared as soon as the peer connects (markWebRtcConnected).\n realtimeWebRtcConnectTimer = setTimeout(function () {\n if (!realtimeWebRtcConnected && isRealtimeActive) {\n fallbackToWebSocket('connection timed out');\n }\n }, REALTIME_WEBRTC_CONNECT_TIMEOUT_MS);\n\n // Send a gated version of the mic: silent unless the user is actually speaking. The gate\n // loads an AudioWorklet, so the track is only available once that resolves — hence the\n // offer is created here rather than synchronously above.\n setupMicGate(stream)\n .then(function (micTrackToSend) {\n if (realtimePc !== pc) { return null; }\n if (micTrackToSend) { pc.addTrack(micTrackToSend, stream); }\n\n return pc.createOffer();\n })\n .then(function (offer) {\n if (!offer || realtimePc !== pc) { return null; }\n\n return pc.setLocalDescription(offer).then(function () { return offer; });\n })\n .then(function (offer) {\n if (!offer) { return; }\n // \"Auto\" means auto-detect: send nothing (see the WebSocket path above).\n var language = realtimeLanguage || null;\n var voice = (getVoiceName && getVoiceName()) || realtimeVoiceName || '';\n sendStartWebRtc(offer.sdp, voice, language, null, null, realtimeBargeIn);\n })\n .catch(function (err) {\n console.error('Failed to create the WebRTC offer; falling back to WebSocket.', err);\n fallbackToWebSocket('offer failed');\n });\n })\n .catch(function (err) {\n stream.getTracks().forEach(function (t) { t.stop(); });\n isRealtimeActive = false;\n realtimeIsWebRtc = false;\n onDeactivate();\n updateRealtimeButton();\n console.error('The realtime WebRTC conversation could not start because the chat connection is not available.', err);\n });\n })\n .catch(function (err) {\n console.error('Microphone access denied:', err);\n isRealtimeActive = false;\n realtimeIsWebRtc = false;\n onDeactivate();\n updateRealtimeButton();\n });\n }\n\n function bindWebRtcSignalingHandlers() {\n if (realtimeWebRtcHandlersBound) { return; }\n realtimeWebRtcHandlersBound = true;\n\n connection.on('ReceiveRealtimeAnswer', function (sdp) {\n if (!realtimePc) { return; }\n realtimePc.setRemoteDescription({ type: 'answer', sdp: sdp })\n .then(function () {\n realtimeRemoteDescriptionSet = true;\n // Flush any ICE candidates that arrived before the answer was applied.\n var pending = realtimePendingIce;\n realtimePendingIce = [];\n pending.forEach(function (init) {\n try { realtimePc.addIceCandidate(init).catch(function () { }); } catch (err) { }\n });\n })\n .catch(function (err) { console.error('Failed to apply the WebRTC answer.', err); });\n });\n connection.on('ReceiveRealtimeIceCandidate', function (candidate, sdpMid, sdpMLineIndex) {\n if (!realtimePc || !candidate) { return; }\n var init = { candidate: candidate, sdpMid: sdpMid, sdpMLineIndex: sdpMLineIndex };\n // A candidate can only be added after the remote description (answer) is set; buffer until then.\n if (realtimeRemoteDescriptionSet) {\n try { realtimePc.addIceCandidate(init).catch(function () { }); } catch (err) { }\n } else {\n realtimePendingIce.push(init);\n }\n });\n }\n\n function stopRealtimeWebRtc() {\n stopWebRtcEchoGuard();\n realtimeWebRtcMicTrack = null;\n if (realtimePc) {\n try { realtimePc.close(); } catch (err) { }\n realtimePc = null;\n }\n if (realtimeRemoteAudioEl) {\n try { realtimeRemoteAudioEl.srcObject = null; realtimeRemoteAudioEl.remove(); } catch (err) { }\n realtimeRemoteAudioEl = null;\n }\n realtimeIsWebRtc = false;\n }\n\n function markWebRtcConnected() {\n if (realtimeWebRtcConnected) { return; }\n realtimeWebRtcConnected = true;\n if (realtimeWebRtcConnectTimer) { clearTimeout(realtimeWebRtcConnectTimer); realtimeWebRtcConnectTimer = null; }\n }\n\n // --- Microphone gate (thin wrapper over the shared factory) ----------------------------------------\n\n // How long the gate stays open after the user's level drops. The gate is a safety net around echo, not a\n // turn detector: the provider's turn detection sees the real speech and should be the one deciding a\n // turn is over, so this must comfortably outlast the pause it is willing to wait through. The gate emits\n // digital silence when it closes, and whichever of the two expires first is what actually ends the turn.\n var REALTIME_GATE_HANGOVER_MS = 2000;\n\n function realtimeGateModeMessage() {\n return {\n pushToTalk: !!realtimePushToTalk,\n pttActive: !!realtimePttActive,\n bargeIn: !!realtimeBargeIn,\n speechHangoverMs: REALTIME_GATE_HANGOVER_MS\n };\n }\n\n // The gate runs on the audio thread and cannot read this closure's variables, so every settings or\n // push-to-talk change has to be pushed to it explicitly.\n function syncRealtimeGateMode() {\n if (realtimeGate) { realtimeGate.setMode(realtimeGateModeMessage()); }\n }\n\n // Builds the gate and resolves with the track to send (over the peer, or into the WebSocket capture graph).\n function setupMicGate(rawStream) {\n stopWebRtcEchoGuard();\n var rawTrack = (rawStream && rawStream.getAudioTracks()[0]) || null;\n realtimeWebRtcMicTrack = rawTrack;\n\n return createMicGate(rawStream, realtimeGateModeMessage()).then(function (gate) {\n realtimeGate = gate;\n if (realtimeGatePendingRemoteStream) {\n gate.attachAssistantStream(realtimeGatePendingRemoteStream);\n }\n\n return gate.track || rawTrack;\n });\n }\n\n // Feeds the assistant's remote stream into the gate so it knows when the assistant is audible — for the\n // raised threshold with barge-in on, and for half-duplex with barge-in off. The track can arrive before\n // the gate's worklet has finished loading, so remember it either way.\n function attachWebRtcAssistantAnalyser(remoteStream) {\n realtimeGatePendingRemoteStream = remoteStream || null;\n if (realtimeGate && remoteStream) { realtimeGate.attachAssistantStream(remoteStream); }\n }\n\n function stopWebRtcEchoGuard() {\n if (realtimeGate) {\n try { realtimeGate.stop(); } catch (e) { }\n realtimeGate = null;\n }\n realtimeGatePendingRemoteStream = null;\n }\n\n // Route the assistant playback element so the browser's echo canceller couples to it as an AEC reference,\n // the way ChatGPT's voice mode does. Preference order:\n // 1. The \"communications\" sink (Chrome/Edge). Rendering here doesn't just pick a device — it puts the\n // browser's audio pipeline in COMMUNICATIONS mode, which is what actually couples playback with the\n // mic's echo canceller. This is what ChatGPT uses and what keeps full-duplex stable across turns.\n // 2. The concrete device the \"default\" alias points at, matched by groupId.\n // If neither alias exists — Firefox exposes only concrete outputs — we deliberately do nothing and let the\n // browser use its own default. Picking \"the first concrete output\" there routed the assistant to whatever\n // device happened to be enumerated first (often an HDMI monitor), so the assistant appeared silent.\n // Applies the user's chosen speaker to the playing element, live.\n function applyRealtimeOutputDevice() {\n routeOutputToPreferredDevice(realtimeRemoteAudioEl, realtimeOutputDeviceId);\n }\n\n function routeRealtimeOutputToDefaultDevice(el) {\n routeOutputToPreferredDevice(el, realtimeOutputDeviceId);\n }\n\n function ensureRealtimePlayback(el) {\n ensurePlayback(el, function () { setRealtimeState('playback-blocked'); });\n }\n\n // Connect-time only: tear down the failed WebRTC attempt and restart on the known-good WebSocket path.\n // Never called once a session is established (see the connection-state handlers), so we never migrate audio\n // mid-conversation — we only choose the transport before the model starts responding.\n function fallbackToWebSocket(reason) {\n if (realtimeFellBack) { return; }\n realtimeFellBack = true;\n if (realtimeWebRtcConnectTimer) { clearTimeout(realtimeWebRtcConnectTimer); realtimeWebRtcConnectTimer = null; }\n if (window.console && console.warn) {\n console.warn('Realtime WebRTC transport unavailable (' + reason + '); falling back to the WebSocket transport.');\n }\n rememberWebRtcBlocked();\n showCompatibilityModeNotice();\n\n try { if (realtimeStream) { realtimeStream.getTracks().forEach(function (t) { t.stop(); }); } } catch (err) { }\n realtimeStream = null;\n stopRealtimeWebRtc();\n realtimeIsWebRtc = false;\n // Reset the active flag so the WebSocket start proceeds cleanly; it re-activates immediately.\n isRealtimeActive = false;\n\n startRealtimeWebSocketConversation();\n }\n\n function stopRealtimeConversation() {\n if (!isRealtimeActive) { return; }\n\n if (realtimeWebRtcConnectTimer) { clearTimeout(realtimeWebRtcConnectTimer); realtimeWebRtcConnectTimer = null; }\n\n isRealtimeActive = false;\n realtimeSessionReady = false;\n onDeactivate();\n updateRealtimeButton();\n detachRealtimePushToTalk();\n removeRealtimePttUi();\n if (!realtimeEndedNotice) { setRealtimeState('idle'); }\n\n if (realtimeIsWebRtc) {\n stopRealtimeWebRtc();\n try { if (realtimeStream) { realtimeStream.getTracks().forEach(function (t) { t.stop(); }); } } catch (err) { }\n realtimeStream = null;\n\n return;\n }\n\n try { if (realtimeSubject) { realtimeSubject.complete(); } } catch (err) { /* already completed */ }\n realtimeSubject = null;\n stopWebRtcEchoGuard();\n\n try { if (realtimeProcessor) { realtimeProcessor.disconnect(); realtimeProcessor.onaudioprocess = null; } } catch (err) { }\n try { if (realtimeMicSource) { realtimeMicSource.disconnect(); } } catch (err) { }\n try { if (realtimeZeroGain) { realtimeZeroGain.disconnect(); } } catch (err) { }\n try { if (realtimeGain) { realtimeGain.disconnect(); } } catch (err) { }\n try { if (realtimeStream) { realtimeStream.getTracks().forEach(function (t) { t.stop(); }); } } catch (err) { }\n realtimeProcessor = null;\n realtimeMicSource = null;\n realtimeZeroGain = null;\n realtimeGain = null;\n realtimeStream = null;\n\n flushRealtimePlayback();\n try { if (realtimeAudioCtx) { realtimeAudioCtx.close(); } } catch (err) { }\n realtimeAudioCtx = null;\n }\n\n function toggleRealtime() {\n if (isRealtimeActive) { stopRealtimeConversation(); return; }\n startRealtimeConversation();\n }\n\n // Resolves with the receive-side statistics of the assistant's audio track (WebRTC transport only), in\n // the browser's own words: packets lost, jitter, how much the jitter buffer is holding, and how often it\n // had to conceal or time-stretch audio. Null on the WebSocket transport.\n function getTransportStats() {\n if (!realtimePc || typeof realtimePc.getStats !== 'function') { return Promise.resolve(null); }\n\n return realtimePc.getStats().then(function (report) {\n // Where playback actually goes (the \"communications\" sink puts Chrome's pipeline in communications\n // mode; empty means the browser default) and the receiver's requested cushion, so a report of\n // \"sounds different in this browser\" can be tied to the output path.\n var result = {\n transport: 'webrtc',\n inbound: null,\n codec: null,\n sinkId: (realtimeRemoteAudioEl && typeof realtimeRemoteAudioEl.sinkId === 'string') ? realtimeRemoteAudioEl.sinkId : null,\n jitterBufferTargetMs: (function () {\n try {\n var r = realtimePc.getReceivers().filter(function (x) { return x.track && x.track.kind === 'audio'; })[0];\n\n return (r && 'jitterBufferTarget' in r) ? r.jitterBufferTarget : null;\n } catch (e) { return null; }\n })()\n };\n report.forEach(function (stat) {\n if (stat.type === 'inbound-rtp' && stat.kind === 'audio') {\n result.inbound = {\n packetsReceived: stat.packetsReceived,\n packetsLost: stat.packetsLost,\n packetsDiscarded: stat.packetsDiscarded,\n jitterMs: typeof stat.jitter === 'number' ? Math.round(stat.jitter * 1000) : null,\n jitterBufferDelayMs: (typeof stat.jitterBufferDelay === 'number' && stat.jitterBufferEmittedCount)\n ? Math.round(stat.jitterBufferDelay / stat.jitterBufferEmittedCount * 1000) : null,\n totalSamplesReceived: stat.totalSamplesReceived,\n concealedSamples: stat.concealedSamples,\n concealmentEvents: stat.concealmentEvents,\n silentConcealedSamples: stat.silentConcealedSamples,\n insertedSamplesForDeceleration: stat.insertedSamplesForDeceleration,\n removedSamplesForAcceleration: stat.removedSamplesForAcceleration,\n audioLevel: stat.audioLevel\n };\n if (stat.codecId) {\n var codec = report.get(stat.codecId);\n if (codec) { result.codec = { mimeType: codec.mimeType, clockRate: codec.clockRate, channels: codec.channels, sdpFmtpLine: codec.sdpFmtpLine }; }\n }\n }\n });\n\n return result;\n }).catch(function () { return null; });\n }\n\n function playRealtimePcm(bytes) {\n if (!realtimeAudioCtx || !bytes || bytes.length < 2) { return; }\n var ctx = realtimeAudioCtx;\n var sampleCount = Math.floor(bytes.length / 2);\n var pcm = new Int16Array(bytes.buffer, bytes.byteOffset, sampleCount);\n var f32 = new Float32Array(sampleCount);\n for (var i = 0; i < sampleCount; i++) { f32[i] = pcm[i] / 0x8000; }\n\n var buffer = ctx.createBuffer(1, sampleCount, ctx.sampleRate);\n buffer.copyToChannel(f32, 0);\n var src = ctx.createBufferSource();\n src.buffer = buffer;\n src.connect(realtimeGain || ctx.destination);\n\n var now = ctx.currentTime;\n if (realtimePlayHead < now) { realtimePlayHead = now; }\n src.start(realtimePlayHead);\n realtimePlayHead += buffer.duration;\n realtimeSources.push(src);\n src.onended = function () { realtimeSources = realtimeSources.filter(function (s) { return s !== src; }); };\n }\n\n function flushRealtimePlayback() {\n realtimeSources.forEach(function (s) { try { s.stop(); } catch (err) { } });\n realtimeSources = [];\n if (realtimeAudioCtx) { realtimePlayHead = realtimeAudioCtx.currentTime; }\n }\n\n function isRealtimeDeployment(deploymentName) {\n if (!deploymentName) { return false; }\n return realtimeCapableDeployments.indexOf(deploymentName.toLowerCase()) !== -1;\n }\n\n // --- Wire up ---\n var realtimeBtn = q('realtimeButton');\n if (realtimeBtn) {\n realtimeBtn.addEventListener('click', function (e) {\n // Ignore keyboard-synthesized clicks (Space/Enter) during an active realtime session, so a\n // push-to-talk Space press can never toggle the session off.\n if (e && e.detail === 0 && isRealtimeActive) { return; }\n toggleRealtime();\n });\n setupRealtimeAudioSettings();\n }\n\n var deploymentSelect = q('deploymentSelect');\n if (deploymentSelect) {\n deploymentSelect.addEventListener('change', function () {\n applyRealtimeMode(isRealtimeDeployment(deploymentSelect.value));\n });\n }\n\n // Apply the initial input mode: audio-only when the interaction already uses a realtime deployment.\n applyRealtimeMode(isRealtimeMode || (deploymentSelect && isRealtimeDeployment(deploymentSelect.value)));\n\n var controller = {\n toggle: toggleRealtime,\n start: startRealtimeConversation,\n stop: stopRealtimeConversation,\n applyMode: applyRealtimeMode,\n isRealtimeDeployment: isRealtimeDeployment,\n receivePcm: playRealtimePcm,\n isActive: function () { return isRealtimeActive; },\n getState: function () { return realtimeState; },\n // The gate's most recent measurement (level, tracked noise floor, open/closed, assistant audible), for\n // hosts that want to render a microphone meter or explain why the mic is muted.\n getGateLevel: function () { return realtimeGate ? realtimeGate.getLevel() : null; },\n // The browser's own receive-side statistics for the assistant's audio on the WebRTC transport\n // (packets lost, jitter, jitter-buffer delay, concealment), for diagnosing choppy playback.\n getTransportStats: getTransportStats\n };\n\n // The most recently attached controller, for diagnostics from the console or a test.\n window.CoreAIRealtime.activeController = controller;\n\n return controller;\n }\n\n window.CoreAIRealtime = {\n attach: attach,\n createMicGate: createMicGate,\n // Exposed for tests: the gate's rules are where every one of its historical failures lived, and they are\n // far easier to pin down with numbers than with audio.\n decideGate: coreAiGateDecide,\n createGateState: createGateState,\n rmsDb: coreAiRmsDb,\n // Host-agnostic playback helpers, so a host that drives realtime itself still shares one implementation\n // of these rather than growing its own.\n routeOutputToPreferredDevice: routeOutputToPreferredDevice,\n ensurePlayback: ensurePlayback\n };\n})(window, document);\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e,t){"use strict";function n(e,t){var n=t.micDb,a="number"==typeof t.assistantDb?t.assistantDb:-100,o=t.nowMs,i=t.mode||{},r=null===e.lastMs?0:Math.max(0,Math.min(50,o-e.lastMs));e.lastMs=o,a>-50&&(e.assistantUntil=o+400);var c=o<e.assistantUntil;if(a>e.assistantPeakDb?e.assistantPeakDb=a:e.assistantPeakDb=Math.max(-100,e.assistantPeakDb-.02*r),n<=-95){if(null===e.floorDb)return e.open=!1,e}else null===e.floorDb&&(e.floorDb=Math.min(n,-50));if(n<e.floorDb)e.floorDb+=(n-e.floorDb)*Math.min(1,.0075*r);else if(!c){var l=null!==e.openSince&&o-e.openSince>1e4,s=e.open&&!l?1e-4:56e-5;e.floorDb+=(n-e.floorDb)*Math.min(1,s*r)}if(e.floorDb<-75&&(e.floorDb=-75),c&&!e.open&&a>-50&&!i.pushToTalk){var u=n-e.assistantPeakDb;if(null===e.echoReturnDb)e.echoReturnDb=u;else{var d=e.echoLearnedMs<1e3,f=u>e.echoReturnDb?d?.02:.0012:6e-4;e.echoReturnDb+=(u-e.echoReturnDb)*Math.min(1,f*r)}e.echoLearnedMs+=r}var m,p,v=null===e.echoReturnDb?-100:e.assistantPeakDb+e.echoReturnDb;c?(m=Math.max(e.floorDb+12,v+8,-45),p=Math.max(e.floorDb+3,v+3)):(m=e.floorDb+9,p=e.floorDb+3);var h=i.speechHangoverMs||2e3;n>m?c&&!e.open?(null===e.aboveSince&&(e.aboveSince=o),o-e.aboveSince>=250&&(e.speakUntil=o+h)):e.speakUntil=o+h:(e.aboveSince=null,e.open&&n>p&&(e.speakUntil=Math.max(e.speakUntil,o+250)));var b=o<e.speakUntil;return!c&&e.wasAssistantSpeaking&&(e.listenGraceUntil=o+1500),e.wasAssistantSpeaking=c,e.assistantSpeaking=c,i.pushToTalk?e.open=!!i.pttActive:i.bargeIn?e.open=b:e.open=!c&&(b||o<e.listenGraceUntil),e.open&&null===e.openSince?e.openSince=o:e.open||(e.openSince=null),e}function a(){return{floorDb:null,lastMs:null,speakUntil:0,assistantUntil:0,assistantPeakDb:-100,echoReturnDb:null,echoLearnedMs:0,aboveSince:null,listenGraceUntil:0,wasAssistantSpeaking:!1,assistantSpeaking:!1,open:!1,openSince:null}}function o(e){if(!e||!e.length)return-100;for(var t=0,n=0;n<e.length;n++)t+=e[n]*e[n];var a=Math.sqrt(t/e.length);return a>1e-7?20*Math.log10(a):-100}var i=["var decide = "+n.toString()+";","var newState = "+a.toString()+";","var rmsDb = "+o.toString()+";","class CoreAiMicGateProcessor extends AudioWorkletProcessor {"," constructor(options) {"," super();"," var o = (options && options.processorOptions) || {};"," this.delay = new Float32Array(Math.max(1, Math.round(sampleRate * (o.lookaheadMs || 80) / 1000)));"," this.delayPos = 0;"," this.gain = 0;"," this.mode = o.mode || {};"," this.state = newState();"," this.lastPost = 0;"," this.port.onmessage = function (e) { this.mode = e.data || {}; }.bind(this);"," }"," process(inputs, outputs) {"," var mic = (inputs[0] && inputs[0][0]) || null;"," var assistant = (inputs[1] && inputs[1][0]) || null;"," var out = (outputs[0] && outputs[0][0]) || null;"," if (!out) { return true; }"," var micDb = rmsDb(mic);"," decide(this.state, { micDb: micDb, assistantDb: rmsDb(assistant), nowMs: currentTime * 1000, mode: this.mode });"," var target = this.state.open ? 1 : 0;"," var step = 1 / (sampleRate * 0.01);"," var delay = this.delay;"," var pos = this.delayPos;"," var len = delay.length;"," for (var i = 0; i < out.length; i++) {"," var delayed = delay[pos];"," delay[pos] = mic ? mic[i] : 0;"," pos = (pos + 1) % len;"," if (this.gain < target) { this.gain = Math.min(target, this.gain + step); }"," else if (this.gain > target) { this.gain = Math.max(target, this.gain - step); }"," out[i] = delayed * this.gain;"," }"," this.delayPos = pos;"," if (currentTime * 1000 - this.lastPost > 100) {"," this.lastPost = currentTime * 1000;"," this.port.postMessage({ micDb: micDb, floorDb: this.state.floorDb, echoReturnDb: this.state.echoReturnDb, open: this.state.open, assistantSpeaking: this.state.assistantSpeaking });"," }"," return true;"," }","}",'registerProcessor("coreai-mic-gate", CoreAiMicGateProcessor);'].join("\n");function r(t,n){var a=t&&t.getAudioTracks&&t.getAudioTracks()[0]||null,o={ctx:null,node:null,micSource:null,remoteSource:null,dest:null,timer:0,level:null,fallback:null,track:a,stopped:!1},r={track:a,usingWorklet:!1,getLevel:function(){return o.level},setMode:function(e){if(n=e||n,o.node&&o.node.port)try{o.node.port.postMessage(n)}catch(e){}o.fallback&&(o.fallback.mode=n)},attachAssistantStream:function(e){c(o,e)},stop:function(){if(o.stopped=!0,o.timer){try{e.clearInterval(o.timer)}catch(e){}o.timer=0}if(o.node){try{o.node.port.onmessage=null,o.node.disconnect()}catch(e){}o.node=null}if(o.micSource){try{o.micSource.disconnect()}catch(e){}o.micSource=null}if(o.remoteSource){try{o.remoteSource.disconnect()}catch(e){}o.remoteSource=null}if(o.dest){try{o.dest.disconnect()}catch(e){}o.dest=null}if(o.ctx){try{o.ctx.close()}catch(e){}o.ctx=null}o.fallback=null}},s=e.AudioContext||e.webkitAudioContext;if(!s||!a)return Promise.resolve(r);try{o.ctx=new s,"suspended"===o.ctx.state&&"function"==typeof o.ctx.resume&&o.ctx.resume().catch(function(){})}catch(e){return o.ctx=null,Promise.resolve(r)}var u=null;if(o.ctx.audioWorklet&&"function"==typeof o.ctx.audioWorklet.addModule)try{u=URL.createObjectURL(new Blob([i],{type:"application/javascript"}))}catch(e){u=null}return u?o.ctx.audioWorklet.addModule(u).then(function(){try{URL.revokeObjectURL(u)}catch(e){}if(o.stopped)return r;var i=new AudioWorkletNode(o.ctx,"coreai-mic-gate",{numberOfInputs:2,numberOfOutputs:1,outputChannelCount:[1],processorOptions:{lookaheadMs:80,mode:n}});return o.node=i,i.port.onmessage=function(t){o.level=t.data||null,e.CoreAIRealtime.lastGateLevel=o.level},o.micSource=o.ctx.createMediaStreamSource(t),o.micSource.connect(i,0,0),o.dest=o.ctx.createMediaStreamDestination(),i.connect(o.dest),o.pendingRemoteStream&&c(o,o.pendingRemoteStream),r.track=o.dest.stream.getAudioTracks()[0]||a,r.usingWorklet=!0,r}).catch(function(i){try{URL.revokeObjectURL(u)}catch(e){}return e.console&&console.warn&&console.warn("The realtime microphone gate worklet could not be loaded; using the simpler gate.",i),r.track=l(o,t,a,n),r}):(r.track=l(o,t,a,n),Promise.resolve(r))}function c(e,t){if(e.pendingRemoteStream=t||null,e.ctx&&t&&!e.stopped)try{if(e.remoteSource)try{e.remoteSource.disconnect()}catch(e){}var n=e.ctx.createMediaStreamSource(t);if(e.remoteSource=n,e.node)return void n.connect(e.node,0,1);if(e.fallback){var a=e.ctx.createAnalyser();a.fftSize=2048,n.connect(a),e.fallback.remoteAnalyser=a,e.fallback.remoteData=new Float32Array(a.fftSize)}}catch(e){}}function l(t,a,i,r){try{var l=t.ctx,s=l.createMediaStreamSource(a);t.micSource=s;var u=l.createAnalyser();u.fftSize=2048,s.connect(u);var d=l.createGain();d.gain.value=0,s.connect(d);var f=l.createMediaStreamDestination();t.dest=f,d.connect(f);var m={mode:r,remoteAnalyser:null,remoteData:null};t.fallback=m,t.pendingRemoteStream&&c(t,t.pendingRemoteStream);var p=new Float32Array(u.fftSize),v={floorDb:null,lastMs:null,speakUntil:0,assistantUntil:0,assistantPeakDb:-100,echoReturnDb:null,echoLearnedMs:0,aboveSince:null,listenGraceUntil:0,wasAssistantSpeaking:!1,assistantSpeaking:!1,open:!1,openSince:null};return t.timer=e.setInterval(function(){u.getFloatTimeDomainData(p);var a=o(p),i=-100;m.remoteAnalyser&&m.remoteData&&(m.remoteAnalyser.getFloatTimeDomainData(m.remoteData),i=o(m.remoteData));var r=e.performance&&performance.now?performance.now():Date.now();n(v,{micDb:a,assistantDb:i,nowMs:r,mode:m.mode||{}}),t.level={micDb:a,floorDb:v.floorDb,open:v.open,assistantSpeaking:v.assistantSpeaking};var c=v.open?1:0;try{d.gain.setTargetAtTime(c,l.currentTime,.015)}catch(e){d.gain.value=c}},20),f.stream.getAudioTracks()[0]||i}catch(e){return i}}function s(e,t){if(e&&"function"==typeof e.setSinkId)if(t)try{e.setSinkId(t).catch(function(){})}catch(e){}else navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.enumerateDevices().then(function(t){var n=t.filter(function(e){return"audiooutput"===e.kind});if(n.length){for(var a="",o=0;o<n.length;o++)if("communications"===n[o].deviceId){a="communications";break}if(!a){for(var i=null,r=0;r<n.length;r++)if("default"===n[r].deviceId){i=n[r];break}if(i&&i.groupId)for(var c=0;c<n.length;c++)if("default"!==n[c].deviceId&&"communications"!==n[c].deviceId&&n[c].groupId===i.groupId){a=n[c].deviceId;break}}if(a)try{e.setSinkId(a).catch(function(){})}catch(e){}}}).catch(function(){})}function u(t,n){if(t&&"function"==typeof t.play){var a=t.play();a&&"function"==typeof a.catch&&a.catch(function(t){"function"==typeof n&&n(t),e.console&&console.warn&&console.warn("The browser blocked realtime audio playback. Interact with the page to enable audio.",t)})}}e.CoreAIRealtime={attach:function(n){var a=(n=n||{}).connection,o=n.selectors||{},i=n.voiceName||"",c=(n.capableDeployments||[]).map(function(e){return(e||"").toLowerCase()}),l=!!n.realtimeEnabled,d=function(){},f=n.onActivate||d,m=n.onDeactivate||d,p=n.onEnterRealtimeMode||d,v=n.onUserTurnPending||d,h=n.onUserTurnDropped||d,b=n.strings||{};function g(e,t){return"string"==typeof b[e]?b[e]:t}var y=n.ensureConnected||function(){return Promise.resolve(!0)},k=n.sendStart||d,S=n.getVoiceName||null,D=n.sendStartWebRtc||null,M=!0===n.webRtcEnabled&&"function"==typeof e.RTCPeerConnection&&!!D,T=Array.isArray(n.webRtcIceServers)&&n.webRtcIceServers.length?n.webRtcIceServers:null,I=[{urls:"stun:stun.l.google.com:19302"}],E=n.onStateChange||d,w="idle";function x(e){var n=o[e];return n?t.querySelector(n):null}var A=!1,C=!1,R=null,L=null,j=null,P=null,B=null,U=null,O=null,N=null,G=null,F=null,H=0,W=[],q=!1,z=null,_=null,V=!1,J=!1,Y=[],K=!1,Q=null,X=!1,Z="coreai.realtime.webrtcBlocked",$=!1,ee=null,te=null,ne=!0,ae=!1,oe=!1,ie=!1,re=null,ce=null,le=null,se=null,ue=1,de="",fe="",me="",pe=!1;function ve(){var t={bargeIn:!0,pushToTalk:!1,volume:1,micDeviceId:"",outputDeviceId:"",language:"",version:0};try{var n=e.localStorage.getItem("coreai.realtime.audioPrefs");if(n){var a=JSON.parse(n);"boolean"==typeof a.bargeIn&&(t.bargeIn=a.bargeIn),"boolean"==typeof a.pushToTalk&&(t.pushToTalk=a.pushToTalk),"number"==typeof a.volume&&isFinite(a.volume)&&(t.volume=Math.min(1,Math.max(0,a.volume))),"string"==typeof a.micDeviceId&&(t.micDeviceId=a.micDeviceId),"string"==typeof a.outputDeviceId&&(t.outputDeviceId=a.outputDeviceId),"string"==typeof a.language&&(t.language=a.language),"number"==typeof a.version&&(t.version=a.version)}}catch(e){}return function(e){if(3===e.version)return e;return e.version=3,e.bargeIn=!0,e.pushToTalk=!1,he(e),e}(t)}function he(t){try{e.localStorage.setItem("coreai.realtime.audioPrefs",JSON.stringify(t))}catch(e){}}function be(e){ne=!1!==e.bargeIn,ae=!!e.pushToTalk,ue="number"==typeof e.volume?e.volume:1,de=e.micDeviceId||"",fe=e.outputDeviceId||"",me=e.language||"",Oe(),F&&(F.gain.value=ue),_&&(_.volume=Math.max(0,Math.min(1,ue)))}function ge(e){if(!e||!e.tagName)return!1;var t=e.tagName.toLowerCase();return"input"===t||"textarea"===t||"select"===t||!0===e.isContentEditable}function ye(){ie||(ie=!0,oe=!1,re=function(e){!ae||ge(e.target)||"Space"!==e.code&&" "!==e.key||(e.preventDefault(),e.repeat||ke(!0))},ce=function(e){!ae||ge(e.target)||"Space"!==e.code&&" "!==e.key||(e.preventDefault(),ke(!1))},t.addEventListener("keydown",re,!0),t.addEventListener("keyup",ce,!0))}function ke(e){oe=e,Oe(),le&&(le.classList.toggle("btn-danger",e),le.classList.toggle("btn-outline-primary",!e),le.innerHTML=e?'<i class="bi bi-mic-fill me-1"></i> Listening…':'<i class="bi bi-mic me-1"></i> Hold to talk')}function Se(){var n=x("realtimeButton");if(n&&!se){var a=e.matchMedia&&e.matchMedia("(pointer: coarse)").matches,o=t.createElement("div");o.className="text-center mt-2";var i=t.createElement("button");i.type="button",i.className="btn btn-outline-primary btn-sm",i.innerHTML='<i class="bi bi-mic me-1"></i> Hold to talk';var r=t.createElement("div");r.className="form-text mt-1 mb-0",r.innerHTML=a?"Push-to-talk is on — press and hold the button to speak.":"Push-to-talk is on — hold <kbd>Space</kbd> or this button to speak.",o.appendChild(i),o.appendChild(r);var c=n.parentElement;c&&c.parentElement?c.parentElement.appendChild(o):n.insertAdjacentElement("afterend",o),le=i,se=o,i.addEventListener("pointerdown",function(e){e.preventDefault(),ke(!0)}),i.addEventListener("pointerup",function(){ke(!1)}),i.addEventListener("pointerleave",function(){ke(!1)}),i.addEventListener("pointercancel",function(){ke(!1)}),ke(!1)}}function De(n,a){if(a)if(e.DOMPurify&&"function"==typeof e.DOMPurify.sanitize)n.replaceChildren(e.DOMPurify.sanitize(a,{RETURN_DOM_FRAGMENT:!0}));else{var o=a.replace(/<[^>]*>/g," ").replace(/\s+/g," ").trim();n.replaceChildren(t.createTextNode(o))}}function Me(){var e=x("realtimeButton");e&&(A?(e.classList.add("active","btn-primary"),e.classList.remove("btn-dark","btn-outline-dark","btn-outline-secondary"),e.title=e.getAttribute("data-end-title")||"End Conversation",De(e,e.getAttribute("data-end-html"))):(e.classList.remove("active","btn-primary","btn-dark","btn-outline-secondary"),e.classList.add("btn-outline-dark"),e.blur(),e.title=e.getAttribute("data-start-title")||"Start speaking",De(e,e.getAttribute("data-start-html"))))}function Te(e){l=e;var n=x("realtimeButton"),a=x("micButton"),o=x("conversationButton"),i=x("input"),r=x("sendButton"),c=t.getElementById("realtime-audio-settings");e?(p(),i&&(i.hidden=!0),r&&(r.hidden=!0),a&&(a.hidden=!0),o&&(o.hidden=!0),n&&(n.hidden=!1),c&&(c.hidden=!1)):(A&&We(),n&&(n.hidden=!0),c&&(c.hidden=!0),function(){if(!L)return;try{L.remove()}catch(e){}L=null}(),Ae(),i&&(i.hidden=!1),r&&(r.hidden=!1),a&&(a.hidden=!1),o&&(o.hidden=!1)),Me()}var Ie={"requesting-mic":g("requestingMic","Waiting for microphone access…"),connecting:g("connecting","Connecting…"),listening:g("listening","Listening"),"playback-blocked":g("playbackBlocked","Audio is blocked by the browser — click the page to enable it.")};function Ee(e,t){if(w!==e){w=e;var n=Ie[e];n?xe(n,!1):"idle"===e&&Ae();try{E({state:e,transport:q?"webrtc":"websocket",detail:t||null})}catch(e){}}}function we(t){R=t,We(),Ee("ended",t),e.console&&console.info&&console.info("The realtime voice session ended ("+t+")."),"idle"===t?xe(g("endedIdle","Voice paused after a period of silence."),!0):"disconnected"===t?xe(g("endedDisconnected","Voice session ended — the connection dropped."),!0):"error"===t?xe(g("endedError","Voice session ended unexpectedly."),!0):"device_lost"===t&&xe(g("endedDeviceLost","Voice session ended — the microphone was disconnected."),!0)}function xe(e,n){var a=x("realtimeButton");if(a){if(!j){(j=t.createElement("div")).className="form-text mt-2 mb-0 text-center",j.setAttribute("role","status"),j.setAttribute("aria-live","polite");var o=a.parentElement;o&&o.parentElement?o.parentElement.appendChild(j):a.insertAdjacentElement("afterend",j)}if(j.replaceChildren(),j.appendChild(t.createTextNode(e)),n){var i=t.createElement("button");i.type="button",i.className="btn btn-link btn-sm p-0 ms-2 align-baseline",i.textContent=g("resume","Resume"),i.addEventListener("click",function(){Ae(),Re()}),j.appendChild(i)}}}function Ae(){if(j){try{j.remove()}catch(e){}j=null}}function Ce(){if(!L){var e=x("realtimeButton");if(e){var n=t.createElement("div");n.className="form-text mt-2 mb-0 text-center",n.setAttribute("role","status"),n.textContent=g("compatibilityMode","Using compatibility audio mode. Echo cancellation may be weaker — headphones are recommended.");var a=e.parentElement;a&&a.parentElement?a.parentElement.appendChild(n):e.insertAdjacentElement("afterend",n),L=n}}}function Re(){l&&!A&&a&&(be(ve()),X=!1,R=null,Ae(),!C&&a&&(C=!0,a.on("ReceiveRealtimeEvent",function(e,t,n){A&&("session_ready"===t?Ee("listening"):"session_ended"===t?we(n||"completed"):"speech_started"===t?ne&&ze():"playback_flush"===t?ze():"user_turn_pending"===t?v(n):"user_turn_dropped"===t&&h(n))}),a.on("ReceiveError",function(){A&&(!q||K||X?we("error"):He("server reported an error before the peer connected"))}),"function"==typeof a.onclose&&a.onclose(function(){A&&we("disconnected")}),"function"==typeof a.onreconnecting&&a.onreconnecting(function(){A&&we("disconnected")})),Ee("requesting-mic"),!M||function(){try{return"1"===e.sessionStorage.getItem(Z)}catch(e){return!1}}()?Le():function(){var n={echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0};de&&(n.deviceId={exact:de});navigator.mediaDevices.getUserMedia({audio:n}).then(function(n){y().then(function(){return T?Promise.resolve(T):a&&"function"==typeof a.invoke?a.invoke("GetRealtimeIceServers").then(function(e){return Array.isArray(e)&&e.length?e:I}).catch(function(t){return e.console&&console.warn&&console.warn("Could not resolve the realtime ICE servers; using the default STUN server.",t),I}):Promise.resolve(I)}).then(function(e){P=n,A=!0,q=!0,f(),Me(),Ee("connecting"),J=!1,Y=[],K=!1;var o=new RTCPeerConnection({iceServers:e});z=o,ye();var r=x("realtimeButton");if(r)try{r.blur()}catch(e){}ae&&Se();var c=t.createElement("audio");c.autoplay=!0,c.style.display="none",c.volume=Math.max(0,Math.min(1,null!=ue?ue:1)),t.body.appendChild(c),_=c,s(c,fe),o.ontrack=function(e){try{e.receiver&&"jitterBufferTarget"in e.receiver&&(e.receiver.jitterBufferTarget=150)}catch(e){}var t;e.streams&&e.streams[0]&&(c.srcObject=e.streams[0],function(e){u(e,function(){Ee("playback-blocked")})}(c),t=e.streams[0],te=t||null,ee&&t&&ee.attachAssistantStream(t))},$=!1,o.onicecandidate=function(e){if(e.candidate){e.candidate.candidate&&-1!==e.candidate.candidate.indexOf(" relay ")&&($=!0);try{a.send("AddRealtimeIceCandidate",e.candidate.candidate,e.candidate.sdpMid||"",e.candidate.sdpMLineIndex||0)}catch(e){}}else $||K||!Q||(clearTimeout(Q),Q=setTimeout(function(){!K&&A&&He("no relay candidate and no direct connection")},5e3))},o.onconnectionstatechange=function(){"connected"===o.connectionState?Pe():"failed"===o.connectionState?K?A&&We():He("connection failed"):"closed"===o.connectionState&&A&&K&&We()},o.oniceconnectionstatechange=function(){var e=o.iceConnectionState;"connected"===e||"completed"===e?Pe():"failed"!==e||K||He("ICE failed")},function(){if(V)return;V=!0,a.on("ReceiveRealtimeAnswer",function(e){z&&z.setRemoteDescription({type:"answer",sdp:e}).then(function(){J=!0;var e=Y;Y=[],e.forEach(function(e){try{z.addIceCandidate(e).catch(function(){})}catch(e){}})}).catch(function(e){console.error("Failed to apply the WebRTC answer.",e)})}),a.on("ReceiveRealtimeIceCandidate",function(e,t,n){if(z&&e){var a={candidate:e,sdpMid:t,sdpMLineIndex:n};if(J)try{z.addIceCandidate(a).catch(function(){})}catch(e){}else Y.push(a)}})}(),Q=setTimeout(function(){!K&&A&&He("connection timed out")},8e3),Ne(n).then(function(e){return z!==o?null:(e&&o.addTrack(e,n),o.createOffer())}).then(function(e){return e&&z===o?o.setLocalDescription(e).then(function(){return e}):null}).then(function(e){if(e){var t=me||null,n=S&&S()||i||"";D(e.sdp,n,t,null,null,ne)}}).catch(function(e){console.error("Failed to create the WebRTC offer; falling back to WebSocket.",e),He("offer failed")})}).catch(function(e){n.getTracks().forEach(function(e){e.stop()}),A=!1,q=!1,m(),Me(),console.error("The realtime WebRTC conversation could not start because the chat connection is not available.",e)})}).catch(function(e){console.error("Microphone access denied:",e),A=!1,q=!1,m(),Me()})}())}function Le(){M&&Ce(),ye();var t=x("realtimeButton");if(t)try{t.blur()}catch(e){}var n={channelCount:1,echoCancellation:{ideal:!0},noiseSuppression:!0,autoGainControl:!0,echoCancellationType:{ideal:"system"},voiceIsolation:{ideal:!0}};de&&(n.deviceId={exact:de}),navigator.mediaDevices.getUserMedia({audio:n}).then(function(t){y().then(function(){P=t,A=!0,f(),Me(),Ee("connecting");var n=e.AudioContext||e.webkitAudioContext;"suspended"===(B=new n({sampleRate:24e3})).state&&"function"==typeof B.resume&&B.resume().catch(function(t){Ee("playback-blocked"),e.console&&console.warn&&console.warn("The browser blocked realtime audio playback. Interact with the page to enable audio.",t)}),H=0,W=[],(F=B.createGain()).gain.value=null!=ue?ue:1,F.connect(B.destination),U=new e.signalR.Subject;var a=B,o=B.createScriptProcessor(4096,1,1);O=o;var r=B.createMediaStreamDestination();F.connect(r),Ne(t).then(function(e){if(A&&B===a&&e){var t=new MediaStream([e]),n=B.createMediaStreamSource(t);N=n,n.connect(o),ee&&ee.attachAssistantStream(r.stream)}}),o.onaudioprocess=function(e){var t,n=e.inputBuffer.getChannelData(0);t=ae?!oe:!ne&&B&&B.currentTime<H+.5;var a=new Int16Array(n.length);if(!t)for(var o=0;o<n.length;o++){var i=Math.max(-1,Math.min(1,n[o]));a[o]=i<0?32768*i:32767*i}for(var r=new Uint8Array(a.buffer),c="",l=0;l<r.length;l++)c+=String.fromCharCode(r[l]);try{U.next(btoa(c))}catch(e){}};var c=B.createGain();c.gain.value=0,G=c,o.connect(c),c.connect(B.destination);var l=me||null,s=S&&S()||i||"";k(U,s,l,null,null,ne),ae&&Se()}).catch(function(e){t.getTracks().forEach(function(e){e.stop()}),A=!1,m(),Me(),console.error("The realtime conversation could not start because the chat connection is not available.",e)})}).catch(function(e){console.error("Microphone access denied:",e),A=!1,m(),Me()})}function je(){if(Ge(),z){try{z.close()}catch(e){}z=null}if(_){try{_.srcObject=null,_.remove()}catch(e){}_=null}q=!1}function Pe(){K||(K=!0,Q&&(clearTimeout(Q),Q=null))}var Be=2e3;function Ue(){return{pushToTalk:!!ae,pttActive:!!oe,bargeIn:!!ne,speechHangoverMs:Be}}function Oe(){ee&&ee.setMode(Ue())}function Ne(e){Ge();var t=e&&e.getAudioTracks()[0]||null;return r(e,Ue()).then(function(e){return ee=e,te&&e.attachAssistantStream(te),e.track||t})}function Ge(){if(ee){try{ee.stop()}catch(e){}ee=null}te=null}function Fe(){s(_,fe)}function He(t){if(!X){X=!0,Q&&(clearTimeout(Q),Q=null),e.console&&console.warn&&console.warn("Realtime WebRTC transport unavailable ("+t+"); falling back to the WebSocket transport."),function(){try{e.sessionStorage.setItem(Z,"1")}catch(e){}}(),Ce();try{P&&P.getTracks().forEach(function(e){e.stop()})}catch(e){}P=null,je(),q=!1,A=!1,Le()}}function We(){if(A)if(Q&&(clearTimeout(Q),Q=null),A=!1,m(),Me(),function(){if(ie){ie=!1,oe=!1;try{t.removeEventListener("keydown",re,!0)}catch(e){}try{t.removeEventListener("keyup",ce,!0)}catch(e){}}}(),function(){if(le=null,se){try{se.remove()}catch(e){}se=null}}(),R||Ee("idle"),q){je();try{P&&P.getTracks().forEach(function(e){e.stop()})}catch(e){}P=null}else{try{U&&U.complete()}catch(e){}U=null,Ge();try{O&&(O.disconnect(),O.onaudioprocess=null)}catch(e){}try{N&&N.disconnect()}catch(e){}try{G&&G.disconnect()}catch(e){}try{F&&F.disconnect()}catch(e){}try{P&&P.getTracks().forEach(function(e){e.stop()})}catch(e){}O=null,N=null,G=null,F=null,P=null,ze();try{B&&B.close()}catch(e){}B=null}}function qe(){A?We():Re()}function ze(){W.forEach(function(e){try{e.stop()}catch(e){}}),W=[],B&&(H=B.currentTime)}function _e(e){return!!e&&-1!==c.indexOf(e.toLowerCase())}var Ve=x("realtimeButton");Ve&&(Ve.addEventListener("click",function(e){e&&0===e.detail&&A||qe()}),function(){var n=x("realtimeButton");if(n&&!pe){pe=!0;var o=ve();be(o);var i=t.createElement("span");i.id="realtime-audio-settings",i.style.position="relative",i.style.display="inline-flex";var r=t.createElement("button");r.type="button",r.className="btn btn-outline-secondary",r.title=g("settingsTitle","Voice settings"),r.setAttribute("aria-label",g("settingsTitle","Voice settings")),r.innerHTML='<i class="bi bi-gear"></i>';var c='<option value=""'+(""===o.language?" selected":"")+">"+g("languageAuto","Automatic")+"</option>"+[["en","English"],["es","Spanish"],["fr","French"],["de","German"],["it","Italian"],["pt","Portuguese"],["nl","Dutch"],["zh","Chinese"],["ja","Japanese"],["ko","Korean"],["ar","Arabic"],["hi","Hindi"],["ru","Russian"]].map(function(e){return'<option value="'+e[0]+'"'+(o.language===e[0]?" selected":"")+">"+e[1]+"</option>"}).join(""),l=t.createElement("div");l.className="card shadow-sm",l.style.cssText="position:absolute;bottom:calc(100% + 6px);right:0;z-index:1080;width:290px;max-height:70vh;overflow:auto;display:none;",l.innerHTML='<div class="card-body p-3"><div class="fw-semibold mb-2" style="font-size:0.85rem;">'+g("settingsTitle","Voice settings")+'</div><label class="form-label mb-1 d-block" style="font-size:0.8rem;">'+g("microphone","Microphone")+'</label><select class="form-select form-select-sm js-mic mb-2"><option value="">'+g("defaultMicrophone","Default microphone")+'</option></select><label class="form-label mb-1 d-block" style="font-size:0.8rem;">'+g("speaker","Speaker")+'</label><select class="form-select form-select-sm js-out mb-1"><option value="">'+g("automatic","Automatic")+'</option></select><button type="button" class="btn btn-outline-secondary btn-sm mb-2 js-pick-out" style="display:none;">'+g("chooseSpeaker","Choose speaker…")+'</button><div class="form-text mb-2 js-out-help">'+g("speakerHelp","Automatic uses the device your system uses for calls. If you cannot hear the assistant, pick the speakers you are actually listening to.")+'</div><label class="form-label mb-1 d-block" style="font-size:0.8rem;">'+g("assistantVolume","Assistant volume")+': <strong class="js-vol-val">'+Math.round(100*o.volume)+'</strong>%</label><input type="range" class="form-range js-vol mb-2" min="0" max="100" step="5" value="'+Math.round(100*o.volume)+'"><label class="form-label mb-1 d-block" style="font-size:0.8rem;">'+g("language","Language")+'</label><select class="form-select form-select-sm js-lang mb-2">'+c+'</select><div class="form-check form-switch mb-1"><input class="form-check-input js-barge" type="checkbox" id="realtime-setting-barge"'+(o.bargeIn?" checked":"")+'><label class="form-check-label" for="realtime-setting-barge">'+g("allowInterruptions","Allow interruptions")+'</label></div><div class="form-text mb-2">'+g("allowInterruptionsHelp","Talk over the assistant to interrupt it. Turn this off if the assistant keeps hearing itself through your speakers.")+'</div><div class="form-check form-switch mb-1"><input class="form-check-input js-ptt" type="checkbox" id="realtime-setting-ptt"'+(o.pushToTalk?" checked":"")+'><label class="form-check-label" for="realtime-setting-ptt">'+g("pushToTalk","Push-to-talk")+'</label></div><div class="form-text">'+g("pushToTalkHelp","Hold <kbd>Space</kbd> (or the button) to talk. For very noisy places.")+"</div></div>",i.appendChild(r),i.appendChild(l),n.insertAdjacentElement("afterend",i);var s=l.querySelector(".js-barge"),u=l.querySelector(".js-ptt"),d=l.querySelector(".js-vol"),f=l.querySelector(".js-vol-val"),m=l.querySelector(".js-mic"),p=l.querySelector(".js-out"),v=l.querySelector(".js-pick-out"),h=l.querySelector(".js-lang");y(),navigator.mediaDevices&&"function"==typeof navigator.mediaDevices.addEventListener&&navigator.mediaDevices.addEventListener("devicechange",function(){y(),A&&de&&navigator.mediaDevices.enumerateDevices().then(function(e){e.some(function(e){return"audioinput"===e.kind&&e.deviceId===de})||we("device_lost")}).catch(function(){})}),r.addEventListener("click",function(n){n.stopPropagation();var a="none"===l.style.display;a&&(l.style.display="block",function(){l.style.right="0px",l.style.left="auto";var n=l.getBoundingClientRect();n.left<8&&(l.style.right=n.left-8+"px");for(var a=r.getBoundingClientRect(),o=8,i=l.parentElement?l.parentElement.parentElement:null;i&&i!==t.body&&i!==t.documentElement;){var c=e.getComputedStyle(i);if("auto"===c.overflowY||"scroll"===c.overflowY||"hidden"===c.overflowY||"fixed"===c.position){o=Math.max(o,i.getBoundingClientRect().top);break}i=i.parentElement}l.style.maxHeight=Math.max(160,a.top-o-10)+"px"}(),y()),l.style.display=a?"block":"none"}),l.addEventListener("click",function(e){e.stopPropagation()}),t.addEventListener("click",function(){l.style.display="none"}),s.addEventListener("change",b),u.addEventListener("change",b),d.addEventListener("input",function(){f.textContent=d.value,b()}),m.addEventListener("change",b),h.addEventListener("change",b),p.addEventListener("change",function(){b(),Fe()}),navigator.mediaDevices&&"function"==typeof navigator.mediaDevices.selectAudioOutput&&(v.style.display="",v.addEventListener("click",function(){navigator.mediaDevices.selectAudioOutput().then(function(e){if(e&&e.deviceId){var n=t.createElement("option");n.value=e.deviceId,n.textContent=e.label||g("selectedSpeaker","Selected speaker"),p.appendChild(n),p.value=e.deviceId,b(),Fe()}}).catch(function(){})}))}function b(){var e={bargeIn:s.checked,pushToTalk:u.checked,volume:(parseInt(d.value,10)||0)/100,micDeviceId:m.value||"",outputDeviceId:p.value||"",language:h.value||"",version:3};be(e),he(e),function(){if(A&&a&&"function"==typeof a.send)try{a.send("UpdateRealtimeSettings",ne,null,null)}catch(e){}}()}function y(){navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.enumerateDevices().then(function(e){var t=['<option value="">'+g("defaultMicrophone","Default microphone")+"</option>"];e.filter(function(e){return"audioinput"===e.kind}).forEach(function(e,n){var a=e.label||g("microphone","Microphone")+" "+(n+1);t.push('<option value="'+e.deviceId+'"'+(e.deviceId===de?" selected":"")+">"+a.replace(/</g,"")+"</option>")}),m.innerHTML=t.join("");var n=e.filter(function(e){return"audiooutput"===e.kind&&e.deviceId&&"communications"!==e.deviceId&&"default"!==e.deviceId});if(n.length){var a=['<option value="">'+g("automatic","Automatic")+"</option>"];n.forEach(function(e,t){var n=e.label||g("speaker","Speaker")+" "+(t+1);a.push('<option value="'+e.deviceId+'"'+(e.deviceId===fe?" selected":"")+">"+n.replace(/</g,"")+"</option>")}),p.innerHTML=a.join("")}}).catch(function(){})}}());var Je=x("deploymentSelect");Je&&Je.addEventListener("change",function(){Te(_e(Je.value))}),Te(l||Je&&_e(Je.value));var Ye={toggle:qe,start:Re,stop:We,applyMode:Te,isRealtimeDeployment:_e,receivePcm:function(e){if(B&&e&&!(e.length<2)){for(var t=B,n=Math.floor(e.length/2),a=new Int16Array(e.buffer,e.byteOffset,n),o=new Float32Array(n),i=0;i<n;i++)o[i]=a[i]/32768;var r=t.createBuffer(1,n,t.sampleRate);r.copyToChannel(o,0);var c=t.createBufferSource();c.buffer=r,c.connect(F||t.destination);var l=t.currentTime;H<l&&(H=l),c.start(H),H+=r.duration,W.push(c),c.onended=function(){W=W.filter(function(e){return e!==c})}}},isActive:function(){return A},getState:function(){return w},getGateLevel:function(){return ee?ee.getLevel():null},getTransportStats:function(){return z&&"function"==typeof z.getStats?z.getStats().then(function(e){var t={transport:"webrtc",inbound:null,codec:null,sinkId:_&&"string"==typeof _.sinkId?_.sinkId:null,jitterBufferTargetMs:function(){try{var e=z.getReceivers().filter(function(e){return e.track&&"audio"===e.track.kind})[0];return e&&"jitterBufferTarget"in e?e.jitterBufferTarget:null}catch(e){return null}}()};return e.forEach(function(n){if("inbound-rtp"===n.type&&"audio"===n.kind&&(t.inbound={packetsReceived:n.packetsReceived,packetsLost:n.packetsLost,packetsDiscarded:n.packetsDiscarded,jitterMs:"number"==typeof n.jitter?Math.round(1e3*n.jitter):null,jitterBufferDelayMs:"number"==typeof n.jitterBufferDelay&&n.jitterBufferEmittedCount?Math.round(n.jitterBufferDelay/n.jitterBufferEmittedCount*1e3):null,totalSamplesReceived:n.totalSamplesReceived,concealedSamples:n.concealedSamples,concealmentEvents:n.concealmentEvents,silentConcealedSamples:n.silentConcealedSamples,insertedSamplesForDeceleration:n.insertedSamplesForDeceleration,removedSamplesForAcceleration:n.removedSamplesForAcceleration,audioLevel:n.audioLevel},n.codecId)){var a=e.get(n.codecId);a&&(t.codec={mimeType:a.mimeType,clockRate:a.clockRate,channels:a.channels,sdpFmtpLine:a.sdpFmtpLine})}}),t}).catch(function(){return null}):Promise.resolve(null)}};return e.CoreAIRealtime.activeController=Ye,Ye},createMicGate:r,decideGate:n,createGateState:a,rmsDb:o,routeOutputToPreferredDevice:s,ensurePlayback:u}}(window,document);
|
|
2
|
+
//# sourceMappingURL=realtime-audio.min.js.map
|