mirror of
https://github.com/smittix/intercept.git
synced 2026-07-08 09:38:12 -07:00
Fix Listening Post audio issues
- Add auto-reconnect on audio player errors/stalls - Fix tuneToFrequency to properly wait between stop/start - Improve ffmpeg encoding: 96k bitrate, 44.1kHz output, low latency flags - Increase stream chunk size for smoother playback Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -375,13 +375,19 @@ def _start_audio_stream(frequency: float, modulation: str):
|
|||||||
|
|
||||||
encoder_cmd = [
|
encoder_cmd = [
|
||||||
ffmpeg_path,
|
ffmpeg_path,
|
||||||
|
'-hide_banner',
|
||||||
|
'-loglevel', 'error',
|
||||||
'-f', 's16le',
|
'-f', 's16le',
|
||||||
'-ar', str(resample_rate),
|
'-ar', str(resample_rate),
|
||||||
'-ac', '1',
|
'-ac', '1',
|
||||||
'-i', 'pipe:0',
|
'-i', 'pipe:0',
|
||||||
|
'-acodec', 'libmp3lame',
|
||||||
'-f', 'mp3',
|
'-f', 'mp3',
|
||||||
'-b:a', '64k',
|
'-b:a', '96k',
|
||||||
|
'-ar', '44100', # Resample to standard rate for browser compatibility
|
||||||
'-flush_packets', '1',
|
'-flush_packets', '1',
|
||||||
|
'-fflags', '+nobuffer',
|
||||||
|
'-flags', '+low_delay',
|
||||||
'pipe:1'
|
'pipe:1'
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -754,12 +760,14 @@ def stream_audio() -> Response:
|
|||||||
return Response(b'', mimetype='audio/mpeg', status=204)
|
return Response(b'', mimetype='audio/mpeg', status=204)
|
||||||
|
|
||||||
def generate():
|
def generate():
|
||||||
chunk_size = 4096
|
chunk_size = 8192 # Larger chunks for smoother streaming
|
||||||
try:
|
try:
|
||||||
while audio_running and audio_process and audio_process.poll() is None:
|
while audio_running and audio_process and audio_process.poll() is None:
|
||||||
chunk = audio_process.stdout.read(chunk_size)
|
chunk = audio_process.stdout.read(chunk_size)
|
||||||
if not chunk:
|
if not chunk:
|
||||||
break
|
# Small wait before checking again to avoid busy loop
|
||||||
|
time.sleep(0.01)
|
||||||
|
continue
|
||||||
yield chunk
|
yield chunk
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Audio stream error: {e}")
|
logger.error(f"Audio stream error: {e}")
|
||||||
|
|||||||
+40
-3
@@ -8521,15 +8521,17 @@
|
|||||||
document.getElementById('scannerHitCount').textContent = `${tbody.children.length} signals found`;
|
document.getElementById('scannerHitCount').textContent = `${tbody.children.length} signals found`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function tuneToFrequency(freq, mod) {
|
async function tuneToFrequency(freq, mod) {
|
||||||
// Stop scanner if running
|
// Stop scanner if running
|
||||||
if (isScannerRunning) {
|
if (isScannerRunning) {
|
||||||
stopScanner();
|
stopScanner();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop any current audio
|
// Stop any current audio and wait for it to complete
|
||||||
if (isAudioPlaying) {
|
if (isAudioPlaying) {
|
||||||
stopAudio();
|
stopAudio();
|
||||||
|
// Wait for audio to fully stop
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set frequency in manual audio form
|
// Set frequency in manual audio form
|
||||||
@@ -8539,7 +8541,10 @@
|
|||||||
document.getElementById('audioModulation').value = mod;
|
document.getElementById('audioModulation').value = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start playing immediately
|
// Small delay before starting to ensure backend is ready
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
|
||||||
|
// Start playing
|
||||||
startAudio();
|
startAudio();
|
||||||
showNotification('Tuned', `Now listening to ${freq.toFixed(3)} MHz`);
|
showNotification('Tuned', `Now listening to ${freq.toFixed(3)} MHz`);
|
||||||
}
|
}
|
||||||
@@ -8604,6 +8609,38 @@
|
|||||||
|
|
||||||
let isAudioPlaying = false;
|
let isAudioPlaying = false;
|
||||||
let audioToolsAvailable = { rtl_fm: false, ffmpeg: false };
|
let audioToolsAvailable = { rtl_fm: false, ffmpeg: false };
|
||||||
|
let audioReconnectAttempts = 0;
|
||||||
|
const MAX_AUDIO_RECONNECT = 3;
|
||||||
|
|
||||||
|
// Set up audio player error handling
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const audioPlayer = document.getElementById('audioPlayer');
|
||||||
|
if (audioPlayer) {
|
||||||
|
audioPlayer.addEventListener('error', function(e) {
|
||||||
|
console.warn('Audio player error:', e);
|
||||||
|
if (isAudioPlaying && audioReconnectAttempts < MAX_AUDIO_RECONNECT) {
|
||||||
|
audioReconnectAttempts++;
|
||||||
|
console.log(`Reconnecting audio (attempt ${audioReconnectAttempts})...`);
|
||||||
|
setTimeout(() => {
|
||||||
|
audioPlayer.src = '/listening/audio/stream?' + Date.now();
|
||||||
|
audioPlayer.play().catch(() => {});
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
audioPlayer.addEventListener('stalled', function() {
|
||||||
|
console.warn('Audio stalled, attempting recovery...');
|
||||||
|
if (isAudioPlaying) {
|
||||||
|
audioPlayer.load();
|
||||||
|
audioPlayer.play().catch(() => {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
audioPlayer.addEventListener('playing', function() {
|
||||||
|
audioReconnectAttempts = 0; // Reset on successful play
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Web Audio API for visualization
|
// Web Audio API for visualization
|
||||||
let visualizerContext = null;
|
let visualizerContext = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user