To handle multiple audio streams, we’ll use a ThreadPoolExecutor to run each call in its own thread, with a shared SDK instance and a separate AudioProcessor per stream.
import sanas_remote_sdkimport threadingimport timefrom concurrent.futures import ThreadPoolExecutordef sleep_until(target_time): """Sleep until target time with precision""" sleep_time = target_time - time.time() if sleep_time > 0.001: time.sleep(sleep_time - 0.001) while time.time() < target_time: passdef process_call(call_id, sdk): """Process audio in a separate thread""" call_ready = threading.Event() def state_callback(state, reason): if state == sanas_remote_sdk.ProcessorState.READY: print(f"Call {call_id} state: READY") call_ready.set() elif state == sanas_remote_sdk.ProcessorState.FAILED: print(f"Call {call_id} state: FAILED") elif state == sanas_remote_sdk.ProcessorState.DISCONNECTED: print(f"Call {call_id} state: DISCONNECTED") elif state == sanas_remote_sdk.ProcessorState.INITIALIZING: print(f"Call {call_id} state: INITIALIZING") # Create processor for this stream audio_params = sanas_remote_sdk.AudioParams() audio_params.modelName = "desired_sanas_model" audio_params.sampleRate = 16000 processor, result = sdk.CreateAudioProcessor(audio_params, state_callback) if result == sanas_remote_sdk.CreateProcessorResult.SUCCESS: if call_ready.wait(timeout=10): print(f"Call {call_id} processing audio...") first_chunk_time = time.time() # Process 1500 chunks (30 seconds of audio at 8kHz) for i in range(1500): ideal_time = first_chunk_time + (i * 0.02) sleep_until(ideal_time) input_samples = [0.1] * 160 # Simulated audio data (e.g., from network stream) output_samples = processor.ProcessSamples(input_samples) sdk.DestroyAudioProcessor(processor)# Initialize SDK once - shared across all streamssdk = sanas_remote_sdk.CreateRemoteSDK()init_params = sanas_remote_sdk.InitParams()init_params.remoteEndpoint = "your_server_ip"init_params.accountId = "your_account_id"init_params.accountSecret = "your_account_secret"init_params.secureMedia = Falsesdk.Initialize(init_params)# Process 4 concurrent audio streamswith ThreadPoolExecutor(max_workers=4) as executor: futures = [executor.submit(process_call, i + 1, sdk) for i in range(4)] for future in futures: future.result()sdk.Shutdown()
This example uses a ThreadPoolExecutor for demonstration purposes. In production, use any concurrency model (threads, asyncio, etc.) - each stream just needs its own AudioProcessor and must maintain precise 20ms timing between chunks.