Use local faster-whisper only for transcription.
Drop cloud and Ollama engine choices so audio stays on-machine via Docker Whisper, and tighten orphan detection plus UI around a single local flow.
This commit is contained in:
+31
-13
@@ -78,10 +78,8 @@ class Recording extends Model
|
||||
{
|
||||
return Attribute::get(function (): ?string {
|
||||
return match ($this->transcription_driver) {
|
||||
'cloud' => 'Cloud (OpenAI Whisper)',
|
||||
'local' => 'Local (faster-whisper)',
|
||||
'ollama' => 'Ollama host',
|
||||
default => $this->transcription_driver,
|
||||
default => $this->transcription_driver ?: 'Local (faster-whisper)',
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -160,7 +158,7 @@ class Recording extends Model
|
||||
try {
|
||||
$job = unserialize($command);
|
||||
} catch (Throwable) {
|
||||
return (bool) preg_match('/id";i:'.$this->id.';/', $payload);
|
||||
return $this->payloadMentionsRecording($payload);
|
||||
}
|
||||
|
||||
return $job instanceof TranscribeRecording
|
||||
@@ -168,6 +166,15 @@ class Recording extends Model
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback payload match when unserialize is unavailable.
|
||||
*/
|
||||
private function payloadMentionsRecording(string $payload): bool
|
||||
{
|
||||
return (bool) preg_match('/id";i:'.$this->id.';/', $payload)
|
||||
|| str_contains($payload, 'id";s:'.strlen((string) $this->id).':"'.$this->id.'"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing/pending with no worker job left (crashed worker, bad retry_after, etc.).
|
||||
*/
|
||||
@@ -183,12 +190,27 @@ class Recording extends Model
|
||||
|
||||
$reference = $this->transcription_started_at ?? $this->updated_at;
|
||||
|
||||
// Allow a short window after dispatch before the row appears / worker claims it.
|
||||
if ($reference !== null && $reference->gt(now()->subSeconds(15))) {
|
||||
if ($reference === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only treat as orphaned after the job could not possibly still be running.
|
||||
// (A short grace caused false failures while Whisper was still working.)
|
||||
$orphanAfterSeconds = max(120, (int) config('ai.transcription_timeout', 600) + 60);
|
||||
|
||||
return $reference->lte(now()->subSeconds($orphanAfterSeconds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a payload/job belongs to this recording's transcription run start time.
|
||||
*/
|
||||
public function matchesTranscriptionRun(?string $runStartedAt): bool
|
||||
{
|
||||
if ($runStartedAt === null || $this->transcription_started_at === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return $this->transcription_started_at->getTimestamp() === Carbon::parse($runStartedAt)->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,11 +224,7 @@ class Recording extends Model
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($runStartedAt === null || $this->transcription_started_at === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->transcription_started_at->getTimestamp() === Carbon::parse($runStartedAt)->getTimestamp();
|
||||
return $this->matchesTranscriptionRun($runStartedAt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -360,7 +378,7 @@ class Recording extends Model
|
||||
public function transcriptionStatusPayload(): array
|
||||
{
|
||||
$startedAt = $this->transcription_started_at;
|
||||
$elapsed = $startedAt ? $startedAt->diffInSeconds(now()) : null;
|
||||
$elapsed = $startedAt ? (int) round($startedAt->diffInSeconds(now())) : null;
|
||||
|
||||
return [
|
||||
'id' => $this->id,
|
||||
|
||||
Reference in New Issue
Block a user