Audio & Transcription
Na tej stronie
Przegląd komend
Dział zatytułowany „Przegląd komend”Pliki audio i nagrania
Dział zatytułowany „Pliki audio i nagrania”| Komenda | Opis | Typ |
|---|---|---|
save_audio_file | Zapisuje plik audio | write |
process_uploaded_audio_file | Przetwarza uploadowany plik | write |
serve_audio_file | Zwraca zawartość pliku audio | query |
link_recording_to_visit | Powiązuje nagranie z wizytą | write |
cleanup_old_recordings | Usuwa stare nagrania | write |
convert_to_pcm_stereo | Konwertuje do PCM stereo | write |
Transkrypcja
Dział zatytułowany „Transkrypcja”| Komenda | Opis | Typ |
|---|---|---|
transcribe_audio_file | Transkrybuje plik audio | write |
transcribe_recording_now | Transkrypcja z recording_id | write |
transcribe_and_save_to_visit | Transkrybuje i zapisuje do wizyty | write |
queue_transcription_job | Kolejkuje job transkrypcji | write |
get_transcription_job_status | Status jobu transkrypcji | query |
cleanup_old_transcription_jobs | Czyści stare joby | write |
unified_ai_transcribe_file | Transkrypcja przez Unified AI | write |
Pending Captures
Dział zatytułowany „Pending Captures”| Komenda | Opis | Typ |
|---|---|---|
list_pending_audio_captures | Lista oczekujących nagrań | query |
attach_capture_to_visit | Dołącza nagranie do wizyty | write |
discard_pending_capture | Odrzuca oczekujące nagranie | write |
Audio Pipeline Architecture
Dział zatytułowany „Audio Pipeline Architecture”flowchart TB subgraph Input["Źródła audio"] LIVE[🎤 Live Recording] UPLOAD[📁 File Upload] end
subgraph Processing["Przetwarzanie"] SAVE[save_audio_file] PROCESS[process_uploaded_audio_file] LINK[link_recording_to_visit] end
subgraph Transcription["Transkrypcja"] NOW[transcribe_recording_now] QUEUE[queue_transcription_job] UNIFIED[unified_ai_transcribe_file] SAVE_VISIT[transcribe_and_save_to_visit] end
subgraph Storage["Storage"] DB[(SQLite)] FILES[Audio Files] end
LIVE --> SAVE UPLOAD --> PROCESS
SAVE --> LINK PROCESS --> LINK
LINK --> NOW NOW -->|Fallback| QUEUE QUEUE -->|Fallback| UNIFIED
NOW --> DB SAVE_VISIT --> DBTranscription Flow
Dział zatytułowany „Transcription Flow”sequenceDiagram participant UI as Frontend participant Helper as transcriptionHelpers participant Tauri as Tauri Backend participant AI as Unified AI participant DB as SQLite
UI->>Helper: transcribeRecordingWithFallback(path, recordingId, visitId)
alt Ma recordingId Helper->>Tauri: transcribe_recording_now(recordingId, visitId)
alt Success Tauri-->>Helper: TranscriptionResult else Error Helper->>Tauri: queue_transcription_job(recordingId, visitId) Tauri-->>Helper: jobId
Helper->>AI: unified_ai_transcribe_file(path) AI-->>Helper: transcript end else Brak recordingId Helper->>AI: unified_ai_transcribe_file(path) AI-->>Helper: transcript end
Helper-->>UI: TranscriptionResultPliki Audio
Dział zatytułowany „Pliki Audio”save_audio_file
Dział zatytułowany „save_audio_file”Zapisuje dane audio do pliku:
// Frontend (src/types/api/audio.ts)interface SaveAudioRequest { audio_data: Uint8Array; visit_id?: string;}
const result = await safeInvoke<VistaSavedRecording>( 'save_audio_file', withSessionPayload({ audio_data, visit_id }));
interface VistaSavedRecording { recordingId: string; path: string; status: string; visitId?: string; sizeBytes: number; durationMs?: number;}Użycie:
useAudioRecording- zapis nagrania przed transkrypcjąuseAudioTranscription.persistBlob- zapis Blob → plikuseWorkspaceData- szybkie nagrania do wizyt
process_uploaded_audio_file
Dział zatytułowany „process_uploaded_audio_file”Przetwarza uploadowany plik audio:
const result = await safeInvoke<VistaSavedRecording>( 'process_uploaded_audio_file', withSessionPayload({ source_path: filePath, visit_id: visitId }));
// Użycie:// - useAudioRecording.uploadController - upload istniejącego pliku// - useVisitCreation.processAudioData - upload przy tworzeniu wizytyserve_audio_file
Dział zatytułowany „serve_audio_file”Zwraca zawartość pliku audio (do odtwarzania):
const audioData = await safeInvoke<Uint8Array>( 'serve_audio_file', withSessionPayload({ file_path: path }));
// Użycie:// - useEmergencyRecordingBridge - odsłuch nagrania awaryjnego// - useWorkspaceData - odtwarzacz nagrańlink_recording_to_visit
Dział zatytułowany „link_recording_to_visit”Powiązuje nagranie z wizytą:
await safeInvoke( 'link_recording_to_visit', withSessionPayload({ recording_id: recordingId, visit_id: visitId }));
// Aktualizuje: recordings.visit_id = visitIdcleanup_old_recordings
Dział zatytułowany „cleanup_old_recordings”Usuwa stare nagrania wg retencji:
await safeInvoke( 'cleanup_old_recordings', withSessionPayload({ max_age_days: 30 }));
// Usuwa nagrania starsze niż max_age_days// Domyślna retencja: user_preferences.audio_retention_daysconvert_to_pcm_stereo
Dział zatytułowany „convert_to_pcm_stereo”Konwertuje audio do formatu PCM stereo:
const pcmData = await safeInvoke<Uint8Array>( 'convert_to_pcm_stereo', { audio_data: inputData });
// Używane wewnętrznie w pipeline'ach audioTranskrypcja
Dział zatytułowany „Transkrypcja”transcribe_audio_file
Dział zatytułowany „transcribe_audio_file”Podstawowa transkrypcja pliku:
const transcript = await safeInvoke<string>( 'transcribe_audio_file', withSessionPayload({ file_path: audioPath }));
// Zwraca: string z tekstem transkrypcjitranscribe_recording_now
Dział zatytułowany „transcribe_recording_now”Transkrypcja z recording_id (preferowana metoda):
const result = await safeInvoke<RecordingTranscriptionResult>( 'transcribe_recording_now', withSessionPayload({ recording_id: recordingId, visit_id: visitId, // Opcjonalne source_type: 'live' // 'live' | 'upload' }));
interface RecordingTranscriptionResult { recordingId: string; visitId?: string; transcript: string; status: 'success' | 'error'; error?: string;}transcribe_and_save_to_visit
Dział zatytułowany „transcribe_and_save_to_visit”Transkrybuje i od razu zapisuje do wizyty:
await safeInvoke( 'transcribe_and_save_to_visit', withSessionPayload({ file_path: audioPath, visit_id: visitId, source_type: 'live' // lub 'upload' }));
// Backend:// 1. Transkrybuje plik// 2. UPDATE visits SET transcript = ..., raw_transcript = ...// 3. Emituje event: transcription_completedUżycie:
EmergencyRecordingButton- nagranie awaryjneVisitSupportPanel- transkrypcja w panelu wizytyuseVisitCreation- tworzenie wizyty z nagraniemuseWorkspaceData- transkrypcja w workspace
queue_transcription_job
Dział zatytułowany „queue_transcription_job”Kolejkuje job transkrypcji (dla długich nagrań):
const jobId = await safeInvoke<string>( 'queue_transcription_job', withSessionPayload({ recording_id: recordingId, visit_id: visitId, source_type: sourceType }));
// Job jest przetwarzany w tle// Status można sprawdzić przez get_transcription_job_statusget_transcription_job_status
Dział zatytułowany „get_transcription_job_status”Sprawdza status jobu:
const status = await safeInvoke<JobStatus>( 'get_transcription_job_status', withSessionPayload({ job_id: jobId }));
interface JobStatus { job_id: string; status: 'queued' | 'processing' | 'completed' | 'failed'; progress?: number; // 0-100 result?: string; // Transkrypt przy completed error?: string; // Błąd przy failed}cleanup_old_transcription_jobs
Dział zatytułowany „cleanup_old_transcription_jobs”Czyści stare joby:
await safeInvoke( 'cleanup_old_transcription_jobs', withSessionPayload({ max_age_hours: 24 }));unified_ai_transcribe_file
Dział zatytułowany „unified_ai_transcribe_file”Transkrypcja przez Unified AI (fallback):
// src/types/api/audio.ts - unifiedAiApiconst transcript = await safeInvoke<string>( 'unified_ai_transcribe_file', withSessionPayload({ file_path: audioPath }));
// Używane jako fallback gdy transcribe_recording_now zawiedzieTranscription Helpers
Dział zatytułowany „Transcription Helpers”Frontend używa helpera z automatycznym fallback:
export async function transcribeRecordingWithFallback( filePath: string, recordingId?: string, visitId?: string, sourceType: 'live' | 'upload' = 'upload'): Promise<TranscriptionResult> {
// 1. Jeśli mamy recordingId, próbuj transcribe_recording_now if (recordingId) { try { return await audioApi.transcribeRecording(recordingId, visitId, sourceType); } catch (error) { console.warn('transcribe_recording_now failed, trying fallback');
// 2. Kolejkuj job (opcjonalnie) if (visitId) { await audioApi.queueTranscription(recordingId, visitId, sourceType); } } }
// 3. Fallback: Unified AI const transcript = await unifiedAiApi.transcribeFile(filePath); return { transcript, status: 'success' };}Pending Captures
Dział zatytułowany „Pending Captures”Nagrania oczekujące na powiązanie z wizytą:
flowchart LR RECORD[🎤 Nagranie] --> PENDING[Pending Captures] PENDING -->|Attach| VISIT[Wizyta] PENDING -->|Discard| DELETED[Usunięte]list_pending_audio_captures
Dział zatytułowany „list_pending_audio_captures”const captures = await safeInvoke<PendingCaptureSummary[]>( 'list_pending_audio_captures', withSessionPayload({ limit: 10 }));
interface PendingCaptureSummary { recording_id: string; file_path: string; duration_ms?: number; size_bytes: number; created_at: string; status: 'pending' | 'processing';}attach_capture_to_visit
Dział zatytułowany „attach_capture_to_visit”Dołącza pending capture do wizyty:
await safeInvoke( 'attach_capture_to_visit', withSessionPayload({ recording_id: recordingId, visit_id: visitId }));
// Po attach:// 1. recording.visit_id = visitId// 2. recording.status = 'attached'// 3. Opcjonalnie: transkrypcjadiscard_pending_capture
Dział zatytułowany „discard_pending_capture”Odrzuca (usuwa) pending capture:
await safeInvoke( 'discard_pending_capture', withSessionPayload({ recording_id: recordingId }));
// Usuwa nagranie i powiązany plikusePendingCaptures Hook
Dział zatytułowany „usePendingCaptures Hook”const { captures, // PendingCaptureSummary[] loading, error,
refresh, // Odśwież listę attachCapture, // (recordingId, visitId) => Promise discardCapture, // (recordingId) => Promise} = usePendingCaptures({ limit: 10, pollIntervalMs: 5000 // Polling co 5s});useAudioRecording Hook
Dział zatytułowany „useAudioRecording Hook”Główny hook do nagrywania:
const { // Stan isRecording, isPaused, duration, audioLevel,
// Kontrola startRecording, stopRecording, pauseRecording, resumeRecording,
// Upload uploadFile,
// Wynik recordingResult, // VistaSavedRecording | null transcriptionResult, // TranscriptionResult | null
// Błędy error,} = useAudioRecording({ visitId?: string, autoTranscribe?: boolean, onTranscriptionComplete?: (result) => void,});useAudioTranscription Hook
Dział zatytułowany „useAudioTranscription Hook”Prostszy hook do transkrypcji:
const { isTranscribing, progress, result, error,
transcribeBlob, // (blob: Blob, visitId?) => Promise transcribeFile, // (filePath: string, visitId?) => Promise persistBlob, // (blob: Blob, visitId?) => Promise<path> cancel,} = useAudioTranscription();Audio Formats
Dział zatytułowany „Audio Formats”Vista wspiera następujące formaty:
| Format | Extension | Uwagi |
|---|---|---|
| WebM | .webm | Domyślny dla live recording |
| MP3 | .mp3 | Uploadowane pliki |
| WAV | .wav | Uploadowane pliki |
| FLAC | .flac | Uploadowane pliki |
| MP4 | .mp4 | Audio track z video |
STT Providers
Dział zatytułowany „STT Providers”Transkrypcja używa providera z automatycznym failover:
flowchart TD AUDIO[Audio] --> CHECK{Provider available?}
CHECK -->|1| LIBRAXIS[LibraxisAI] LIBRAXIS -->|Fail| MLX CHECK -->|2| MLX[MLX Whisper] MLX -->|Fail| OPENAI CHECK -->|3| OPENAI[OpenAI Whisper]
LIBRAXIS --> RESULT[Transcript] MLX --> RESULT OPENAI --> RESULT| Provider | Diaryzacja | Latency | Uwagi |
|---|---|---|---|
| LibraxisAI | ✅ | ~2s/min | Primary |
| MLX Whisper | ❌ | ~3s/min | Apple Silicon only |
| OpenAI Whisper | ❌ | ~4s/min | Fallback |
Tauri Events
Dział zatytułowany „Tauri Events”| Event | Payload | Kiedy |
|---|---|---|
transcription_completed | { visit_id } | Po zakończeniu transkrypcji |
transcription_progress | { progress, job_id } | Postęp transkrypcji |
recording_saved | { recording_id, path } | Po zapisaniu nagrania |
pending_capture_added | { recording_id } | Nowe pending capture |
Error Codes
Dział zatytułowany „Error Codes”| Kod | Opis | Rozwiązanie |
|---|---|---|
recording_not_found | Nagranie nie istnieje | Sprawdź recording_id |
audio_file_not_found | Plik audio nie istnieje | Sprawdź ścieżkę |
audio_too_short | Nagranie < 1 sekunda | Nagraj dłużej |
audio_corrupted | Nie można zdekodować | Nagraj ponownie |
transcription_timeout | STT timeout | Spróbuj krótsze audio |
stt_unavailable | Brak dostępnego STT | Sprawdź połączenie |
unsupported_format | Nieobsługiwany format | Użyj WebM/MP3/WAV |
Powiązane dokumenty
Dział zatytułowany „Powiązane dokumenty”- Audio Overview - Przegląd pipeline audio
- WhisperX Integration - STT providers
- Diarization - Rozpoznawanie mówców
- Transcripts - Przetwarzanie transkryptów
- Visits Commands - Transkrypcja w wizytach