pythonflaskaudiosocket.io

Periodic beeping in live audio stream using Flask-SocketIO and sounddevice — concurrency issue?


Periodic beeping in live audio stream using Flask-SocketIO and sounddevice — concurrency or deployment issue?

Question

I'm building a live audio streaming feature with Flask-SocketIO and sounddevice. Audio is captured from a microphone and emitted in chunks to clients via Socket.IO rooms.

Problem: When I listen to the streamed audio on the client, I hear a periodic beeping noise roughly twice per second, which interrupts the audio stream. It sounds like a timing or threading issue.


Setup

import eventlet
eventlet.monkey_patch()

I use sounddevice to capture audio.

gunicorn -k eventlet -w 1 -t 4 -b 0.0.0.0:5001 app:app

Deployment command.

import sounddevice as sd
import threading
from extensions import sio
from flask_socketio import join_room, leave_room

class AudioStreamer:
    def __init__(self, sample_rate=44100, channels=2, chunk_size=1024):
        self.sample_rate = sample_rate
        self.channels = channels
        self.chunk_size = chunk_size
        self.thread = None
        self.room = 'audio_listeners'
        self.is_running = False

    def start(self):
        if self.is_running:
            return
        self.is_running = True
        self.thread = threading.Thread(target=self._stream_audio, daemon=True).start()
        print('[AudioStreamer] Audio thread started.')

    def stop(self):
        if not self.is_running:
            return
        self.is_running = False
        self.thread.join(timeout=1)
        print('[AudioStreamer] Audio thread stopped.')

    def add_client(self, sid):
        join_room(self.room, sid=sid)
        if not self.is_running:
            self.start()

    def remove_client(self, sid):
        leave_room(self.room, sid=sid)
        # TODO: stop streaming if no clients remain

    def _stream_audio(self):
        try:
            with sd.InputStream(samplerate=self.sample_rate, channels=self.channels, dtype='int16') as stream:
                while self.is_running:
                    data, _ = stream.read(self.chunk_size)
                    sio.emit('audio_chunk', data.tobytes(), room=self.room)
                    sio.sleep(0)
        except Exception as e:
            print(f'[AudioStreamer] Error: {e}')

Here is an example that works that I've tried:

import eventlet
eventlet.monkey_patch()

from flask import Flask, render_template
from flask_socketio import SocketIO
import sounddevice as sd
import threading

app = Flask(__name__)
socketio = SocketIO(app)

sample_rate = 44100
channels = 2
chunk_size = 1024

def audio_stream_thread():
    with sd.InputStream(samplerate=sample_rate, channels=channels, dtype='int16') as stream:
        while True:
            data, _ = stream.read(chunk_size)
            # send raw PCM bytes to all connected clients
            socketio.emit('audio_chunk', data.tobytes())
            socketio.sleep(0)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    threading.Thread(target=audio_stream_thread, daemon=True).start()
    socketio.run(app, host='0.0.0.0', port=5001, allow_unsafe_werkzeug=True)


Solution

  • I found the problem. It is a hardware or a driver level issue. Because even in an ffmpeg recorded video I can hear the beeping. (My mic is also a webcam.) But if the camera is off the mic works fine. So yeah.