Keep live Whisper segments on screen without a page refresh.

Treat streamed chunks as appends, stop Livewire from remorphing the Alpine tree, and hydrate from HTTP while a run is active so segment cards appear as they arrive.
This commit is contained in:
ben
2026-08-13 16:35:33 +02:00
parent 187b6b5d12
commit 3a9cf50529
7 changed files with 265 additions and 65 deletions
@@ -330,6 +330,35 @@ class TranscriptionBroadcastTest extends TestCase
$this->assertSame(-0.1, $recording->transcription_verbose['segments'][0]['avg_logprob']);
}
public function test_consecutive_live_whisper_segments_are_appended(): void
{
Event::fake([RecordingTranscriptionUpdated::class]);
$recording = Recording::query()->create([
'user_id' => $this->user->id,
'title' => 'Append live',
'original_filename' => 'append.mp3',
'file_path' => 'recordings/append.mp3',
'file_size_bytes' => 100,
'transcription_status' => 'processing',
'transcription_driver' => 'local',
'transcription_started_at' => now(),
]);
$recording->reportProgress('Transcribing locally…', 40, partialTranscript: "didn't I wasn't aware", whisperDelta: [
'language' => 'en',
'segment' => ['id' => 0, 'text' => "didn't I wasn't aware", 'start' => 254.5, 'end' => 260.8],
]);
$recording->refresh()->reportProgress('Transcribing locally…', 45, partialTranscript: "didn't I wasn't aware other people", whisperDelta: [
'language' => 'en',
'segment' => ['id' => 0, 'text' => 'other people', 'start' => 260.8, 'end' => 267.4],
]);
$recording->refresh();
$this->assertCount(2, $recording->transcription_verbose['segments']);
$this->assertSame('other people', $recording->transcription_verbose['segments'][1]['text']);
}
public function test_oversized_transcript_delta_is_not_broadcast(): void
{
$recording = Recording::query()->create([