forked from computertech/techdj
Add /stream_debug and improve MP3 transcoder startup
This commit is contained in:
31
server.py
31
server.py
@@ -29,6 +29,9 @@ _ffmpeg_in_q = queue.Queue(maxsize=200)
|
||||
_mp3_clients = set() # set[queue.Queue]
|
||||
_mp3_lock = threading.Lock()
|
||||
_transcode_threads_started = False
|
||||
_transcoder_bytes_out = 0
|
||||
_transcoder_last_error = None
|
||||
_last_audio_chunk_ts = 0.0
|
||||
|
||||
|
||||
def _start_transcoder_if_needed():
|
||||
@@ -62,7 +65,10 @@ def _start_transcoder_if_needed():
|
||||
print('⚠️ ffmpeg not found; /stream.mp3 fallback disabled')
|
||||
return
|
||||
|
||||
print('🎛️ ffmpeg transcoder started for /stream.mp3')
|
||||
|
||||
def _writer():
|
||||
global _transcoder_last_error
|
||||
while True:
|
||||
chunk = _ffmpeg_in_q.get()
|
||||
if chunk is None:
|
||||
@@ -74,9 +80,11 @@ def _start_transcoder_if_needed():
|
||||
proc.stdin.write(chunk)
|
||||
except Exception:
|
||||
# If ffmpeg dies or pipe breaks, just stop writing.
|
||||
_transcoder_last_error = 'stdin write failed'
|
||||
break
|
||||
|
||||
def _reader():
|
||||
global _transcoder_bytes_out, _transcoder_last_error
|
||||
proc = _ffmpeg_proc
|
||||
if proc is None or proc.stdout is None:
|
||||
return
|
||||
@@ -84,9 +92,11 @@ def _start_transcoder_if_needed():
|
||||
try:
|
||||
data = proc.stdout.read(4096)
|
||||
except Exception:
|
||||
_transcoder_last_error = 'stdout read failed'
|
||||
break
|
||||
if not data:
|
||||
break
|
||||
_transcoder_bytes_out += len(data)
|
||||
with _mp3_lock:
|
||||
clients = list(_mp3_clients)
|
||||
for q in clients:
|
||||
@@ -120,8 +130,10 @@ def _stop_transcoder():
|
||||
|
||||
|
||||
def _feed_transcoder(data: bytes):
|
||||
global _last_audio_chunk_ts
|
||||
if _ffmpeg_proc is None or _ffmpeg_proc.poll() is not None:
|
||||
return
|
||||
_last_audio_chunk_ts = eventlet.greenthread.time.time()
|
||||
try:
|
||||
_ffmpeg_in_q.put_nowait(data)
|
||||
except Exception:
|
||||
@@ -280,6 +292,21 @@ def setup_shared_routes(app):
|
||||
},
|
||||
)
|
||||
|
||||
@app.route('/stream_debug')
|
||||
def stream_debug():
|
||||
proc = _ffmpeg_proc
|
||||
running = proc is not None and proc.poll() is None
|
||||
return jsonify({
|
||||
'broadcast_active': broadcast_state.get('active', False),
|
||||
'broadcast_mimeType': broadcast_state.get('mimeType'),
|
||||
'ffmpeg_running': running,
|
||||
'ffmpeg_found': (proc is not None),
|
||||
'mp3_clients': len(_mp3_clients),
|
||||
'transcoder_bytes_out': _transcoder_bytes_out,
|
||||
'transcoder_last_error': _transcoder_last_error,
|
||||
'last_audio_chunk_ts': _last_audio_chunk_ts,
|
||||
})
|
||||
|
||||
# === DJ SERVER (Port 5000) ===
|
||||
dj_app = Flask(__name__, static_folder='.', static_url_path='')
|
||||
dj_app.config['SECRET_KEY'] = 'dj_panel_secret'
|
||||
@@ -344,6 +371,10 @@ def dj_audio(data):
|
||||
# Relay audio chunk to all listeners immediately
|
||||
if broadcast_state['active']:
|
||||
listener_socketio.emit('audio_data', data, namespace='/')
|
||||
# Ensure MP3 fallback transcoder is running (if ffmpeg is installed)
|
||||
if _ffmpeg_proc is None or _ffmpeg_proc.poll() is not None:
|
||||
_start_transcoder_if_needed()
|
||||
|
||||
if isinstance(data, (bytes, bytearray)):
|
||||
_feed_transcoder(bytes(data))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user