From fc8341137a70896691d1af270485a8438e56a8a2 Mon Sep 17 00:00:00 2001 From: pstruebi Date: Tue, 22 Jul 2025 16:38:43 +0200 Subject: [PATCH] implement basic support for auracast over the network --- src/auracast/multicast.py | 2 +- src/auracast/server/multicast_frontend.py | 20 +++++++------------- src/auracast/server/multicast_server.py | 6 +++++- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/auracast/multicast.py b/src/auracast/multicast.py index 37a7f07..5da94a6 100644 --- a/src/auracast/multicast.py +++ b/src/auracast/multicast.py @@ -632,7 +632,7 @@ async def broadcast(global_conf: auracast_config.AuracastGlobalConfig, big_conf: if __name__ == "__main__": import os - logging.basicConfig( #export LOG_LEVEL=INFO + logging.basicConfig( #export LOG_LEVEL=DEBUG level=os.environ.get('LOG_LEVEL', logging.INFO), format='%(module)s.py:%(lineno)d %(levelname)s: %(message)s' ) diff --git a/src/auracast/server/multicast_frontend.py b/src/auracast/server/multicast_frontend.py index 332670b..8adeb83 100644 --- a/src/auracast/server/multicast_frontend.py +++ b/src/auracast/server/multicast_frontend.py @@ -37,7 +37,7 @@ except Exception: st.title("🎙️ Auracast Audio Mode Control") # Audio mode selection with persisted default -options = ["Webapp", "USB", "Demo"] +options = ["Webapp", "USB/Network", "Demo"] saved_audio_mode = saved_settings.get("audio_mode", "Webapp") if saved_audio_mode not in options: saved_audio_mode = "Webapp" @@ -46,7 +46,7 @@ audio_mode = st.selectbox( "Audio Mode", options, index=options.index(saved_audio_mode), - help="Select the audio input source. Choose 'Webapp' for browser microphone, 'USB' for a connected hardware device, or 'Demo' for a simulated stream." + help="Select the audio input source. Choose 'Webapp' for browser microphone, 'USB/Network' for a connected hardware device, or 'Demo' for a simulated stream." ) if audio_mode == "Demo": @@ -201,15 +201,9 @@ else: mic_gain = 1.0 # Input device selection for USB mode - if audio_mode == "USB": - try: - resp = requests.get(f"{BACKEND_URL}/audio_inputs") - if resp.status_code == 200: - input_options = [f"{d['id']}:{d['name']}" for d in resp.json().get('inputs', [])] - else: - input_options = [] - except Exception: - input_options = [] + if audio_mode == "USB/Network": + resp = requests.get(f"{BACKEND_URL}/audio_inputs") + input_options = [f"{d['id']}:{d['name']}" for d in resp.json().get('inputs', [])] if not input_options: st.warning("No hardware audio input devices found. Plug in a USB input device and click Refresh.") @@ -295,11 +289,11 @@ else: program_info=program_info, language=language, audio_source=( - f"device:{input_device}" if audio_mode == "USB" else ( + f"device:{input_device}" if audio_mode == "USB/Network" else ( "webrtc" if audio_mode == "Webapp" else "network" ) ), - input_format=(f"int16le,{q['rate']},1" if audio_mode == "USB" else "auto"), + input_format=(f"int16le,{q['rate']},1" if audio_mode == "USB/Network" else "auto"), iso_que_len=1, # TODO: this should be way less to decrease delay sampling_frequency=q['rate'], octets_per_frame=q['octets'], diff --git a/src/auracast/server/multicast_server.py b/src/auracast/server/multicast_server.py index ca1979d..c1e644e 100644 --- a/src/auracast/server/multicast_server.py +++ b/src/auracast/server/multicast_server.py @@ -219,11 +219,14 @@ async def scan_audio_devices(): log.info("Re-initializing sounddevice to scan for new devices") sd._terminate() sd._initialize() + + # TODO: select this dynamically from pw-cli ls Node determine id + #os.environ["PIPEWIRE_NODE"] = "101" devs = sd.query_devices() inputs = [ {"id": idx, "name": d["name"]} for idx, d in enumerate(devs) - if d.get("max_input_channels", 0) > 0 and ("(hw:" in d["name"].lower() or "usb" in d["name"].lower()) + # if d.get("max_input_channels", 0) > 0 and ("(hw:" in d["name"].lower() or "usb" in d["name"].lower()) ] log.info('Found %d audio input devices: %s', len(inputs), inputs) AUDIO_INPUT_DEVICES_CACHE = inputs @@ -384,6 +387,7 @@ async def shutdown(): except Exception as e: raise HTTPException(status_code=500, detail=str(e)) + if __name__ == '__main__': import os os.chdir(os.path.dirname(__file__))