Fix buffering issue and app bugs: improve stream delivery, fixed reset UI desync, and EQ naming
This commit is contained in:
parent
1776f631ef
commit
02f72e2372
12
script.js
12
script.js
|
|
@ -2242,7 +2242,17 @@ function initListenerMode() {
|
|||
socket.on('broadcast_started', () => {
|
||||
const nowPlayingEl = document.getElementById('listener-now-playing');
|
||||
if (nowPlayingEl) nowPlayingEl.textContent = '🎵 Stream is live!';
|
||||
// Reset MediaSource for fresh stream if needed
|
||||
|
||||
// Force a reload of the audio element to capture the fresh stream
|
||||
if (window.listenerAudio) {
|
||||
console.log('🔄 Broadcast started: Refreshing audio stream...');
|
||||
const wasPlaying = !window.listenerAudio.paused;
|
||||
window.listenerAudio.src = getMp3FallbackUrl();
|
||||
window.listenerAudio.load();
|
||||
if (wasPlaying || window.listenerAudioEnabled) {
|
||||
window.listenerAudio.play().catch(e => console.warn('Auto-play after refresh blocked:', e));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('stream_status', (data) => {
|
||||
|
|
|
|||
21
server.py
21
server.py
|
|
@ -55,7 +55,7 @@ _transcode_threads_started = False
|
|||
_transcoder_bytes_out = 0
|
||||
_transcoder_last_error = None
|
||||
_last_audio_chunk_ts = 0.0
|
||||
_mp3_preroll = collections.deque(maxlen=60) # Pre-roll (~2.5s at 192k)
|
||||
_mp3_preroll = collections.deque(maxlen=256) # Pre-roll (~10s at 192k with 1KB chunks)
|
||||
|
||||
|
||||
def _start_transcoder_if_needed(is_mp3_input=False):
|
||||
|
|
@ -141,7 +141,8 @@ def _start_transcoder_if_needed(is_mp3_input=False):
|
|||
break
|
||||
continue
|
||||
except Exception as e:
|
||||
print(f"⚠️ Transcoder writer error: {e}")
|
||||
if _ffmpeg_proc is not None:
|
||||
print(f"⚠️ Transcoder writer error: {e}")
|
||||
_transcoder_last_error = f'stdin write failed: {e}'
|
||||
break
|
||||
_transcode_threads_started = False
|
||||
|
|
@ -153,8 +154,9 @@ def _start_transcoder_if_needed(is_mp3_input=False):
|
|||
proc = _ffmpeg_proc
|
||||
while proc and proc.poll() is None:
|
||||
try:
|
||||
# Use a larger read for efficiency
|
||||
data = proc.stdout.read(4096)
|
||||
# Smaller read for smoother delivery (1KB)
|
||||
# This prevents buffering delays at lower bitrates
|
||||
data = proc.stdout.read(1024)
|
||||
if not data:
|
||||
break
|
||||
_transcoder_bytes_out += len(data)
|
||||
|
|
@ -199,6 +201,17 @@ def _stop_transcoder():
|
|||
|
||||
if proc is None:
|
||||
return
|
||||
|
||||
# Signal all listening clients to finish their stream
|
||||
with _mp3_lock:
|
||||
clients = list(_mp3_clients)
|
||||
for q in clients:
|
||||
try:
|
||||
q.put_nowait(None)
|
||||
except:
|
||||
pass
|
||||
_mp3_clients.clear()
|
||||
|
||||
try:
|
||||
proc.terminate()
|
||||
except Exception:
|
||||
|
|
|
|||
27
techdj_qt.py
27
techdj_qt.py
|
|
@ -57,6 +57,7 @@ class AudioEngine:
|
|||
'loop_active': False,
|
||||
'repeat': False,
|
||||
'queue': [],
|
||||
'needs_next_track': False,
|
||||
},
|
||||
'B': {
|
||||
'audio_data': None,
|
||||
|
|
@ -75,6 +76,7 @@ class AudioEngine:
|
|||
'loop_active': False,
|
||||
'repeat': False,
|
||||
'queue': [],
|
||||
'needs_next_track': False,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -410,8 +412,8 @@ class BroadcastThread(QThread):
|
|||
|
||||
# Thread to read encoded chunks from stdout
|
||||
def read_output():
|
||||
# Smaller buffer for more frequent updates (4KB = ~0.15s @ 192k)
|
||||
buffer_size = 4096
|
||||
# Smaller buffer for more frequent updates (2KB = ~0.08s @ 192k)
|
||||
buffer_size = 2048
|
||||
while self.running:
|
||||
try:
|
||||
data = self.process.stdout.read(buffer_size)
|
||||
|
|
@ -806,8 +808,9 @@ class DeckWidget(QWidget):
|
|||
eq_widget = QWidget()
|
||||
eq_layout = QHBoxLayout(eq_widget)
|
||||
eq_layout.setSpacing(8)
|
||||
self.eq_sliders = {}
|
||||
|
||||
for band in ['HI', 'MID', 'LO']:
|
||||
for band in ['HIGH', 'MID', 'LOW']:
|
||||
band_widget = QWidget()
|
||||
band_layout = QVBoxLayout(band_widget)
|
||||
band_layout.setSpacing(2)
|
||||
|
|
@ -819,6 +822,7 @@ class DeckWidget(QWidget):
|
|||
slider.setFixedHeight(80)
|
||||
slider.setStyleSheet(self.get_slider_style())
|
||||
slider.valueChanged.connect(lambda v, b=band.lower(): self.on_eq_change(b, v))
|
||||
self.eq_sliders[band.lower()] = slider
|
||||
|
||||
label = QLabel(band)
|
||||
label.setStyleSheet("color: #888; font-size: 9px;")
|
||||
|
|
@ -1001,20 +1005,23 @@ class DeckWidget(QWidget):
|
|||
|
||||
def reset_deck(self):
|
||||
"""Reset all deck controls to default values"""
|
||||
# Setting values on sliders will trigger the valueChanged signal
|
||||
# which will in turn update the audio engine.
|
||||
|
||||
# Reset volume to 80%
|
||||
self.volume_slider.setValue(80)
|
||||
|
||||
# Reset speed to 100%
|
||||
self.speed_slider.setValue(100)
|
||||
|
||||
# Reset EQ to 0 (just update the engine, sliders will update via signals)
|
||||
self.audio_engine.set_eq(self.deck_id, 'high', 0)
|
||||
self.audio_engine.set_eq(self.deck_id, 'mid', 0)
|
||||
self.audio_engine.set_eq(self.deck_id, 'low', 0)
|
||||
# Reset EQ sliders to 0
|
||||
if hasattr(self, 'eq_sliders'):
|
||||
for band, slider in self.eq_sliders.items():
|
||||
slider.setValue(0)
|
||||
|
||||
# Reset filters
|
||||
self.audio_engine.set_filter(self.deck_id, 'lowpass', 100)
|
||||
self.audio_engine.set_filter(self.deck_id, 'highpass', 0)
|
||||
# Reset filter sliders
|
||||
self.lp_slider.setValue(100)
|
||||
self.hp_slider.setValue(0)
|
||||
|
||||
print(f"🔄 Deck {self.deck_id} reset to defaults")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue