implement basic support for auracast over the network

This commit is contained in:
pstruebi
2025-07-22 16:38:43 +02:00
parent c2901849ff
commit fc8341137a
3 changed files with 13 additions and 15 deletions

View File

@@ -632,7 +632,7 @@ async def broadcast(global_conf: auracast_config.AuracastGlobalConfig, big_conf:
if __name__ == "__main__": if __name__ == "__main__":
import os import os
logging.basicConfig( #export LOG_LEVEL=INFO logging.basicConfig( #export LOG_LEVEL=DEBUG
level=os.environ.get('LOG_LEVEL', logging.INFO), level=os.environ.get('LOG_LEVEL', logging.INFO),
format='%(module)s.py:%(lineno)d %(levelname)s: %(message)s' format='%(module)s.py:%(lineno)d %(levelname)s: %(message)s'
) )

View File

@@ -37,7 +37,7 @@ except Exception:
st.title("🎙️ Auracast Audio Mode Control") st.title("🎙️ Auracast Audio Mode Control")
# Audio mode selection with persisted default # Audio mode selection with persisted default
options = ["Webapp", "USB", "Demo"] options = ["Webapp", "USB/Network", "Demo"]
saved_audio_mode = saved_settings.get("audio_mode", "Webapp") saved_audio_mode = saved_settings.get("audio_mode", "Webapp")
if saved_audio_mode not in options: if saved_audio_mode not in options:
saved_audio_mode = "Webapp" saved_audio_mode = "Webapp"
@@ -46,7 +46,7 @@ audio_mode = st.selectbox(
"Audio Mode", "Audio Mode",
options, options,
index=options.index(saved_audio_mode), 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": if audio_mode == "Demo":
@@ -201,15 +201,9 @@ else:
mic_gain = 1.0 mic_gain = 1.0
# Input device selection for USB mode # Input device selection for USB mode
if audio_mode == "USB": if audio_mode == "USB/Network":
try: resp = requests.get(f"{BACKEND_URL}/audio_inputs")
resp = requests.get(f"{BACKEND_URL}/audio_inputs") input_options = [f"{d['id']}:{d['name']}" for d in resp.json().get('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 not input_options: if not input_options:
st.warning("No hardware audio input devices found. Plug in a USB input device and click Refresh.") 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, program_info=program_info,
language=language, language=language,
audio_source=( 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" "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 iso_que_len=1, # TODO: this should be way less to decrease delay
sampling_frequency=q['rate'], sampling_frequency=q['rate'],
octets_per_frame=q['octets'], octets_per_frame=q['octets'],

View File

@@ -219,11 +219,14 @@ async def scan_audio_devices():
log.info("Re-initializing sounddevice to scan for new devices") log.info("Re-initializing sounddevice to scan for new devices")
sd._terminate() sd._terminate()
sd._initialize() sd._initialize()
# TODO: select this dynamically from pw-cli ls Node determine id
#os.environ["PIPEWIRE_NODE"] = "101"
devs = sd.query_devices() devs = sd.query_devices()
inputs = [ inputs = [
{"id": idx, "name": d["name"]} {"id": idx, "name": d["name"]}
for idx, d in enumerate(devs) 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) log.info('Found %d audio input devices: %s', len(inputs), inputs)
AUDIO_INPUT_DEVICES_CACHE = inputs AUDIO_INPUT_DEVICES_CACHE = inputs
@@ -384,6 +387,7 @@ async def shutdown():
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))
if __name__ == '__main__': if __name__ == '__main__':
import os import os
os.chdir(os.path.dirname(__file__)) os.chdir(os.path.dirname(__file__))