Add gain slider in webapp mode

This commit is contained in:
2025-06-18 13:25:35 +02:00
parent c7926724e2
commit 22d27ce2f5

View File

@@ -5,6 +5,10 @@ import requests
from auracast import auracast_config
import logging as log
# Track whether WebRTC stream is active across Streamlit reruns
if 'stream_started' not in st.session_state:
st.session_state['stream_started'] = False
# Global: desired packetization time in ms for Opus (should match backend)
PTIME = 40
BACKEND_URL = "http://localhost:5000"
@@ -47,6 +51,11 @@ if audio_mode in ["Webapp", "USB"]:
default_input = saved_settings.get('input_device') or 'default'
stream_name = st.text_input("Channel Name", value=default_name)
language = st.text_input("Language (ISO 639-3)", value=default_lang)
# Gain slider for Webapp mode
if audio_mode == "Webapp":
mic_gain = st.slider("Microphone Gain", 0.0, 4.0, 1.0, 0.1, help="Adjust microphone volume sent to Auracast")
else:
mic_gain = 1.0
# Input device selection for USB mode
if audio_mode == "USB":
@@ -83,7 +92,17 @@ if audio_mode in ["Webapp", "USB"]:
start_stream = st.button("Start Auracast")
stop_stream = st.button("Stop Auracast")
# If gain slider moved while streaming, send update to JS without restarting
if audio_mode == "Webapp" and st.session_state.get('stream_started'):
update_js = f"""
<script>
if (window.gainNode) {{ window.gainNode.gain.value = {mic_gain}; }}
</script>
"""
st.components.v1.html(update_js, height=0)
if stop_stream:
st.session_state['stream_started'] = False
try:
r = requests.post(f"{BACKEND_URL}/stop_audio").json()
if r['was_running']:
@@ -133,14 +152,28 @@ if audio_mode in ["Webapp", "USB"]:
except Exception as e:
st.error(f"Error: {e}")
if audio_mode == "Webapp" and start_stream:
# Render / maintain WebRTC component
if audio_mode == "Webapp" and (start_stream or st.session_state.get('stream_started')):
st.markdown("Starting microphone; allow access if prompted and speak.")
component = f"""
<script>
(async () => {{
if (window.webrtc_started) return; // Prevent re-init on rerun
window.webrtc_started = true;
const GAIN_VALUE = {mic_gain};
const pc = new RTCPeerConnection(); // No STUN needed for localhost
const stream = await navigator.mediaDevices.getUserMedia({{audio:true}});
stream.getTracks().forEach(t => pc.addTrack(t, stream));
const micStream = await navigator.mediaDevices.getUserMedia({{audio:true}});
// Create Web Audio gain processing
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const source = audioCtx.createMediaStreamSource(micStream);
const gainNode = audioCtx.createGain();
gainNode.gain.value = GAIN_VALUE;
// Expose for later adjustments
window.gainNode = gainNode;
const dest = audioCtx.createMediaStreamDestination();
source.connect(gainNode).connect(dest);
// Add processed tracks to WebRTC
dest.stream.getTracks().forEach(t => pc.addTrack(t, dest.stream));
// --- WebRTC offer/answer exchange ---
const offer = await pc.createOffer();
// Patch SDP offer to include a=ptime using global PTIME
@@ -169,6 +202,7 @@ if audio_mode in ["Webapp", "USB"]:
</script>
"""
st.components.v1.html(component, height=0)
st.session_state['stream_started'] = True
else:
st.header("Advertised Streams (Cloud Announcements)")
st.info("This feature requires backend support to list advertised streams.")