I’m trying to send audio in one way from client mic to server speaker, I tried using tcp socket and use these codes.
This for client side:
import socket
import sounddevice as sd
import numpy as np
import threading
import time
Sender settings
HOST = “server ip” # Server IP address
PORT = 6000 # Server port
Adjust buffer sizes
BUFFER_SIZE = 8192*4 # Match the server’s BLOCK_SIZE
Create a socket for communication
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, PORT))
print(f”Connected to server at {HOST}:{PORT}”)
ack_received = False # Flag to track acknowledgment
mic_enabled = False # Flag to track microphone status
def audio_callback(indata, frames, time, status):
global ack_received
if status:
print(f"Error in audio stream: {status}")
if mic_enabled and ack_received:
#print(f"Sending data: {len(indata.tobytes())} bytes") # Debug
client_socket.sendall(indata.tobytes())
def receive_ack():
global ack_received
while True:
try:
data = client_socket.recv(1024) # Receive acknowledgment from server
if data == b'ACK':
ack_received = True # Set acknowledgment flag
except Exception as e:
print(f"Error receiving acknowledgment: {e}")
break
def handle_input():
global mic_enabled
while True:
command = input("Press '1' to enable mic, '0' to disable mic: ")
if command == '1':
mic_enabled = True
client_socket.sendall(b'1') # Notify the server to expect audio data
elif command == '0':
mic_enabled = False
Start a thread to receive acknowledgments from the server
ack_thread = threading.Thread(target=receive_ack)
ack_thread.daemon = True # Daemonize the thread so it terminates with the main thread
ack_thread.start()
Start a thread to handle user input
input_thread = threading.Thread(target=handle_input)
input_thread.daemon = True # Daemonize the thread so it terminates with the main thread
input_thread.start()
with sd.InputStream(callback=audio_callback, blocksize=BUFFER_SIZE, latency=’low’, channels=1):
print("Sending audio to server. Press Ctrl+C to stop.")
try:
while True:
if ack_received and mic_enabled:
time.sleep(0.01) # Add a small delay to reduce CPU usage
except KeyboardInterrupt:
print("Exiting...")
client_socket.close() # Close the socket on client exit
import time
import threading
import sounddevice as sd
import numpy as np
def audio_callback(outdata, frames, time, status, conn):
global audio_running
with audio_running_lock:
if not audio_running:
return
if status:
print(f"Error in audio stream: {status}")
if status.output_underflow:
print("Output underflow occurred. Consider adjusting buffer sizes or optimizing performance.")
try:
data = conn.recv(outdata.nbytes)
#print(f"Received data: {len(data)} bytes") # Debug
if len(data) == 0:
print("No data received.")
outdata.fill(0) # Fill output buffer with zeros (silence)
return
data_array = np.frombuffer(data, dtype=outdata.dtype)
data_array_copy = data_array.copy() # Create a copy to ensure ownership of data
data_array_copy.resize((frames, outdata.shape[1]))
outdata[:, :] = data_array_copy # Copy processed data to output buffer
except Exception as e:
print(f"Error processing audio data: {e}")
def handle_client_commands(conn):
global audio_running
while True:
try:
command = conn.recv(1024)
if command == b'1':
conn.sendall(b'ACK')
with audio_running_lock:
audio_running = True # Enable the speaker
elif command == b'0':
with audio_running_lock:
audio_running = False # Disable the speaker
except Exception as e:
print(f"Error receiving command: {e}")
break
def start_socket(HOST, PORT):
global audio_running, audio_running_lock
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(1)
print(f"Listening on {HOST}:{PORT}...")
# Accept a client connection
conn, address = server_socket.accept()
print(f"Connected to {address}")
audio_running = True
audio_running_lock = threading.Lock()
BLOCK_SIZE = 8192*4 # Increased buffer size
# Start a thread for handling client commands
command_thread = threading.Thread(target=handle_client_commands, args=(conn,))
command_thread.start()
with sd.OutputStream(callback=lambda outdata, frames, time, status: audio_callback(outdata, frames, time, status, conn),
blocksize=BLOCK_SIZE, channels=1):
print("Receiving audio from client. Press Ctrl+C to stop.")
while True:
try:
time.sleep(0.1)
except KeyboardInterrupt:
print("Stopping server...")
break
# Clean up
command_thread.join()
server_socket.close()
if name == “main“:
start_socket("server ip", 6000)
I have some interruption and echo which means audio not clear when applied server code on linux and client code on windows.
1.Is there any suggestion to solve it ?
2. Is there any another efficient and more professional way to do same “stream audio over local network”, with less latency, low load on network ?
Handle my case, in my codes and if there’s any suggestion to acheive same task with professional way