mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Bind monitor audio stream to start request token
This commit is contained in:
@@ -1606,14 +1606,25 @@ def audio_probe() -> Response:
|
|||||||
return jsonify({'status': 'ok', 'bytes': size})
|
return jsonify({'status': 'ok', 'bytes': size})
|
||||||
|
|
||||||
|
|
||||||
@receiver_bp.route('/audio/stream')
|
@receiver_bp.route('/audio/stream')
|
||||||
def stream_audio() -> Response:
|
def stream_audio() -> Response:
|
||||||
"""Stream WAV audio."""
|
"""Stream WAV audio."""
|
||||||
if audio_source == 'waterfall':
|
request_token_raw = request.args.get('request_token')
|
||||||
for _ in range(40):
|
request_token = None
|
||||||
if audio_running:
|
if request_token_raw is not None:
|
||||||
break
|
try:
|
||||||
time.sleep(0.05)
|
request_token = int(request_token_raw)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
request_token = None
|
||||||
|
|
||||||
|
if request_token is not None and request_token < audio_start_token:
|
||||||
|
return Response(b'', mimetype='audio/wav', status=204)
|
||||||
|
|
||||||
|
if audio_source == 'waterfall':
|
||||||
|
for _ in range(40):
|
||||||
|
if audio_running:
|
||||||
|
break
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
||||||
if not audio_running:
|
if not audio_running:
|
||||||
return Response(b'', mimetype='audio/wav', status=204)
|
return Response(b'', mimetype='audio/wav', status=204)
|
||||||
@@ -1633,6 +1644,8 @@ def stream_audio() -> Response:
|
|||||||
inactive_since: float | None = None
|
inactive_since: float | None = None
|
||||||
|
|
||||||
while audio_running and audio_source == 'waterfall':
|
while audio_running and audio_source == 'waterfall':
|
||||||
|
if request_token is not None and request_token < audio_start_token:
|
||||||
|
break
|
||||||
chunk = read_shared_monitor_audio_chunk(timeout=1.0)
|
chunk = read_shared_monitor_audio_chunk(timeout=1.0)
|
||||||
if chunk:
|
if chunk:
|
||||||
inactive_since = None
|
inactive_since = None
|
||||||
@@ -1672,11 +1685,11 @@ def stream_audio() -> Response:
|
|||||||
if not audio_running or not audio_process:
|
if not audio_running or not audio_process:
|
||||||
return Response(b'', mimetype='audio/wav', status=204)
|
return Response(b'', mimetype='audio/wav', status=204)
|
||||||
|
|
||||||
def generate():
|
def generate():
|
||||||
# Capture local reference to avoid race condition with stop
|
# Capture local reference to avoid race condition with stop
|
||||||
proc = audio_process
|
proc = audio_process
|
||||||
if not proc or not proc.stdout:
|
if not proc or not proc.stdout:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
# Drain stale audio that accumulated in the pipe buffer
|
# Drain stale audio that accumulated in the pipe buffer
|
||||||
# between pipeline start and stream connection. Keep the
|
# between pipeline start and stream connection. Keep the
|
||||||
@@ -1695,15 +1708,17 @@ def stream_audio() -> Response:
|
|||||||
if header_chunk:
|
if header_chunk:
|
||||||
yield header_chunk
|
yield header_chunk
|
||||||
|
|
||||||
# Stream real-time audio
|
# Stream real-time audio
|
||||||
first_chunk_deadline = time.time() + 20.0
|
first_chunk_deadline = time.time() + 20.0
|
||||||
warned_wait = False
|
warned_wait = False
|
||||||
while audio_running and proc.poll() is None:
|
while audio_running and proc.poll() is None:
|
||||||
# Use select to avoid blocking forever
|
if request_token is not None and request_token < audio_start_token:
|
||||||
ready, _, _ = select.select([proc.stdout], [], [], 2.0)
|
break
|
||||||
if ready:
|
# Use select to avoid blocking forever
|
||||||
chunk = proc.stdout.read(8192)
|
ready, _, _ = select.select([proc.stdout], [], [], 2.0)
|
||||||
if chunk:
|
if ready:
|
||||||
|
chunk = proc.stdout.read(8192)
|
||||||
|
if chunk:
|
||||||
warned_wait = False
|
warned_wait = False
|
||||||
yield chunk
|
yield chunk
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -2603,7 +2603,7 @@ const Waterfall = (function () {
|
|||||||
player.load();
|
player.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _attachMonitorAudio(nonce) {
|
async function _attachMonitorAudio(nonce, streamToken = null) {
|
||||||
const player = document.getElementById('wfAudioPlayer');
|
const player = document.getElementById('wfAudioPlayer');
|
||||||
if (!player) {
|
if (!player) {
|
||||||
return { ok: false, reason: 'player_missing', message: 'Audio player is unavailable.' };
|
return { ok: false, reason: 'player_missing', message: 'Audio player is unavailable.' };
|
||||||
@@ -2622,7 +2622,10 @@ const Waterfall = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await _pauseMonitorAudioElement();
|
await _pauseMonitorAudioElement();
|
||||||
player.src = `/receiver/audio/stream?fresh=1&t=${Date.now()}-${attempt}`;
|
const tokenQuery = (streamToken !== null && streamToken !== undefined && String(streamToken).length > 0)
|
||||||
|
? `&request_token=${encodeURIComponent(String(streamToken))}`
|
||||||
|
: '';
|
||||||
|
player.src = `/receiver/audio/stream?fresh=1&t=${Date.now()}-${attempt}${tokenQuery}`;
|
||||||
player.load();
|
player.load();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -2886,7 +2889,7 @@ const Waterfall = (function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const attach = await _attachMonitorAudio(nonce);
|
const attach = await _attachMonitorAudio(nonce, payload?.request_token);
|
||||||
if (nonce !== _audioConnectNonce) return;
|
if (nonce !== _audioConnectNonce) return;
|
||||||
_monitorSource = payload?.source === 'waterfall' ? 'waterfall' : 'process';
|
_monitorSource = payload?.source === 'waterfall' ? 'waterfall' : 'process';
|
||||||
if (
|
if (
|
||||||
|
|||||||
Reference in New Issue
Block a user