diff --git a/python/voice-live-avatar/README.md b/python/voice-live-avatar/README.md index d5fdd94..a526f99 100644 --- a/python/voice-live-avatar/README.md +++ b/python/voice-live-avatar/README.md @@ -47,7 +47,7 @@ The avatar feature is currently available in the following service regions: Sout - `AZURE_VOICELIVE_ENDPOINT` - Your Azure AI Services endpoint - `AZURE_VOICELIVE_API_KEY` - Your API key - - `VOICELIVE_MODEL` - Model to use (default: `gpt-4o-realtime`) + - `VOICELIVE_MODEL` - Model to use (default: `gpt-realtime`) - `VOICELIVE_VOICE` - Voice name (default: `en-US-AvaMultilingualNeural`) 3. **Run the server:** diff --git a/python/voice-live-avatar/app.py b/python/voice-live-avatar/app.py index 49cadb6..49a4083 100644 --- a/python/voice-live-avatar/app.py +++ b/python/voice-live-avatar/app.py @@ -113,7 +113,7 @@ async def health_check(): async def get_config(): """Return default configuration to the frontend.""" return { - "model": os.getenv("VOICELIVE_MODEL", "gpt-4o-realtime"), + "model": os.getenv("VOICELIVE_MODEL", "gpt-realtime"), "voice": os.getenv("VOICELIVE_VOICE", "en-US-AvaMultilingualNeural"), "endpoint": os.getenv("AZURE_VOICELIVE_ENDPOINT", ""), "hasApiKey": bool(os.getenv("AZURE_VOICELIVE_API_KEY")), diff --git a/python/voice-live-avatar/static/app.js b/python/voice-live-avatar/static/app.js index 4cad0ff..61eac0e 100644 --- a/python/voice-live-avatar/static/app.js +++ b/python/voice-live-avatar/static/app.js @@ -55,7 +55,11 @@ async function fetchServerConfig() { const resp = await fetch('/api/config'); const config = await resp.json(); if (config.endpoint) document.getElementById('endpoint').value = config.endpoint; - if (config.model) document.getElementById('model').value = config.model; + if (config.model) { + const modelEl = document.getElementById('model'); + modelEl.value = config.model; + modelEl.dispatchEvent(new Event('change')); + } if (config.voice) document.getElementById('voiceName').value = config.voice; } catch (e) { console.log('No server config available, using defaults'); @@ -67,7 +71,17 @@ function setupUIBindings() { // Mode change document.getElementById('mode').addEventListener('change', updateConditionalFields); // Model change - document.getElementById('model').addEventListener('change', updateConditionalFields); + document.getElementById('model').addEventListener('change', (e) => { + const voiceTypeEl = document.getElementById('voiceType'); + if (e.target.value === 'azure-realtime') { + voiceTypeEl.value = 'azure-realtime-native'; + const nativeEl = document.getElementById('nativeVoiceName'); + if (nativeEl) nativeEl.value = 'ava'; + } else if (voiceTypeEl.value === 'azure-realtime-native') { + voiceTypeEl.value = 'standard'; + } + updateConditionalFields(); + }); // Voice type change document.getElementById('voiceType').addEventListener('change', updateConditionalFields); // Voice name change @@ -198,7 +212,11 @@ function updateConditionalFields() { const srModel = document.getElementById('srModel').value; // Cascaded models - const cascadedModels = ['gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano', 'gpt-4o', 'gpt-4o-mini', 'phi4-mm', 'phi4-mini']; + const cascadedModels = [ + 'gpt-5.4', 'gpt-5.3-chat', 'gpt-5.2', 'gpt-5.2-chat', 'gpt-5.1', 'gpt-5.1-chat', + 'gpt-5', 'gpt-5-mini', 'gpt-5-nano', 'gpt-5-chat', + 'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano', 'gpt-4o', 'gpt-4o-mini', + ]; const isCascaded = cascadedModels.includes(model); const isRealtime = model && model.includes('realtime'); @@ -229,11 +247,17 @@ function updateConditionalFields() { show('standardVoiceField', voiceType === 'standard'); show('customVoiceFields', voiceType === 'custom'); show('personalVoiceFields', voiceType === 'personal'); + show('nativeVoiceField', voiceType === 'azure-realtime-native'); // Voice temperature (DragonHD or personal voice) const isDragonHD = voiceName && voiceName.includes('DragonHD'); const isPersonal = voiceType === 'personal'; - show('voiceTempField', isDragonHD || isPersonal); + show('voiceTempField', voiceType !== 'azure-realtime-native' && (isDragonHD || isPersonal)); + + show('voiceSpeedField', voiceType !== 'azure-realtime-native'); + + const nativeOpt = document.querySelector('#voiceType option[value="azure-realtime-native"]'); + if (nativeOpt) nativeOpt.hidden = (model !== 'azure-realtime'); // Avatar settings show('avatarSettings', avatarEnabled); @@ -317,11 +341,15 @@ function gatherConfig() { const voiceSpeed = parseFloat(document.getElementById('voiceSpeed').value) / 100; + const voiceName = voiceType === 'azure-realtime-native' + ? document.getElementById('nativeVoiceName').value + : document.getElementById('voiceName').value; + const config = { mode: mode, model: model, voiceType: voiceType, - voiceName: document.getElementById('voiceName').value, + voiceName: voiceName, voiceSpeed: voiceSpeed, voiceTemperature: parseFloat(document.getElementById('voiceTemperature').value), voiceDeploymentId: document.getElementById('voiceDeploymentId').value, diff --git a/python/voice-live-avatar/static/index.html b/python/voice-live-avatar/static/index.html index 65373b9..b6630a9 100644 --- a/python/voice-live-avatar/static/index.html +++ b/python/voice-live-avatar/static/index.html @@ -73,15 +73,25 @@
@@ -183,6 +193,7 @@ + @@ -251,6 +262,25 @@ + + +