Enable recorded stream seeking

This commit is contained in:
2026-05-26 19:11:19 -07:00
parent 5e2a2e1de7
commit 8b74d25954
5 changed files with 56 additions and 13 deletions

View File

@@ -269,11 +269,14 @@ app.get('/audio/:sessionId', (request, response) => {
return;
}
if (PLAYBACK_CONNECTION_MODE === 'single' || PLAYBACK_CONNECTION_MODE === 'relay') {
getOrCreatePlayback(session).attachAudio(request, response);
const playbackMode = getSessionPlaybackConnectionMode(session);
if (playbackMode === 'single' || playbackMode === 'relay') {
getOrCreatePlayback(session, playbackMode).attachAudio(request, response);
return;
}
stopSharedPlaybackIfNeeded(session, playbackMode);
streamSplitAudio(request, response, session);
});
@@ -301,11 +304,14 @@ wss.on('connection', (websocket, _request, sessionId) => {
return;
}
if (PLAYBACK_CONNECTION_MODE === 'single' || PLAYBACK_CONNECTION_MODE === 'relay') {
getOrCreatePlayback(session).attachFrames(websocket);
const playbackMode = getSessionPlaybackConnectionMode(session);
if (playbackMode === 'single' || playbackMode === 'relay') {
getOrCreatePlayback(session, playbackMode).attachFrames(websocket);
return;
}
stopSharedPlaybackIfNeeded(session, playbackMode);
streamSplitFrames(websocket, session);
});
@@ -413,7 +419,19 @@ function formatSessionPayload(session) {
}
function isSessionSeekable(session) {
return PLAYBACK_CONNECTION_MODE !== 'relay' && Number.isFinite(session.duration) && session.duration > 0;
return hasRecordedDuration(session);
}
function hasRecordedDuration(session) {
return Number.isFinite(session.duration) && session.duration > 0;
}
function getSessionPlaybackConnectionMode(session) {
if (PLAYBACK_CONNECTION_MODE === 'relay' && hasRecordedDuration(session)) {
return 'split';
}
return PLAYBACK_CONNECTION_MODE;
}
function startSessionMetadataProbe(session) {
@@ -666,18 +684,34 @@ function getSession(sessionId) {
return session;
}
function getOrCreatePlayback(session) {
function getOrCreatePlayback(session, playbackMode = getSessionPlaybackConnectionMode(session)) {
const existing = playbacks.get(session.id);
if (existing && !existing.closed) {
if (existing && !existing.closed && existing.mode === playbackMode) {
return existing;
}
const playback = PLAYBACK_CONNECTION_MODE === 'relay' ? createRelayPlayback(session) : createPlayback(session);
stopSharedPlaybackIfNeeded(session, playbackMode);
const playback = playbackMode === 'relay' ? createRelayPlayback(session) : createPlayback(session);
playbacks.set(session.id, playback);
return playback;
}
function stopSharedPlaybackIfNeeded(session, playbackMode) {
const existing = playbacks.get(session.id);
if (!existing || existing.closed || existing.mode === playbackMode) {
return;
}
existing.stop('playback_mode_changed');
if (playbacks.get(session.id) === existing) {
playbacks.delete(session.id);
}
}
function streamSplitAudio(request, response, session) {
const worker = createAudioWorker(session);
const releaseWorker = once(worker.release);
@@ -884,6 +918,7 @@ function createRelayPlayback(session) {
const frameParser = createJpegFrameParser(handleJpegFrame);
const playback = {
mode: 'relay',
get closed() {
return closed;
},
@@ -1243,6 +1278,7 @@ function createPlayback(session) {
const frameParser = createJpegFrameParser(handleJpegFrame);
const playback = {
mode: 'single',
get closed() {
return closed;
},