@medc-com-br/ngx-jaimes-scribe 0.1.7 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"medc-com-br-ngx-jaimes-scribe.mjs","sources":["../../../libs/ngx-jaimes-scribe/src/lib/services/vad.service.ts","../../../libs/ngx-jaimes-scribe/src/lib/services/audio-capture.service.ts","../../../libs/ngx-jaimes-scribe/src/lib/services/scribe-socket.service.ts","../../../libs/ngx-jaimes-scribe/src/lib/utils/pcm-to-wav.ts","../../../libs/ngx-jaimes-scribe/src/lib/components/recorder/recorder.component.ts","../../../libs/ngx-jaimes-scribe/src/medc-com-br-ngx-jaimes-scribe.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\nexport type VadState = 'idle' | 'speech' | 'silence_pending' | 'silence';\n\nexport interface VadConfig {\n speechThreshold: number;\n silenceThreshold: number;\n silenceDebounceMs: number;\n}\n\nconst DEFAULT_CONFIG: VadConfig = {\n speechThreshold: 8,\n silenceThreshold: 3,\n silenceDebounceMs: 1500,\n};\n\n@Injectable({ providedIn: 'root' })\nexport class VadService {\n private state: VadState = 'idle';\n private silenceStartTime: number | null = null;\n private config = { ...DEFAULT_CONFIG };\n\n readonly state$ = new BehaviorSubject<VadState>('idle');\n\n analyzeLevel(level: number): { isSilence: boolean } {\n const now = Date.now();\n\n if (level >= this.config.speechThreshold) {\n this.state = 'speech';\n this.silenceStartTime = null;\n this.state$.next('speech');\n return { isSilence: false };\n }\n\n if (level < this.config.silenceThreshold) {\n if (this.state === 'speech') {\n this.silenceStartTime = now;\n this.state = 'silence_pending';\n } else if (this.state === 'silence_pending' && this.silenceStartTime) {\n if (now - this.silenceStartTime >= this.config.silenceDebounceMs) {\n this.state = 'silence';\n this.state$.next('silence');\n }\n }\n } else {\n if (this.state === 'silence_pending') {\n this.state = 'speech';\n this.silenceStartTime = null;\n }\n }\n\n return { isSilence: this.state === 'silence' };\n }\n\n reset(): void {\n this.state = 'idle';\n this.silenceStartTime = null;\n this.state$.next('idle');\n }\n\n getState(): VadState {\n return this.state;\n }\n}\n","import { Injectable, InjectionToken, inject, NgZone } from '@angular/core';\nimport { Subject, Observable, BehaviorSubject } from 'rxjs';\nimport { VadService } from './vad.service';\n\nexport interface AudioCaptureConfig {\n workletUrl: string;\n levelUpdateInterval: number;\n}\n\nexport const AUDIO_CAPTURE_CONFIG = new InjectionToken<AudioCaptureConfig>('AUDIO_CAPTURE_CONFIG');\n\nconst DEFAULT_CONFIG: AudioCaptureConfig = {\n workletUrl: '/assets/pcm-processor.js',\n levelUpdateInterval: 50,\n};\n\nexport interface AudioChunk {\n data: ArrayBuffer;\n isSilence: boolean;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class AudioCaptureService {\n private config: AudioCaptureConfig;\n private ngZone: NgZone;\n private vadService: VadService;\n private audioContext: AudioContext | null = null;\n private workletNode: AudioWorkletNode | null = null;\n private analyserNode: AnalyserNode | null = null;\n private source: MediaStreamAudioSourceNode | null = null;\n private stream: MediaStream | null = null;\n private workletRegistered = false;\n private levelInterval: ReturnType<typeof setInterval> | null = null;\n private paused = false;\n\n private audioChunkSubject = new Subject<AudioChunk>();\n private audioLevelSubject = new BehaviorSubject<number>(0);\n private errorSubject = new Subject<Error>();\n\n audioChunk$: Observable<AudioChunk> = this.audioChunkSubject.asObservable();\n audioLevel$: Observable<number> = this.audioLevelSubject.asObservable();\n error$: Observable<Error> = this.errorSubject.asObservable();\n\n constructor() {\n const injectedConfig = inject(AUDIO_CAPTURE_CONFIG, { optional: true });\n this.config = injectedConfig ?? DEFAULT_CONFIG;\n this.ngZone = inject(NgZone);\n this.vadService = inject(VadService);\n }\n\n async startCapture(): Promise<void> {\n try {\n this.stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n channelCount: 1,\n echoCancellation: true,\n noiseSuppression: true,\n },\n });\n\n this.audioContext = new AudioContext();\n\n if (!this.workletRegistered) {\n await this.audioContext.audioWorklet.addModule(this.config.workletUrl);\n this.workletRegistered = true;\n }\n\n this.workletNode = new AudioWorkletNode(this.audioContext, 'pcm-processor', {\n processorOptions: {\n inputSampleRate: this.audioContext.sampleRate,\n },\n });\n\n this.workletNode.port.onmessage = (event: MessageEvent<ArrayBuffer>) => {\n if (!this.paused) {\n const level = this.getAudioLevel();\n const { isSilence } = this.vadService.analyzeLevel(level);\n this.audioChunkSubject.next({ data: event.data, isSilence });\n }\n };\n\n this.analyserNode = this.audioContext.createAnalyser();\n this.analyserNode.fftSize = 256;\n this.analyserNode.smoothingTimeConstant = 0.8;\n\n this.source = this.audioContext.createMediaStreamSource(this.stream);\n this.source.connect(this.analyserNode);\n this.source.connect(this.workletNode);\n\n this.startLevelMonitoring();\n } catch (error) {\n const err = error instanceof Error ? error : new Error('Failed to start audio capture');\n this.errorSubject.next(err);\n throw err;\n }\n }\n\n async stopCapture(): Promise<void> {\n this.stopLevelMonitoring();\n this.paused = false;\n this.vadService.reset();\n\n if (this.workletNode) {\n this.workletNode.port.close();\n this.workletNode.disconnect();\n this.workletNode = null;\n }\n\n if (this.analyserNode) {\n this.analyserNode.disconnect();\n this.analyserNode = null;\n }\n\n if (this.source) {\n this.source.disconnect();\n this.source = null;\n }\n\n if (this.audioContext) {\n await this.audioContext.close();\n this.audioContext = null;\n this.workletRegistered = false;\n }\n\n if (this.stream) {\n this.stream.getTracks().forEach((track) => track.stop());\n this.stream = null;\n }\n\n this.audioLevelSubject.next(0);\n }\n\n pauseCapture(): void {\n if (this.isCapturing() && !this.paused) {\n this.paused = true;\n }\n }\n\n resumeCapture(): void {\n if (this.isCapturing() && this.paused) {\n this.paused = false;\n }\n }\n\n isCapturing(): boolean {\n return this.workletNode !== null && this.stream !== null;\n }\n\n isPaused(): boolean {\n return this.paused;\n }\n\n getSampleRate(): number | null {\n return this.audioContext?.sampleRate ?? null;\n }\n\n private startLevelMonitoring(): void {\n this.stopLevelMonitoring();\n\n this.ngZone.runOutsideAngular(() => {\n this.levelInterval = setInterval(() => {\n const level = this.getAudioLevel();\n this.ngZone.run(() => {\n this.audioLevelSubject.next(level);\n });\n }, this.config.levelUpdateInterval);\n });\n }\n\n private stopLevelMonitoring(): void {\n if (this.levelInterval) {\n clearInterval(this.levelInterval);\n this.levelInterval = null;\n }\n }\n\n private getAudioLevel(): number {\n if (!this.analyserNode) {\n return 0;\n }\n\n const dataArray = new Uint8Array(this.analyserNode.frequencyBinCount);\n this.analyserNode.getByteFrequencyData(dataArray);\n\n const sum = dataArray.reduce((acc, val) => acc + val, 0);\n const average = sum / dataArray.length;\n\n return Math.round((average / 255) * 100);\n }\n}\n","import { Injectable, InjectionToken, inject, NgZone } from '@angular/core';\nimport { BehaviorSubject, Subject, Observable } from 'rxjs';\nimport type { TranscriptionEvent } from '@medc-com-br/jaimes-shared';\n\nexport type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n\nexport interface ScribeSocketConfig {\n reconnectAttempts: number;\n reconnectBaseDelay: number;\n chunkBufferInterval: number;\n}\n\nexport const SCRIBE_SOCKET_CONFIG = new InjectionToken<ScribeSocketConfig>('SCRIBE_SOCKET_CONFIG');\n\nconst DEFAULT_CONFIG: ScribeSocketConfig = {\n reconnectAttempts: 5,\n reconnectBaseDelay: 1000,\n chunkBufferInterval: 250,\n};\n\n@Injectable({ providedIn: 'root' })\nexport class ScribeSocketService {\n private config: ScribeSocketConfig;\n private ngZone: NgZone;\n private ws: WebSocket | null = null;\n private wsUrl: string | null = null;\n private token: string | null = null;\n private premium = false;\n private reconnectAttempt = 0;\n private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n private intentionalClose = false;\n\n private chunkBuffer: string[] = [];\n private sendInterval: ReturnType<typeof setInterval> | null = null;\n private keepaliveInterval: ReturnType<typeof setInterval> | null = null;\n private currentlyInSilence = false;\n\n private connectionStateSubject = new BehaviorSubject<ConnectionState>('disconnected');\n private transcriptionSubject = new Subject<TranscriptionEvent>();\n private errorSubject = new Subject<Error>();\n private sessionIdSubject = new BehaviorSubject<string | null>(null);\n\n connectionState$: Observable<ConnectionState> = this.connectionStateSubject.asObservable();\n transcription$: Observable<TranscriptionEvent> = this.transcriptionSubject.asObservable();\n error$: Observable<Error> = this.errorSubject.asObservable();\n sessionId$: Observable<string | null> = this.sessionIdSubject.asObservable();\n\n constructor() {\n const injectedConfig = inject(SCRIBE_SOCKET_CONFIG, { optional: true });\n this.config = injectedConfig ?? DEFAULT_CONFIG;\n this.ngZone = inject(NgZone);\n }\n\n async connect(url: string, token: string, premium = false): Promise<void> {\n if (this.connectionStateSubject.getValue() === 'connecting') {\n throw new Error('Connection already in progress');\n }\n\n if (this.isConnected()) {\n this.disconnect();\n }\n\n this.clearReconnectTimeout();\n this.wsUrl = url;\n this.token = token;\n this.premium = premium;\n this.intentionalClose = false;\n this.reconnectAttempt = 0;\n\n return this.createConnection();\n }\n\n disconnect(): void {\n this.intentionalClose = true;\n this.flushAndStopBuffering();\n this.clearReconnectTimeout();\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close(1000, 'Client disconnect');\n }\n this.ws = null;\n\n this.connectionStateSubject.next('disconnected');\n this.sessionIdSubject.next(null);\n }\n\n sendAudioChunk(chunk: ArrayBuffer, isSilence: boolean): void {\n const message = JSON.stringify({\n type: 'audio',\n isSilence,\n data: this.arrayBufferToBase64(chunk),\n });\n this.chunkBuffer.push(message);\n\n if (isSilence && !this.currentlyInSilence) {\n this.currentlyInSilence = true;\n this.startKeepaliveInterval();\n } else if (!isSilence && this.currentlyInSilence) {\n this.currentlyInSilence = false;\n this.stopKeepaliveInterval();\n }\n }\n\n private startKeepaliveInterval(): void {\n this.stopKeepaliveInterval();\n this.keepaliveInterval = setInterval(() => {\n if (this.isConnected()) {\n this.ws!.send(JSON.stringify({ type: 'keepalive' }));\n }\n }, 3000);\n }\n\n private stopKeepaliveInterval(): void {\n if (this.keepaliveInterval) {\n clearInterval(this.keepaliveInterval);\n this.keepaliveInterval = null;\n }\n }\n\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n getSessionId(): string | null {\n return this.sessionIdSubject.getValue();\n }\n\n private createConnection(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.wsUrl) {\n reject(new Error('WebSocket URL is required'));\n return;\n }\n\n this.connectionStateSubject.next('connecting');\n const params = new URLSearchParams({ premium: String(this.premium) });\n if (this.token) {\n params.set('token', this.token);\n }\n const url = `${this.wsUrl}?${params.toString()}`;\n\n this.ws = new WebSocket(url);\n this.ws.binaryType = 'arraybuffer';\n\n this.ws.onopen = () => {\n this.ngZone.run(() => {\n this.reconnectAttempt = 0;\n this.connectionStateSubject.next('connected');\n this.startBuffering();\n resolve();\n });\n };\n\n this.ws.onerror = () => {\n this.ngZone.run(() => {\n const error = new Error('WebSocket connection error');\n this.errorSubject.next(error);\n if (this.connectionStateSubject.getValue() === 'connecting') {\n reject(error);\n }\n });\n };\n\n this.ws.onmessage = (event) => {\n this.ngZone.run(() => {\n try {\n const data = JSON.parse(event.data);\n if (data.type === 'connected' && data.sessionId) {\n this.sessionIdSubject.next(data.sessionId);\n }\n this.transcriptionSubject.next(data as TranscriptionEvent);\n } catch (e) {\n const error = new Error(`Failed to parse WebSocket message: ${e instanceof Error ? e.message : String(e)}`);\n console.error(error.message);\n this.errorSubject.next(error);\n }\n });\n };\n\n this.ws.onclose = (event) => {\n this.ngZone.run(() => {\n this.stopBuffering();\n\n if (!this.intentionalClose && event.code !== 1000) {\n this.attemptReconnect();\n } else {\n this.connectionStateSubject.next('disconnected');\n this.sessionIdSubject.next(null);\n }\n });\n };\n });\n }\n\n private attemptReconnect(): void {\n if (this.reconnectAttempt >= this.config.reconnectAttempts) {\n this.connectionStateSubject.next('disconnected');\n this.errorSubject.next(new Error('Max reconnection attempts reached'));\n return;\n }\n\n this.connectionStateSubject.next('reconnecting');\n const delay = this.config.reconnectBaseDelay * Math.pow(2, this.reconnectAttempt);\n this.reconnectAttempt++;\n\n this.reconnectTimeout = setTimeout(() => {\n this.createConnection().catch(() => {});\n }, delay);\n }\n\n private clearReconnectTimeout(): void {\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n }\n\n private startBuffering(): void {\n this.stopBuffering();\n\n this.sendInterval = setInterval(() => {\n if (this.chunkBuffer.length > 0 && this.isConnected()) {\n for (const msg of this.chunkBuffer) {\n this.ws!.send(msg);\n }\n this.chunkBuffer = [];\n }\n }, this.config.chunkBufferInterval);\n }\n\n private flushAndStopBuffering(): void {\n if (this.sendInterval) {\n clearInterval(this.sendInterval);\n this.sendInterval = null;\n }\n\n if (this.chunkBuffer.length > 0 && this.isConnected()) {\n for (const msg of this.chunkBuffer) {\n this.ws!.send(msg);\n }\n }\n this.chunkBuffer = [];\n this.stopKeepaliveInterval();\n this.currentlyInSilence = false;\n }\n\n private stopBuffering(): void {\n if (this.sendInterval) {\n clearInterval(this.sendInterval);\n this.sendInterval = null;\n }\n this.chunkBuffer = [];\n }\n\n}\n","const SAMPLE_RATE = 16000;\nconst NUM_CHANNELS = 1;\nconst BITS_PER_SAMPLE = 16;\n\nfunction writeString(view: DataView, offset: number, str: string): void {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n}\n\nfunction concatBuffers(buffer1: ArrayBuffer, buffer2: ArrayBuffer): ArrayBuffer {\n const combined = new Uint8Array(buffer1.byteLength + buffer2.byteLength);\n combined.set(new Uint8Array(buffer1), 0);\n combined.set(new Uint8Array(buffer2), buffer1.byteLength);\n return combined.buffer;\n}\n\nexport function pcmToWav(pcmData: ArrayBuffer, sampleRate = SAMPLE_RATE): ArrayBuffer {\n const header = new ArrayBuffer(44);\n const view = new DataView(header);\n\n const byteRate = sampleRate * NUM_CHANNELS * (BITS_PER_SAMPLE / 8);\n const blockAlign = NUM_CHANNELS * (BITS_PER_SAMPLE / 8);\n\n // RIFF chunk descriptor\n writeString(view, 0, 'RIFF');\n view.setUint32(4, 36 + pcmData.byteLength, true);\n writeString(view, 8, 'WAVE');\n\n // fmt sub-chunk\n writeString(view, 12, 'fmt ');\n view.setUint32(16, 16, true); // SubChunk1Size (16 for PCM)\n view.setUint16(20, 1, true); // AudioFormat (1 = PCM)\n view.setUint16(22, NUM_CHANNELS, true); // NumChannels\n view.setUint32(24, sampleRate, true); // SampleRate\n view.setUint32(28, byteRate, true); // ByteRate\n view.setUint16(32, blockAlign, true); // BlockAlign\n view.setUint16(34, BITS_PER_SAMPLE, true); // BitsPerSample\n\n // data sub-chunk\n writeString(view, 36, 'data');\n view.setUint32(40, pcmData.byteLength, true);\n\n return concatBuffers(header, pcmData);\n}\n\nexport function createAudioBlobUrl(wavData: ArrayBuffer): string {\n const blob = new Blob([wavData], { type: 'audio/wav' });\n return URL.createObjectURL(blob);\n}\n\nexport function formatTime(seconds: number): string {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n","import { Component, inject, signal, input, output, OnDestroy, computed, HostListener, ElementRef, effect } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { AudioCaptureService } from '../../services/audio-capture.service';\nimport { ScribeSocketService, ConnectionState } from '../../services/scribe-socket.service';\nimport { pcmToWav, createAudioBlobUrl, formatTime } from '../../utils/pcm-to-wav';\nimport type { TranscriptionEvent, TemplateOption, GeneratedDocument, SessionPlaybackData, TranscriptSegment, TranscriptionWord } from '@medc-com-br/jaimes-shared';\n\ninterface TranscriptEntry {\n id: number;\n text: string;\n speaker?: number;\n isFinal: boolean;\n startTime?: number;\n endTime?: number;\n}\n\nexport type RecorderMode = 'recording' | 'playback';\n\ninterface SpeakerGroup {\n speaker?: number;\n entries: TranscriptEntry[];\n}\n\nconst SPEAKER_LABELS: Record<number, string> = {\n 0: 'Pessoa 1',\n 1: 'Pessoa 2',\n 2: 'Pessoa 3',\n 3: 'Pessoa 4',\n};\n\n@Component({\n selector: 'ngx-jaimes-scribe-recorder',\n standalone: true,\n imports: [CommonModule],\n template: `\n <div class=\"scribe-recorder\">\n @if (mode() === 'playback') {\n <!-- Playback Mode -->\n <div class=\"scribe-playback\">\n @if (isLoadingSession()) {\n <div class=\"scribe-loading\">\n <svg class=\"scribe-icon scribe-icon--spinner\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"32\" stroke-linecap=\"round\"/>\n </svg>\n <span>Carregando sessão...</span>\n </div>\n } @else if (sessionData()) {\n <!-- Audio Player -->\n <div class=\"scribe-player\">\n <button\n class=\"scribe-btn scribe-btn--play\"\n (click)=\"togglePlayback()\"\n [attr.aria-label]=\"isPlaying() ? 'Pausar' : 'Reproduzir'\"\n >\n @if (isPlaying()) {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M6 19h4V5H6v14zm8-14v14h4V5h-4z\"/>\n </svg>\n } @else {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n }\n </button>\n\n <div class=\"scribe-timeline\">\n <input\n type=\"range\"\n class=\"scribe-timeline-slider\"\n [min]=\"0\"\n [max]=\"audioDuration()\"\n [value]=\"audioCurrentTime()\"\n step=\"0.1\"\n (input)=\"seekTo($event)\"\n aria-label=\"Posição do áudio\"\n />\n <div class=\"scribe-time\">\n {{ formatTimeDisplay(audioCurrentTime()) }} / {{ formatTimeDisplay(audioDuration()) }}\n </div>\n </div>\n\n <select\n class=\"scribe-speed\"\n [value]=\"playbackRate()\"\n (change)=\"setPlaybackRate($event)\"\n aria-label=\"Velocidade de reprodução\"\n >\n <option value=\"0.5\">0.5x</option>\n <option value=\"0.75\">0.75x</option>\n <option value=\"1\">1x</option>\n <option value=\"1.25\">1.25x</option>\n <option value=\"1.5\">1.5x</option>\n <option value=\"2\">2x</option>\n </select>\n </div>\n\n <!-- Transcription with Highlight -->\n <div class=\"scribe-transcript-playback\">\n @for (segment of segments(); track segment.id; let idx = $index) {\n <div\n class=\"scribe-segment\"\n [class.scribe-segment--active]=\"activeSegmentId() === segment.id\"\n [style.--speaker-color]=\"getSpeakerColor(segment.speaker)\"\n [attr.data-segment-id]=\"segment.id\"\n (click)=\"seekToSegment(segment)\"\n >\n @if (segment.speaker !== undefined && shouldShowSpeakerLabel(idx)) {\n <span class=\"scribe-speaker-label\" [class]=\"'scribe-speaker--' + segment.speaker\">\n {{ getSpeakerLabel(segment.speaker) }}\n </span>\n }\n\n <p class=\"scribe-segment-text\">\n @if (segment.words?.length) {\n @for (word of segment.words; track $index; let i = $index) {\n <span\n class=\"scribe-word\"\n [class.scribe-word--active]=\"activeSegmentId() === segment.id && activeWordIndex() === i\"\n (click)=\"seekToWord(word, $event)\"\n >{{ word.word }}</span>{{ ' ' }}\n }\n } @else {\n {{ segment.text }}\n }\n </p>\n </div>\n }\n @if (segments().length === 0) {\n <span class=\"scribe-placeholder\">Nenhuma transcrição disponível.</span>\n }\n </div>\n } @else {\n <div class=\"scribe-error\">\n <span>Não foi possível carregar a sessão.</span>\n </div>\n }\n </div>\n } @else {\n <!-- Recording Mode -->\n @if (isLoadingSession()) {\n <div class=\"scribe-loading\">\n <svg class=\"scribe-icon scribe-icon--spinner\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"32\" stroke-linecap=\"round\"/>\n </svg>\n <span>Carregando sessão...</span>\n </div>\n } @else {\n <div class=\"scribe-controls\">\n @if (!hasFinishedSession()) {\n <button\n class=\"scribe-btn scribe-btn--mic\"\n [class.scribe-btn--active]=\"isRecording() && !isPaused()\"\n [class.scribe-btn--paused]=\"isPaused()\"\n [class.scribe-btn--connecting]=\"connectionState() === 'connecting'\"\n [disabled]=\"connectionState() === 'connecting'\"\n (click)=\"toggleRecording()\"\n [attr.aria-label]=\"getMicButtonLabel()\"\n >\n @if (connectionState() === 'connecting') {\n <svg class=\"scribe-icon scribe-icon--spinner\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"32\" stroke-linecap=\"round\"/>\n </svg>\n } @else if (isPaused()) {\n <!-- Play icon when paused -->\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n } @else if (isRecording()) {\n <!-- Pause icon when recording -->\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M6 19h4V5H6v14zm8-14v14h4V5h-4z\"/>\n </svg>\n } @else {\n <!-- Mic icon when idle -->\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1-9c0-.55.45-1 1-1s1 .45 1 1v6c0 .55-.45 1-1 1s-1-.45-1-1V5z\"/>\n <path d=\"M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z\"/>\n </svg>\n }\n </button>\n\n <div class=\"scribe-level\" [class.scribe-level--active]=\"isRecording() && !isPaused()\">\n <div class=\"scribe-level__fill\" [style.width.%]=\"isPaused() ? 0 : audioLevel()\"></div>\n </div>\n\n <button\n class=\"scribe-btn scribe-btn--finish\"\n [disabled]=\"!isRecording() && !isPaused()\"\n (click)=\"finishSession()\"\n aria-label=\"Finalizar gravação\"\n >\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\">\n <path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>\n </svg>\n <span>Finalizar</span>\n </button>\n }\n\n @if (hasFinishedSession() && templates().length > 0) {\n <div class=\"scribe-generate-container\">\n <button\n class=\"scribe-btn scribe-btn--generate\"\n [disabled]=\"isGenerating()\"\n [attr.aria-expanded]=\"showTemplateMenu()\"\n aria-haspopup=\"menu\"\n (click)=\"toggleTemplateMenu()\"\n aria-label=\"Gerar resumo\"\n >\n @if (isGenerating()) {\n <svg class=\"scribe-icon scribe-icon--spinner\" viewBox=\"0 0 24 24\" width=\"20\" height=\"20\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"32\" stroke-linecap=\"round\"/>\n </svg>\n <span>Gerando...</span>\n } @else {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\">\n <path d=\"M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11zm-3-7h-2v2h-2v-2H9v-2h2V9h2v2h2v2z\"/>\n </svg>\n <span>Gerar Resumo</span>\n }\n </button>\n\n @if (showTemplateMenu()) {\n <div class=\"scribe-template-menu\" role=\"menu\">\n @for (template of templates(); track template.id) {\n <button\n class=\"scribe-template-item\"\n role=\"menuitem\"\n (click)=\"selectTemplate(template)\"\n >\n <span class=\"scribe-template-name\">{{ template.name }}</span>\n @if (template.description) {\n <span class=\"scribe-template-desc\">{{ template.description }}</span>\n }\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"scribe-transcript\" [class.scribe-transcript--empty]=\"speakerGroups().length === 0 && !partialText()\">\n @if (speakerGroups().length === 0 && !partialText()) {\n <span class=\"scribe-placeholder\">A transcrição aparecerá aqui...</span>\n } @else {\n @for (group of speakerGroups(); track $index) {\n <div class=\"scribe-speaker-block\" [attr.data-speaker]=\"group.speaker\">\n @if (group.speaker !== undefined && group.speaker !== null) {\n <span class=\"scribe-speaker-label\" [class]=\"'scribe-speaker--' + group.speaker\">\n {{ getSpeakerLabel(group.speaker) }}\n </span>\n }\n <div class=\"scribe-speaker-text\">\n @for (entry of group.entries; track entry.id) {\n <span class=\"scribe-text scribe-text--final\">{{ entry.text }} </span>\n }\n </div>\n </div>\n }\n @if (partialText()) {\n <div class=\"scribe-speaker-block scribe-speaker-block--partial\">\n @if (currentSpeaker() !== undefined && currentSpeaker() !== null) {\n <span class=\"scribe-speaker-label\" [class]=\"'scribe-speaker--' + currentSpeaker()\">\n {{ getSpeakerLabel(currentSpeaker()!) }}\n </span>\n }\n <div class=\"scribe-speaker-text\">\n <span class=\"scribe-text scribe-text--partial\">{{ partialText() }}</span>\n </div>\n </div>\n }\n }\n </div>\n }\n }\n </div>\n `,\n styles: [`\n :host {\n --scribe-primary: #4caf50;\n --scribe-primary-dark: #388e3c;\n --scribe-primary-light: #81c784;\n --scribe-danger: #f44336;\n --scribe-danger-dark: #d32f2f;\n --scribe-text-color: #212121;\n --scribe-text-partial: #9e9e9e;\n --scribe-font-family: inherit;\n --scribe-font-size: 1rem;\n --scribe-bg: #ffffff;\n --scribe-bg-transcript: #f5f5f5;\n --scribe-border-radius: 8px;\n --scribe-border-color: #e0e0e0;\n --scribe-level-bg: #e0e0e0;\n --scribe-level-fill: #4caf50;\n\n --scribe-speaker-0: #2196f3;\n --scribe-speaker-1: #9c27b0;\n --scribe-speaker-2: #ff9800;\n --scribe-speaker-3: #009688;\n\n display: block;\n font-family: var(--scribe-font-family);\n font-size: var(--scribe-font-size);\n }\n\n .scribe-recorder {\n background: var(--scribe-bg);\n border-radius: var(--scribe-border-radius);\n }\n\n .scribe-controls {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1rem;\n }\n\n .scribe-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem;\n border: none;\n border-radius: var(--scribe-border-radius);\n font-family: var(--scribe-font-family);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .scribe-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .scribe-btn--mic {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: var(--scribe-bg-transcript);\n color: var(--scribe-text-color);\n }\n\n .scribe-btn--mic:hover:not(:disabled) {\n background: var(--scribe-border-color);\n }\n\n .scribe-btn--mic.scribe-btn--active {\n background: var(--scribe-danger);\n color: white;\n animation: pulse-recording 1.5s ease-in-out infinite;\n }\n\n .scribe-btn--mic.scribe-btn--paused {\n background: var(--scribe-primary);\n color: white;\n }\n\n .scribe-btn--mic.scribe-btn--paused:hover:not(:disabled) {\n background: var(--scribe-primary-dark);\n }\n\n .scribe-btn--mic.scribe-btn--connecting {\n background: var(--scribe-primary-light);\n color: white;\n }\n\n .scribe-btn--finish {\n padding: 0.75rem 1.25rem;\n background: var(--scribe-primary);\n color: white;\n }\n\n .scribe-btn--finish:hover:not(:disabled) {\n background: var(--scribe-primary-dark);\n }\n\n .scribe-icon {\n flex-shrink: 0;\n }\n\n .scribe-icon--spinner {\n animation: spin 1s linear infinite;\n }\n\n .scribe-level {\n flex: 1;\n height: 8px;\n background: var(--scribe-level-bg);\n border-radius: 4px;\n overflow: hidden;\n opacity: 0.5;\n transition: opacity 0.2s ease;\n }\n\n .scribe-level--active {\n opacity: 1;\n }\n\n .scribe-level__fill {\n height: 100%;\n background: var(--scribe-level-fill);\n border-radius: 4px;\n transition: width 0.05s ease-out;\n }\n\n .scribe-transcript {\n min-height: 120px;\n max-height: 400px;\n overflow-y: auto;\n padding: 1rem;\n margin: 0 1rem 1rem;\n background: var(--scribe-bg-transcript);\n border-radius: var(--scribe-border-radius);\n line-height: 1.6;\n }\n\n .scribe-transcript--empty {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .scribe-placeholder {\n color: var(--scribe-text-partial);\n font-style: italic;\n }\n\n .scribe-speaker-block {\n margin-bottom: 0.75rem;\n padding-left: 0.5rem;\n border-left: 3px solid var(--scribe-border-color);\n }\n\n .scribe-speaker-block--partial {\n opacity: 0.7;\n }\n\n .scribe-speaker-block[data-speaker=\"0\"] {\n border-left-color: var(--scribe-speaker-0);\n }\n\n .scribe-speaker-block[data-speaker=\"1\"] {\n border-left-color: var(--scribe-speaker-1);\n }\n\n .scribe-speaker-block[data-speaker=\"2\"] {\n border-left-color: var(--scribe-speaker-2);\n }\n\n .scribe-speaker-block[data-speaker=\"3\"] {\n border-left-color: var(--scribe-speaker-3);\n }\n\n .scribe-speaker-label {\n display: inline-block;\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: 0.125rem 0.5rem;\n border-radius: 4px;\n margin-bottom: 0.25rem;\n color: white;\n background: var(--scribe-border-color);\n }\n\n .scribe-speaker--0 {\n background: var(--scribe-speaker-0);\n }\n\n .scribe-speaker--1 {\n background: var(--scribe-speaker-1);\n }\n\n .scribe-speaker--2 {\n background: var(--scribe-speaker-2);\n }\n\n .scribe-speaker--3 {\n background: var(--scribe-speaker-3);\n }\n\n .scribe-speaker-text {\n margin-top: 0.25rem;\n }\n\n .scribe-text {\n word-wrap: break-word;\n }\n\n .scribe-text--final {\n color: var(--scribe-text-color);\n }\n\n .scribe-text--partial {\n color: var(--scribe-text-partial);\n font-style: italic;\n }\n\n .scribe-generate-container {\n position: relative;\n margin-left: 0.5rem;\n }\n\n .scribe-btn--generate {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n background: var(--scribe-primary);\n color: white;\n border: none;\n border-radius: var(--scribe-border-radius);\n font-family: var(--scribe-font-family);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .scribe-btn--generate:hover:not(:disabled) {\n background: var(--scribe-primary-dark);\n }\n\n .scribe-btn--generate:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n }\n\n .scribe-template-menu {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 0.25rem;\n min-width: 220px;\n background: var(--scribe-bg);\n border: 1px solid var(--scribe-border-color);\n border-radius: var(--scribe-border-radius);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n z-index: 100;\n overflow: hidden;\n }\n\n .scribe-template-item {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n padding: 0.75rem 1rem;\n border: none;\n background: transparent;\n cursor: pointer;\n text-align: left;\n transition: background 0.15s ease;\n }\n\n .scribe-template-item:hover {\n background: var(--scribe-bg-transcript);\n }\n\n .scribe-template-item:not(:last-child) {\n border-bottom: 1px solid var(--scribe-border-color);\n }\n\n .scribe-template-name {\n font-weight: 500;\n color: var(--scribe-text-color);\n }\n\n .scribe-template-desc {\n font-size: 0.75rem;\n color: var(--scribe-text-partial);\n margin-top: 0.25rem;\n }\n\n @keyframes pulse-recording {\n 0%, 100% { box-shadow: 0 0 0 0 rgba(244, 67, 54, 0.4); }\n 50% { box-shadow: 0 0 0 8px rgba(244, 67, 54, 0); }\n }\n\n @keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n /* Playback Mode Styles */\n .scribe-playback {\n padding: 1rem;\n }\n\n .scribe-loading,\n .scribe-error {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 2rem;\n color: var(--scribe-text-partial);\n }\n\n .scribe-player {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1rem;\n background: var(--scribe-bg-transcript);\n border-radius: var(--scribe-border-radius);\n margin-bottom: 1rem;\n }\n\n .scribe-btn--play {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: var(--scribe-primary);\n color: white;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s ease;\n flex-shrink: 0;\n }\n\n .scribe-btn--play:hover {\n background: var(--scribe-primary-dark);\n }\n\n .scribe-timeline {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 0.25rem;\n }\n\n .scribe-timeline-slider {\n width: 100%;\n cursor: pointer;\n height: 6px;\n -webkit-appearance: none;\n appearance: none;\n background: var(--scribe-level-bg);\n border-radius: 3px;\n outline: none;\n }\n\n .scribe-timeline-slider::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 14px;\n height: 14px;\n background: var(--scribe-primary);\n border-radius: 50%;\n cursor: pointer;\n }\n\n .scribe-timeline-slider::-moz-range-thumb {\n width: 14px;\n height: 14px;\n background: var(--scribe-primary);\n border-radius: 50%;\n cursor: pointer;\n border: none;\n }\n\n .scribe-time {\n font-size: 0.75rem;\n color: var(--scribe-text-partial);\n }\n\n .scribe-speed {\n padding: 0.375rem 0.5rem;\n border-radius: 4px;\n border: 1px solid var(--scribe-border-color);\n background: var(--scribe-bg);\n font-size: 0.875rem;\n cursor: pointer;\n }\n\n .scribe-transcript-playback {\n max-height: 400px;\n overflow-y: auto;\n scroll-behavior: smooth;\n padding: 0.5rem;\n }\n\n .scribe-segment {\n padding: 0.75rem 1rem;\n margin-bottom: 0.5rem;\n border-left: 3px solid var(--speaker-color, var(--scribe-border-color));\n background: var(--scribe-bg);\n border-radius: 0 var(--scribe-border-radius) var(--scribe-border-radius) 0;\n cursor: pointer;\n transition: background 0.2s ease;\n }\n\n .scribe-segment:hover {\n background: var(--scribe-bg-transcript);\n }\n\n .scribe-segment--active {\n background: rgba(76, 175, 80, 0.1);\n border-left-color: var(--scribe-primary);\n }\n\n .scribe-segment-text {\n margin: 0.25rem 0 0 0;\n line-height: 1.6;\n }\n\n .scribe-word {\n transition: background 0.15s ease, color 0.15s ease;\n padding: 0 1px;\n border-radius: 2px;\n }\n\n .scribe-word:hover {\n background: rgba(0, 0, 0, 0.05);\n cursor: pointer;\n }\n\n .scribe-word--active {\n background: var(--scribe-primary);\n color: white;\n }\n `],\n})\nexport class RecorderComponent implements OnDestroy {\n private audioCapture = inject(AudioCaptureService);\n private socket = inject(ScribeSocketService);\n private elementRef = inject(ElementRef);\n private subscriptions: Subscription[] = [];\n private entryIdCounter = 0;\n private generateAbortController: AbortController | null = null;\n\n @HostListener('document:click', ['$event'])\n onDocumentClick(event: MouseEvent): void {\n if (!this.showTemplateMenu()) return;\n const target = event.target as HTMLElement;\n if (!this.elementRef.nativeElement.contains(target)) {\n this.showTemplateMenu.set(false);\n }\n }\n\n wsUrl = input<string>('');\n token = input<string>('');\n speakerLabels = input<Record<number, string>>({});\n premium = input<boolean>(false);\n templates = input<TemplateOption[]>([]);\n lambdaUrl = input<string>('');\n\n sessionId = input<string | undefined>();\n apiUrl = input<string>('');\n resumeSessionId = input<string | undefined>();\n\n sessionStarted = output<string>();\n sessionFinished = output<{ transcript: string; entries: TranscriptEntry[] }>();\n error = output<Error>();\n documentGenerated = output<GeneratedDocument>();\n generationError = output<Error>();\n\n isRecording = signal(false);\n isPaused = signal(false);\n audioLevel = signal(0);\n connectionState = signal<ConnectionState>('disconnected');\n entries = signal<TranscriptEntry[]>([]);\n partialText = signal('');\n currentSpeaker = signal<number | undefined>(undefined);\n showTemplateMenu = signal(false);\n isGenerating = signal(false);\n lastSessionId = signal<string | null>(null);\n\n isPlaying = signal(false);\n isLoadingSession = signal(false);\n audioCurrentTime = signal(0);\n audioDuration = signal(0);\n playbackRate = signal(1);\n sessionData = signal<SessionPlaybackData | null>(null);\n activeSegmentId = signal<string | null>(null);\n activeWordIndex = signal<number | null>(null);\n\n private audioElement: HTMLAudioElement | null = null;\n private audioBlobUrl: string | null = null;\n\n mode = computed<RecorderMode>(() =>\n this.sessionId() ? 'playback' : 'recording'\n );\n\n segments = computed(() =>\n this.sessionData()?.transcription.segments ?? []\n );\n\n hasFinishedSession = computed(() =>\n this.lastSessionId() !== null &&\n !this.isRecording() &&\n !this.isPaused()\n );\n\n speakerGroups = computed<SpeakerGroup[]>(() => {\n const allEntries = this.entries();\n if (allEntries.length === 0) return [];\n\n const groups: SpeakerGroup[] = [];\n let currentGroup: SpeakerGroup | null = null;\n\n for (const entry of allEntries) {\n if (!currentGroup || currentGroup.speaker !== entry.speaker) {\n currentGroup = { speaker: entry.speaker, entries: [] };\n groups.push(currentGroup);\n }\n currentGroup.entries.push(entry);\n }\n\n return groups;\n });\n\n constructor() {\n this.subscriptions.push(\n this.audioCapture.audioLevel$.subscribe((level) => {\n this.audioLevel.set(level);\n }),\n this.socket.connectionState$.subscribe((state) => {\n this.connectionState.set(state);\n }),\n this.socket.transcription$.subscribe((event) => {\n this.handleTranscription(event);\n }),\n this.socket.error$.subscribe((err) => {\n this.error.emit(err);\n }),\n this.audioCapture.error$.subscribe((err) => {\n this.error.emit(err);\n }),\n this.audioCapture.audioChunk$.subscribe(({ data, isSilence }) => {\n this.socket.sendAudioChunk(data, isSilence);\n })\n );\n\n effect(() => {\n const sid = this.sessionId();\n const api = this.apiUrl();\n if (sid && api && this.mode() === 'playback') {\n this.loadSession();\n }\n });\n\n effect(() => {\n const resumeId = this.resumeSessionId();\n const api = this.apiUrl();\n if (resumeId && api && this.mode() === 'recording') {\n this.resumeSession(resumeId);\n }\n });\n }\n\n ngOnDestroy(): void {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.generateAbortController?.abort();\n this.cleanup();\n this.cleanupPlayback();\n }\n\n private audioEventHandlers: {\n loadedmetadata?: () => void;\n timeupdate?: () => void;\n ended?: () => void;\n } = {};\n\n private cleanupPlayback(): void {\n if (this.audioElement) {\n this.audioElement.pause();\n if (this.audioEventHandlers.loadedmetadata) {\n this.audioElement.removeEventListener('loadedmetadata', this.audioEventHandlers.loadedmetadata);\n }\n if (this.audioEventHandlers.timeupdate) {\n this.audioElement.removeEventListener('timeupdate', this.audioEventHandlers.timeupdate);\n }\n if (this.audioEventHandlers.ended) {\n this.audioElement.removeEventListener('ended', this.audioEventHandlers.ended);\n }\n this.audioEventHandlers = {};\n this.audioElement = null;\n }\n if (this.audioBlobUrl) {\n URL.revokeObjectURL(this.audioBlobUrl);\n this.audioBlobUrl = null;\n }\n }\n\n getSpeakerLabel(speaker: number): string {\n const customLabels = this.speakerLabels();\n if (customLabels[speaker]) {\n return customLabels[speaker];\n }\n return SPEAKER_LABELS[speaker] || `Pessoa ${speaker + 1}`;\n }\n\n shouldShowSpeakerLabel(segmentIndex: number): boolean {\n const segs = this.segments();\n if (segmentIndex === 0) return true;\n const currentSpeaker = segs[segmentIndex]?.speaker;\n const previousSpeaker = segs[segmentIndex - 1]?.speaker;\n return currentSpeaker !== previousSpeaker;\n }\n\n getMicButtonLabel(): string {\n if (this.isPaused()) {\n return 'Retomar gravação';\n }\n if (this.isRecording()) {\n return 'Pausar gravação';\n }\n return 'Iniciar gravação';\n }\n\n async toggleRecording(): Promise<void> {\n if (this.isPaused()) {\n this.resumeRecording();\n } else if (this.isRecording()) {\n this.pauseRecording();\n } else {\n await this.startRecording();\n }\n }\n\n pauseRecording(): void {\n if (!this.isRecording() || this.isPaused()) return;\n this.audioCapture.pauseCapture();\n this.isPaused.set(true);\n }\n\n resumeRecording(): void {\n if (!this.isPaused()) return;\n this.audioCapture.resumeCapture();\n this.isPaused.set(false);\n }\n\n async finishSession(): Promise<void> {\n if (!this.isRecording() && !this.isPaused()) return;\n\n const sessionId = this.socket.getSessionId();\n\n await this.stopRecording();\n\n const allEntries = this.entries();\n const fullTranscript = allEntries.map((e) => e.text).join(' ');\n\n this.sessionFinished.emit({ transcript: fullTranscript, entries: allEntries });\n\n this.partialText.set('');\n this.currentSpeaker.set(undefined);\n\n this.lastSessionId.set(sessionId);\n }\n\n toggleTemplateMenu(): void {\n this.showTemplateMenu.update((v) => !v);\n }\n\n async selectTemplate(template: TemplateOption): Promise<void> {\n if (this.isGenerating()) return;\n\n this.showTemplateMenu.set(false);\n\n const lambdaUrl = this.lambdaUrl();\n if (!lambdaUrl) {\n this.generationError.emit(new Error('Lambda URL not provided'));\n return;\n }\n\n const sessionId = this.lastSessionId();\n if (!sessionId) {\n this.generationError.emit(new Error('No session available'));\n return;\n }\n\n this.generateAbortController?.abort();\n this.generateAbortController = new AbortController();\n\n this.isGenerating.set(true);\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n const token = this.token();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${lambdaUrl}/generate`, {\n method: 'POST',\n headers,\n signal: this.generateAbortController.signal,\n body: JSON.stringify({\n sessionId,\n outputSchema: template.content,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.error || `HTTP ${response.status}`);\n }\n\n const result = await response.json();\n\n this.documentGenerated.emit({\n sessionId,\n templateId: template.id,\n content: result.content,\n generatedAt: result.generatedAt,\n });\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') return;\n this.generationError.emit(err instanceof Error ? err : new Error(String(err)));\n } finally {\n this.isGenerating.set(false);\n }\n }\n\n async loadSession(): Promise<void> {\n const sid = this.sessionId();\n const api = this.apiUrl();\n\n if (!sid || !api) return;\n\n this.isLoadingSession.set(true);\n\n try {\n const headers: Record<string, string> = {};\n const token = this.token();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${api}/session/${sid}`, { headers });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data: SessionPlaybackData = await response.json();\n this.sessionData.set(data);\n\n await this.loadAudio(data.audioUrl);\n } catch (err) {\n this.error.emit(err instanceof Error ? err : new Error(String(err)));\n } finally {\n this.isLoadingSession.set(false);\n }\n }\n\n async resumeSession(sessionId: string): Promise<void> {\n const api = this.apiUrl();\n if (!api) return;\n\n this.isLoadingSession.set(true);\n\n try {\n const headers: Record<string, string> = {};\n const token = this.token();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${api}/session/${sessionId}`, { headers });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data: SessionPlaybackData = await response.json();\n\n const entries: TranscriptEntry[] = data.transcription.segments.map((seg, idx) => ({\n id: idx + 1,\n text: seg.text,\n speaker: seg.speaker,\n isFinal: true,\n startTime: seg.startTime,\n endTime: seg.endTime,\n }));\n\n this.entryIdCounter = entries.length;\n this.entries.set(entries);\n this.lastSessionId.set(sessionId);\n } catch (err) {\n this.error.emit(err instanceof Error ? err : new Error(String(err)));\n } finally {\n this.isLoadingSession.set(false);\n }\n }\n\n private async loadAudio(pcmUrl: string): Promise<void> {\n this.cleanupPlayback();\n\n const response = await fetch(pcmUrl);\n if (!response.ok) {\n throw new Error(`Failed to load audio: HTTP ${response.status}`);\n }\n\n const pcmData = await response.arrayBuffer();\n\n const wavData = pcmToWav(pcmData);\n this.audioBlobUrl = createAudioBlobUrl(wavData);\n\n this.audioElement = new Audio(this.audioBlobUrl);\n\n this.audioEventHandlers.loadedmetadata = () => {\n this.audioDuration.set(this.audioElement!.duration);\n };\n this.audioEventHandlers.timeupdate = () => {\n this.audioCurrentTime.set(this.audioElement!.currentTime);\n this.updateActiveSegment();\n };\n this.audioEventHandlers.ended = () => {\n this.isPlaying.set(false);\n };\n\n this.audioElement.addEventListener('loadedmetadata', this.audioEventHandlers.loadedmetadata);\n this.audioElement.addEventListener('timeupdate', this.audioEventHandlers.timeupdate);\n this.audioElement.addEventListener('ended', this.audioEventHandlers.ended);\n }\n\n togglePlayback(): void {\n if (!this.audioElement) return;\n\n if (this.isPlaying()) {\n this.audioElement.pause();\n this.isPlaying.set(false);\n } else {\n this.audioElement.play();\n this.isPlaying.set(true);\n }\n }\n\n seekTo(event: Event): void {\n const input = event.target as HTMLInputElement | null;\n if (!input) return;\n const time = parseFloat(input.value);\n if (this.audioElement && !isNaN(time)) {\n this.audioElement.currentTime = time;\n this.audioCurrentTime.set(time);\n }\n }\n\n setPlaybackRate(event: Event): void {\n const select = event.target as HTMLSelectElement | null;\n if (!select) return;\n const rate = parseFloat(select.value);\n if (isNaN(rate)) return;\n this.playbackRate.set(rate);\n if (this.audioElement) {\n this.audioElement.playbackRate = rate;\n }\n }\n\n seekToSegment(segment: TranscriptSegment): void {\n if (this.audioElement) {\n this.audioElement.currentTime = segment.startTime;\n this.audioCurrentTime.set(segment.startTime);\n if (!this.isPlaying()) {\n this.togglePlayback();\n }\n }\n }\n\n seekToWord(word: TranscriptionWord, event: Event): void {\n event.stopPropagation();\n if (this.audioElement) {\n this.audioElement.currentTime = word.start;\n this.audioCurrentTime.set(word.start);\n if (!this.isPlaying()) {\n this.togglePlayback();\n }\n }\n }\n\n formatTimeDisplay(seconds: number): string {\n return formatTime(seconds);\n }\n\n getSpeakerColor(speaker: number | undefined): string {\n if (speaker === undefined) return 'var(--scribe-border-color)';\n const colors = [\n 'var(--scribe-speaker-0)',\n 'var(--scribe-speaker-1)',\n 'var(--scribe-speaker-2)',\n 'var(--scribe-speaker-3)',\n ];\n return colors[speaker % colors.length];\n }\n\n private updateActiveSegment(): void {\n const time = this.audioCurrentTime();\n const segs = this.segments();\n\n const seg = segs.find((s) => time >= s.startTime && time <= s.endTime);\n this.activeSegmentId.set(seg?.id ?? null);\n\n if (seg?.words) {\n const wordIdx = seg.words.findIndex((w) => time >= w.start && time <= w.end);\n this.activeWordIndex.set(wordIdx >= 0 ? wordIdx : null);\n } else {\n this.activeWordIndex.set(null);\n }\n\n this.scrollToActiveSegment();\n }\n\n private scrollToActiveSegment(): void {\n const activeId = this.activeSegmentId();\n if (!activeId) return;\n\n const container = this.elementRef.nativeElement.querySelector('.scribe-transcript-playback');\n const activeEl = container?.querySelector(`[data-segment-id=\"${activeId}\"]`);\n\n if (activeEl && container) {\n const containerRect = container.getBoundingClientRect();\n const activeRect = activeEl.getBoundingClientRect();\n\n if (activeRect.top < containerRect.top || activeRect.bottom > containerRect.bottom) {\n activeEl.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }\n }\n\n private async startRecording(): Promise<void> {\n try {\n await this.socket.connect(this.wsUrl(), this.token(), this.premium());\n await this.audioCapture.startCapture();\n this.isRecording.set(true);\n this.isPaused.set(false);\n\n const sessionId = this.socket.getSessionId();\n if (sessionId) {\n this.sessionStarted.emit(sessionId);\n }\n } catch (err) {\n this.error.emit(err instanceof Error ? err : new Error('Failed to start recording'));\n await this.cleanup();\n }\n }\n\n private async stopRecording(): Promise<void> {\n await this.audioCapture.stopCapture();\n this.socket.disconnect();\n this.isRecording.set(false);\n this.isPaused.set(false);\n }\n\n private async cleanup(): Promise<void> {\n await this.audioCapture.stopCapture();\n this.socket.disconnect();\n this.isRecording.set(false);\n this.isPaused.set(false);\n }\n\n private handleTranscription(event: TranscriptionEvent): void {\n if (!event.transcript) return;\n\n if (event.type === 'final') {\n const entry: TranscriptEntry = {\n id: ++this.entryIdCounter,\n text: event.transcript,\n speaker: event.speaker,\n isFinal: true,\n startTime: event.start,\n endTime: event.end,\n };\n\n this.entries.update((entries) => [...entries, entry]);\n this.partialText.set('');\n this.currentSpeaker.set(undefined);\n } else if (event.type === 'partial') {\n this.partialText.set(event.transcript);\n this.currentSpeaker.set(event.speaker);\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["DEFAULT_CONFIG"],"mappings":"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"}
1
+ {"version":3,"file":"medc-com-br-ngx-jaimes-scribe.mjs","sources":["../../../libs/ngx-jaimes-scribe/src/lib/services/vad.service.ts","../../../libs/ngx-jaimes-scribe/src/lib/services/audio-capture.service.ts","../../../libs/ngx-jaimes-scribe/src/lib/services/scribe-socket.service.ts","../../../libs/ngx-jaimes-scribe/src/lib/services/speaker-identification.service.ts","../../../libs/ngx-jaimes-scribe/src/lib/utils/pcm-to-wav.ts","../../../libs/ngx-jaimes-scribe/src/lib/services/playback.service.ts","../../../libs/ngx-jaimes-scribe/src/lib/components/recorder/recorder.component.ts","../../../libs/ngx-jaimes-scribe/src/medc-com-br-ngx-jaimes-scribe.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\nexport type VadState = 'idle' | 'speech' | 'silence_pending' | 'silence';\n\nexport interface VadConfig {\n speechThreshold: number;\n silenceThreshold: number;\n silenceDebounceMs: number;\n}\n\nconst DEFAULT_CONFIG: VadConfig = {\n speechThreshold: 8,\n silenceThreshold: 3,\n silenceDebounceMs: 1500,\n};\n\n@Injectable({ providedIn: 'root' })\nexport class VadService {\n private state: VadState = 'idle';\n private silenceStartTime: number | null = null;\n private config = { ...DEFAULT_CONFIG };\n\n readonly state$ = new BehaviorSubject<VadState>('idle');\n\n analyzeLevel(level: number): { isSilence: boolean } {\n const now = Date.now();\n\n if (level >= this.config.speechThreshold) {\n this.state = 'speech';\n this.silenceStartTime = null;\n this.state$.next('speech');\n return { isSilence: false };\n }\n\n if (level < this.config.silenceThreshold) {\n if (this.state === 'speech') {\n this.silenceStartTime = now;\n this.state = 'silence_pending';\n } else if (this.state === 'silence_pending' && this.silenceStartTime) {\n if (now - this.silenceStartTime >= this.config.silenceDebounceMs) {\n this.state = 'silence';\n this.state$.next('silence');\n }\n }\n } else {\n if (this.state === 'silence_pending') {\n this.state = 'speech';\n this.silenceStartTime = null;\n }\n }\n\n return { isSilence: this.state === 'silence' };\n }\n\n reset(): void {\n this.state = 'idle';\n this.silenceStartTime = null;\n this.state$.next('idle');\n }\n\n getState(): VadState {\n return this.state;\n }\n}\n","import { Injectable, InjectionToken, inject, NgZone } from '@angular/core';\nimport { Subject, Observable, BehaviorSubject } from 'rxjs';\nimport { VadService } from './vad.service';\n\nexport interface AudioCaptureConfig {\n workletUrl: string;\n levelUpdateInterval: number;\n}\n\nexport const AUDIO_CAPTURE_CONFIG = new InjectionToken<AudioCaptureConfig>('AUDIO_CAPTURE_CONFIG');\n\nconst DEFAULT_CONFIG: AudioCaptureConfig = {\n workletUrl: '/assets/pcm-processor.js',\n levelUpdateInterval: 50,\n};\n\nexport interface AudioChunk {\n data: ArrayBuffer;\n isSilence: boolean;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class AudioCaptureService {\n private config: AudioCaptureConfig;\n private ngZone: NgZone;\n private vadService: VadService;\n private audioContext: AudioContext | null = null;\n private workletNode: AudioWorkletNode | null = null;\n private analyserNode: AnalyserNode | null = null;\n private source: MediaStreamAudioSourceNode | null = null;\n private stream: MediaStream | null = null;\n private workletRegistered = false;\n private levelInterval: ReturnType<typeof setInterval> | null = null;\n private paused = false;\n\n private audioChunkSubject = new Subject<AudioChunk>();\n private audioLevelSubject = new BehaviorSubject<number>(0);\n private errorSubject = new Subject<Error>();\n\n audioChunk$: Observable<AudioChunk> = this.audioChunkSubject.asObservable();\n audioLevel$: Observable<number> = this.audioLevelSubject.asObservable();\n error$: Observable<Error> = this.errorSubject.asObservable();\n\n constructor() {\n const injectedConfig = inject(AUDIO_CAPTURE_CONFIG, { optional: true });\n this.config = injectedConfig ?? DEFAULT_CONFIG;\n this.ngZone = inject(NgZone);\n this.vadService = inject(VadService);\n }\n\n async startCapture(): Promise<void> {\n try {\n this.stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n channelCount: 1,\n echoCancellation: true,\n noiseSuppression: true,\n },\n });\n\n this.audioContext = new AudioContext();\n\n if (!this.workletRegistered) {\n await this.audioContext.audioWorklet.addModule(this.config.workletUrl);\n this.workletRegistered = true;\n }\n\n this.workletNode = new AudioWorkletNode(this.audioContext, 'pcm-processor', {\n processorOptions: {\n inputSampleRate: this.audioContext.sampleRate,\n },\n });\n\n this.workletNode.port.onmessage = (event: MessageEvent<ArrayBuffer>) => {\n if (!this.paused) {\n const level = this.getAudioLevel();\n const { isSilence } = this.vadService.analyzeLevel(level);\n this.audioChunkSubject.next({ data: event.data, isSilence });\n }\n };\n\n this.analyserNode = this.audioContext.createAnalyser();\n this.analyserNode.fftSize = 256;\n this.analyserNode.smoothingTimeConstant = 0.8;\n\n this.source = this.audioContext.createMediaStreamSource(this.stream);\n this.source.connect(this.analyserNode);\n this.source.connect(this.workletNode);\n\n this.startLevelMonitoring();\n } catch (error) {\n const err = error instanceof Error ? error : new Error('Failed to start audio capture');\n this.errorSubject.next(err);\n throw err;\n }\n }\n\n async stopCapture(): Promise<void> {\n this.stopLevelMonitoring();\n this.paused = false;\n this.vadService.reset();\n\n if (this.workletNode) {\n this.workletNode.port.close();\n this.workletNode.disconnect();\n this.workletNode = null;\n }\n\n if (this.analyserNode) {\n this.analyserNode.disconnect();\n this.analyserNode = null;\n }\n\n if (this.source) {\n this.source.disconnect();\n this.source = null;\n }\n\n if (this.audioContext) {\n await this.audioContext.close();\n this.audioContext = null;\n this.workletRegistered = false;\n }\n\n if (this.stream) {\n this.stream.getTracks().forEach((track) => track.stop());\n this.stream = null;\n }\n\n this.audioLevelSubject.next(0);\n }\n\n pauseCapture(): void {\n if (this.isCapturing() && !this.paused) {\n this.paused = true;\n }\n }\n\n resumeCapture(): void {\n if (this.isCapturing() && this.paused) {\n this.paused = false;\n }\n }\n\n isCapturing(): boolean {\n return this.workletNode !== null && this.stream !== null;\n }\n\n isPaused(): boolean {\n return this.paused;\n }\n\n getSampleRate(): number | null {\n return this.audioContext?.sampleRate ?? null;\n }\n\n private startLevelMonitoring(): void {\n this.stopLevelMonitoring();\n\n this.ngZone.runOutsideAngular(() => {\n this.levelInterval = setInterval(() => {\n const level = this.getAudioLevel();\n this.ngZone.run(() => {\n this.audioLevelSubject.next(level);\n });\n }, this.config.levelUpdateInterval);\n });\n }\n\n private stopLevelMonitoring(): void {\n if (this.levelInterval) {\n clearInterval(this.levelInterval);\n this.levelInterval = null;\n }\n }\n\n private getAudioLevel(): number {\n if (!this.analyserNode) {\n return 0;\n }\n\n const dataArray = new Uint8Array(this.analyserNode.frequencyBinCount);\n this.analyserNode.getByteFrequencyData(dataArray);\n\n const sum = dataArray.reduce((acc, val) => acc + val, 0);\n const average = sum / dataArray.length;\n\n return Math.round((average / 255) * 100);\n }\n}\n","import { Injectable, InjectionToken, inject, NgZone } from '@angular/core';\nimport { BehaviorSubject, Subject, Observable } from 'rxjs';\nimport type { TranscriptionEvent } from '@medc-com-br/jaimes-shared';\n\nexport type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n\nexport interface ScribeSocketConfig {\n reconnectAttempts: number;\n reconnectBaseDelay: number;\n chunkBufferInterval: number;\n}\n\nexport const SCRIBE_SOCKET_CONFIG = new InjectionToken<ScribeSocketConfig>('SCRIBE_SOCKET_CONFIG');\n\nconst DEFAULT_CONFIG: ScribeSocketConfig = {\n reconnectAttempts: 5,\n reconnectBaseDelay: 1000,\n chunkBufferInterval: 250,\n};\n\n@Injectable({ providedIn: 'root' })\nexport class ScribeSocketService {\n private config: ScribeSocketConfig;\n private ngZone: NgZone;\n private ws: WebSocket | null = null;\n private wsUrl: string | null = null;\n private token: string | null = null;\n private premium = false;\n private reconnectAttempt = 0;\n private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n private intentionalClose = false;\n\n private chunkBuffer: string[] = [];\n private sendInterval: ReturnType<typeof setInterval> | null = null;\n private keepaliveInterval: ReturnType<typeof setInterval> | null = null;\n private currentlyInSilence = false;\n\n private connectionStateSubject = new BehaviorSubject<ConnectionState>('disconnected');\n private transcriptionSubject = new Subject<TranscriptionEvent>();\n private errorSubject = new Subject<Error>();\n private sessionIdSubject = new BehaviorSubject<string | null>(null);\n\n connectionState$: Observable<ConnectionState> = this.connectionStateSubject.asObservable();\n transcription$: Observable<TranscriptionEvent> = this.transcriptionSubject.asObservable();\n error$: Observable<Error> = this.errorSubject.asObservable();\n sessionId$: Observable<string | null> = this.sessionIdSubject.asObservable();\n\n constructor() {\n const injectedConfig = inject(SCRIBE_SOCKET_CONFIG, { optional: true });\n this.config = injectedConfig ?? DEFAULT_CONFIG;\n this.ngZone = inject(NgZone);\n }\n\n async connect(url: string, token: string, premium = false): Promise<void> {\n if (this.connectionStateSubject.getValue() === 'connecting') {\n throw new Error('Connection already in progress');\n }\n\n if (this.isConnected()) {\n this.disconnect();\n }\n\n this.clearReconnectTimeout();\n this.wsUrl = url;\n this.token = token;\n this.premium = premium;\n this.intentionalClose = false;\n this.reconnectAttempt = 0;\n\n return this.createConnection();\n }\n\n disconnect(): void {\n this.intentionalClose = true;\n this.flushAndStopBuffering();\n this.clearReconnectTimeout();\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.close(1000, 'Client disconnect');\n }\n this.ws = null;\n\n this.connectionStateSubject.next('disconnected');\n this.sessionIdSubject.next(null);\n }\n\n sendAudioChunk(chunk: ArrayBuffer, isSilence: boolean): void {\n const message = JSON.stringify({\n type: 'audio',\n isSilence,\n data: this.arrayBufferToBase64(chunk),\n });\n this.chunkBuffer.push(message);\n\n if (isSilence && !this.currentlyInSilence) {\n this.currentlyInSilence = true;\n this.startKeepaliveInterval();\n } else if (!isSilence && this.currentlyInSilence) {\n this.currentlyInSilence = false;\n this.stopKeepaliveInterval();\n }\n }\n\n private startKeepaliveInterval(): void {\n this.stopKeepaliveInterval();\n this.keepaliveInterval = setInterval(() => {\n if (this.isConnected()) {\n this.ws!.send(JSON.stringify({ type: 'keepalive' }));\n }\n }, 3000);\n }\n\n private stopKeepaliveInterval(): void {\n if (this.keepaliveInterval) {\n clearInterval(this.keepaliveInterval);\n this.keepaliveInterval = null;\n }\n }\n\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n getSessionId(): string | null {\n return this.sessionIdSubject.getValue();\n }\n\n private createConnection(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.wsUrl) {\n reject(new Error('WebSocket URL is required'));\n return;\n }\n\n this.connectionStateSubject.next('connecting');\n const params = new URLSearchParams({ premium: String(this.premium) });\n if (this.token) {\n params.set('token', this.token);\n }\n const url = `${this.wsUrl}?${params.toString()}`;\n\n this.ws = new WebSocket(url);\n this.ws.binaryType = 'arraybuffer';\n\n this.ws.onopen = () => {\n this.ngZone.run(() => {\n this.reconnectAttempt = 0;\n this.connectionStateSubject.next('connected');\n this.startBuffering();\n resolve();\n });\n };\n\n this.ws.onerror = () => {\n this.ngZone.run(() => {\n const error = new Error('WebSocket connection error');\n this.errorSubject.next(error);\n if (this.connectionStateSubject.getValue() === 'connecting') {\n reject(error);\n }\n });\n };\n\n this.ws.onmessage = (event) => {\n this.ngZone.run(() => {\n try {\n const data = JSON.parse(event.data);\n if (data.type === 'connected' && data.sessionId) {\n this.sessionIdSubject.next(data.sessionId);\n }\n this.transcriptionSubject.next(data as TranscriptionEvent);\n } catch (e) {\n const error = new Error(`Failed to parse WebSocket message: ${e instanceof Error ? e.message : String(e)}`);\n console.error(error.message);\n this.errorSubject.next(error);\n }\n });\n };\n\n this.ws.onclose = (event) => {\n this.ngZone.run(() => {\n this.stopBuffering();\n\n if (!this.intentionalClose && event.code !== 1000) {\n this.attemptReconnect();\n } else {\n this.connectionStateSubject.next('disconnected');\n this.sessionIdSubject.next(null);\n }\n });\n };\n });\n }\n\n private attemptReconnect(): void {\n if (this.reconnectAttempt >= this.config.reconnectAttempts) {\n this.connectionStateSubject.next('disconnected');\n this.errorSubject.next(new Error('Max reconnection attempts reached'));\n return;\n }\n\n this.connectionStateSubject.next('reconnecting');\n const delay = this.config.reconnectBaseDelay * Math.pow(2, this.reconnectAttempt);\n this.reconnectAttempt++;\n\n this.reconnectTimeout = setTimeout(() => {\n this.createConnection().catch(() => {});\n }, delay);\n }\n\n private clearReconnectTimeout(): void {\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n }\n\n private startBuffering(): void {\n this.stopBuffering();\n\n this.sendInterval = setInterval(() => {\n if (this.chunkBuffer.length > 0 && this.isConnected()) {\n for (const msg of this.chunkBuffer) {\n this.ws!.send(msg);\n }\n this.chunkBuffer = [];\n }\n }, this.config.chunkBufferInterval);\n }\n\n private flushAndStopBuffering(): void {\n if (this.sendInterval) {\n clearInterval(this.sendInterval);\n this.sendInterval = null;\n }\n\n if (this.chunkBuffer.length > 0 && this.isConnected()) {\n for (const msg of this.chunkBuffer) {\n this.ws!.send(msg);\n }\n }\n this.chunkBuffer = [];\n this.stopKeepaliveInterval();\n this.currentlyInSilence = false;\n }\n\n private stopBuffering(): void {\n if (this.sendInterval) {\n clearInterval(this.sendInterval);\n this.sendInterval = null;\n }\n this.chunkBuffer = [];\n }\n\n}\n","import { Injectable, signal, computed } from '@angular/core';\nimport type {\n SpeakerMapping,\n SpeakerRole,\n IdentifySpeakersResponse,\n SpeakerStats,\n} from '@medc-com-br/jaimes-shared';\nimport { ROLE_LABELS } from '@medc-com-br/jaimes-shared';\n\nexport const MIN_CHARS_FOR_IDENTIFICATION = 100;\nexport const MAX_SAMPLE_SIZE = 20;\nexport const LOW_CONFIDENCE_THRESHOLD = 0.7;\nexport const IDENTIFICATION_DEBOUNCE_MS = 2000;\n\nconst DEFAULT_SPEAKER_LABELS: Record<number, string> = {\n 0: 'Pessoa 1',\n 1: 'Pessoa 2',\n 2: 'Pessoa 3',\n 3: 'Pessoa 4',\n};\n\ninterface TranscriptEntry {\n id: number;\n text: string;\n speaker?: number;\n isFinal: boolean;\n}\n\n@Injectable()\nexport class SpeakerIdentificationService {\n readonly speakerMapping = signal<SpeakerMapping>({});\n readonly identifiedSpeakers = signal<Set<number>>(new Set());\n readonly isIdentifying = signal(false);\n readonly editingSpeaker = signal<number | null>(null);\n\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n hasLowConfidence(speaker: number): boolean {\n const mapping = this.speakerMapping()[speaker.toString()];\n return (mapping?.confidence ?? 1) < LOW_CONFIDENCE_THRESHOLD;\n }\n\n getLabel(\n speaker: number,\n customLabels: Record<number, string>,\n doctorName: string,\n patientName: string,\n companionName: string\n ): string {\n if (customLabels[speaker]) {\n return customLabels[speaker];\n }\n\n const mapping = this.speakerMapping()[speaker.toString()];\n if (mapping) {\n switch (mapping.role) {\n case 'doctor':\n return doctorName || ROLE_LABELS.doctor;\n case 'patient':\n return patientName || ROLE_LABELS.patient;\n case 'companion':\n return companionName || ROLE_LABELS.companion;\n default:\n return ROLE_LABELS[mapping.role] || `Pessoa ${speaker + 1}`;\n }\n }\n\n return DEFAULT_SPEAKER_LABELS[speaker] || `Pessoa ${speaker + 1}`;\n }\n\n getSpeakerStats(entries: TranscriptEntry[]): SpeakerStats {\n const charCount: Record<number, number> = {};\n const speakers = new Set<number>();\n\n for (const entry of entries) {\n if (entry.speaker !== undefined && entry.isFinal) {\n speakers.add(entry.speaker);\n charCount[entry.speaker] = (charCount[entry.speaker] || 0) + entry.text.length;\n }\n }\n\n return {\n speakers: Array.from(speakers),\n uniqueSpeakers: speakers.size,\n charCount,\n };\n }\n\n shouldIdentify(entries: TranscriptEntry[]): boolean {\n if (this.isIdentifying()) return false;\n\n const stats = this.getSpeakerStats(entries);\n const identifiedSet = this.identifiedSpeakers();\n\n const hasNewSpeaker = stats.speakers.some(\n (s) => !identifiedSet.has(s) && stats.charCount[s] >= MIN_CHARS_FOR_IDENTIFICATION\n );\n\n const allSpeakersHaveEnoughContext = stats.speakers.every(\n (s) => stats.charCount[s] >= MIN_CHARS_FOR_IDENTIFICATION\n );\n\n return (\n stats.uniqueSpeakers >= 2 &&\n allSpeakersHaveEnoughContext &&\n (identifiedSet.size === 0 || hasNewSpeaker)\n );\n }\n\n scheduleIdentification(callback: () => Promise<void>): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n this.debounceTimer = setTimeout(() => {\n callback();\n }, IDENTIFICATION_DEBOUNCE_MS);\n }\n\n async identify(\n entries: TranscriptEntry[],\n apiUrl: string,\n token: string,\n sessionId: string | null,\n premium: boolean\n ): Promise<void> {\n if (entries.length < 3 || !apiUrl) return;\n\n this.isIdentifying.set(true);\n\n try {\n const sample = entries\n .filter((e) => e.isFinal && e.speaker !== undefined)\n .slice(0, MAX_SAMPLE_SIZE)\n .map((e) => ({ speaker: e.speaker!, text: e.text }));\n\n if (sample.length < 2) return;\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${apiUrl}/identify-speakers`, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n segments: sample,\n context: { sessionId, premium },\n }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data: IdentifySpeakersResponse = await response.json();\n\n this.speakerMapping.set(data.speakerMapping);\n\n const newIdentified = new Set(this.identifiedSpeakers());\n for (const speakerId of Object.keys(data.speakerMapping)) {\n newIdentified.add(parseInt(speakerId, 10));\n }\n this.identifiedSpeakers.set(newIdentified);\n } catch (err) {\n console.error('Failed to identify speakers:', err);\n } finally {\n this.isIdentifying.set(false);\n }\n }\n\n setRole(speaker: number, role: SpeakerRole): SpeakerMapping {\n const current = this.speakerMapping();\n\n const updated: SpeakerMapping = {\n ...current,\n [speaker.toString()]: {\n role,\n confidence: 1,\n isManualOverride: true,\n },\n };\n\n this.speakerMapping.set(updated);\n this.editingSpeaker.set(null);\n\n return updated;\n }\n\n toggleMenu(speaker: number): void {\n const current = this.editingSpeaker();\n this.editingSpeaker.set(current === speaker ? null : speaker);\n }\n\n closeMenu(): void {\n this.editingSpeaker.set(null);\n }\n\n reset(): void {\n this.speakerMapping.set({});\n this.identifiedSpeakers.set(new Set());\n this.isIdentifying.set(false);\n this.editingSpeaker.set(null);\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n }\n}\n","const SAMPLE_RATE = 16000;\nconst NUM_CHANNELS = 1;\nconst BITS_PER_SAMPLE = 16;\n\nfunction writeString(view: DataView, offset: number, str: string): void {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n}\n\nfunction concatBuffers(buffer1: ArrayBuffer, buffer2: ArrayBuffer): ArrayBuffer {\n const combined = new Uint8Array(buffer1.byteLength + buffer2.byteLength);\n combined.set(new Uint8Array(buffer1), 0);\n combined.set(new Uint8Array(buffer2), buffer1.byteLength);\n return combined.buffer;\n}\n\nexport function pcmToWav(pcmData: ArrayBuffer, sampleRate = SAMPLE_RATE): ArrayBuffer {\n const header = new ArrayBuffer(44);\n const view = new DataView(header);\n\n const byteRate = sampleRate * NUM_CHANNELS * (BITS_PER_SAMPLE / 8);\n const blockAlign = NUM_CHANNELS * (BITS_PER_SAMPLE / 8);\n\n // RIFF chunk descriptor\n writeString(view, 0, 'RIFF');\n view.setUint32(4, 36 + pcmData.byteLength, true);\n writeString(view, 8, 'WAVE');\n\n // fmt sub-chunk\n writeString(view, 12, 'fmt ');\n view.setUint32(16, 16, true); // SubChunk1Size (16 for PCM)\n view.setUint16(20, 1, true); // AudioFormat (1 = PCM)\n view.setUint16(22, NUM_CHANNELS, true); // NumChannels\n view.setUint32(24, sampleRate, true); // SampleRate\n view.setUint32(28, byteRate, true); // ByteRate\n view.setUint16(32, blockAlign, true); // BlockAlign\n view.setUint16(34, BITS_PER_SAMPLE, true); // BitsPerSample\n\n // data sub-chunk\n writeString(view, 36, 'data');\n view.setUint32(40, pcmData.byteLength, true);\n\n return concatBuffers(header, pcmData);\n}\n\nexport function createAudioBlobUrl(wavData: ArrayBuffer): string {\n const blob = new Blob([wavData], { type: 'audio/wav' });\n return URL.createObjectURL(blob);\n}\n\nexport function formatTime(seconds: number): string {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n","import { Injectable, signal, ElementRef } from '@angular/core';\nimport type { SessionPlaybackData, TranscriptSegment, TranscriptionWord } from '@medc-com-br/jaimes-shared';\nimport { pcmToWav, createAudioBlobUrl, formatTime } from '../utils/pcm-to-wav';\n\n@Injectable()\nexport class PlaybackService {\n readonly isPlaying = signal(false);\n readonly isLoading = signal(false);\n readonly currentTime = signal(0);\n readonly duration = signal(0);\n readonly playbackRate = signal(1);\n readonly sessionData = signal<SessionPlaybackData | null>(null);\n readonly activeSegmentId = signal<string | null>(null);\n readonly activeWordIndex = signal<number | null>(null);\n\n private audioElement: HTMLAudioElement | null = null;\n private audioBlobUrl: string | null = null;\n private elementRef: ElementRef | null = null;\n\n private eventHandlers: {\n loadedmetadata?: () => void;\n timeupdate?: () => void;\n ended?: () => void;\n } = {};\n\n setElementRef(ref: ElementRef): void {\n this.elementRef = ref;\n }\n\n get segments(): TranscriptSegment[] {\n return this.sessionData()?.transcription.segments ?? [];\n }\n\n async loadSession(apiUrl: string, sessionId: string, token: string): Promise<void> {\n this.isLoading.set(true);\n\n try {\n const headers: Record<string, string> = {};\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${apiUrl}/session/${sessionId}`, { headers });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data: SessionPlaybackData = await response.json();\n this.sessionData.set(data);\n\n await this.loadAudio(data.audioUrl);\n } finally {\n this.isLoading.set(false);\n }\n }\n\n private async loadAudio(pcmUrl: string): Promise<void> {\n this.cleanup();\n\n const response = await fetch(pcmUrl);\n if (!response.ok) {\n throw new Error(`Failed to load audio: HTTP ${response.status}`);\n }\n\n const pcmData = await response.arrayBuffer();\n const wavData = pcmToWav(pcmData);\n this.audioBlobUrl = createAudioBlobUrl(wavData);\n\n this.audioElement = new Audio(this.audioBlobUrl);\n\n this.eventHandlers.loadedmetadata = () => {\n if (this.audioElement) {\n this.duration.set(this.audioElement.duration);\n }\n };\n\n this.eventHandlers.timeupdate = () => {\n if (this.audioElement) {\n this.currentTime.set(this.audioElement.currentTime);\n this.updateActiveSegment();\n }\n };\n\n this.eventHandlers.ended = () => {\n this.isPlaying.set(false);\n };\n\n this.audioElement.addEventListener('loadedmetadata', this.eventHandlers.loadedmetadata);\n this.audioElement.addEventListener('timeupdate', this.eventHandlers.timeupdate);\n this.audioElement.addEventListener('ended', this.eventHandlers.ended);\n }\n\n togglePlayback(): void {\n if (!this.audioElement) return;\n\n if (this.isPlaying()) {\n this.audioElement.pause();\n this.isPlaying.set(false);\n } else {\n this.audioElement.play();\n this.isPlaying.set(true);\n }\n }\n\n seekTo(time: number): void {\n if (this.audioElement && !isNaN(time)) {\n this.audioElement.currentTime = time;\n this.currentTime.set(time);\n }\n }\n\n seekToSegment(segment: TranscriptSegment): void {\n if (this.audioElement) {\n this.audioElement.currentTime = segment.startTime;\n this.currentTime.set(segment.startTime);\n if (!this.isPlaying()) {\n this.togglePlayback();\n }\n }\n }\n\n seekToWord(word: TranscriptionWord): void {\n if (this.audioElement) {\n this.audioElement.currentTime = word.start;\n this.currentTime.set(word.start);\n if (!this.isPlaying()) {\n this.togglePlayback();\n }\n }\n }\n\n setRate(rate: number): void {\n if (isNaN(rate)) return;\n this.playbackRate.set(rate);\n if (this.audioElement) {\n this.audioElement.playbackRate = rate;\n }\n }\n\n formatTime(seconds: number): string {\n return formatTime(seconds);\n }\n\n private updateActiveSegment(): void {\n const time = this.currentTime();\n const segs = this.segments;\n\n const seg = segs.find((s) => time >= s.startTime && time <= s.endTime);\n this.activeSegmentId.set(seg?.id ?? null);\n\n if (seg?.words) {\n const wordIdx = seg.words.findIndex((w) => time >= w.start && time <= w.end);\n this.activeWordIndex.set(wordIdx >= 0 ? wordIdx : null);\n } else {\n this.activeWordIndex.set(null);\n }\n\n this.scrollToActiveSegment();\n }\n\n private scrollToActiveSegment(): void {\n const activeId = this.activeSegmentId();\n if (!activeId || !this.elementRef) return;\n\n const container = this.elementRef.nativeElement.querySelector('.scribe-transcript-playback');\n const activeEl = container?.querySelector(`[data-segment-id=\"${activeId}\"]`);\n\n if (activeEl && container) {\n const containerRect = container.getBoundingClientRect();\n const activeRect = activeEl.getBoundingClientRect();\n\n if (activeRect.top < containerRect.top || activeRect.bottom > containerRect.bottom) {\n activeEl.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }\n }\n\n cleanup(): void {\n if (this.audioElement) {\n this.audioElement.pause();\n if (this.eventHandlers.loadedmetadata) {\n this.audioElement.removeEventListener('loadedmetadata', this.eventHandlers.loadedmetadata);\n }\n if (this.eventHandlers.timeupdate) {\n this.audioElement.removeEventListener('timeupdate', this.eventHandlers.timeupdate);\n }\n if (this.eventHandlers.ended) {\n this.audioElement.removeEventListener('ended', this.eventHandlers.ended);\n }\n this.eventHandlers = {};\n this.audioElement = null;\n }\n if (this.audioBlobUrl) {\n URL.revokeObjectURL(this.audioBlobUrl);\n this.audioBlobUrl = null;\n }\n }\n\n reset(): void {\n this.cleanup();\n this.isPlaying.set(false);\n this.isLoading.set(false);\n this.currentTime.set(0);\n this.duration.set(0);\n this.playbackRate.set(1);\n this.sessionData.set(null);\n this.activeSegmentId.set(null);\n this.activeWordIndex.set(null);\n }\n}\n","import { Component, inject, signal, input, output, OnDestroy, computed, HostListener, ElementRef, effect } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { AudioCaptureService } from '../../services/audio-capture.service';\nimport { ScribeSocketService, ConnectionState } from '../../services/scribe-socket.service';\nimport { SpeakerIdentificationService } from '../../services/speaker-identification.service';\nimport { PlaybackService } from '../../services/playback.service';\nimport type {\n TranscriptionEvent,\n TemplateOption,\n GeneratedDocument,\n TranscriptSegment,\n TranscriptionWord,\n SpeakerRole,\n} from '@medc-com-br/jaimes-shared';\n\ninterface TranscriptEntry {\n id: number;\n text: string;\n speaker?: number;\n isFinal: boolean;\n startTime?: number;\n endTime?: number;\n}\n\nexport type RecorderMode = 'recording' | 'playback';\n\ninterface SpeakerGroup {\n speaker?: number;\n entries: TranscriptEntry[];\n}\n\n@Component({\n selector: 'ngx-jaimes-scribe-recorder',\n standalone: true,\n imports: [CommonModule],\n providers: [SpeakerIdentificationService, PlaybackService],\n template: `\n <div class=\"scribe-recorder\">\n @if (mode() === 'playback') {\n <!-- Playback Mode -->\n <div class=\"scribe-playback\">\n @if (playback.isLoading()) {\n <div class=\"scribe-loading\">\n <svg class=\"scribe-icon scribe-icon--spinner\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"32\" stroke-linecap=\"round\"/>\n </svg>\n <span>Carregando sessão...</span>\n </div>\n } @else if (playback.sessionData()) {\n <!-- Audio Player -->\n <div class=\"scribe-player\">\n <button\n class=\"scribe-btn scribe-btn--play\"\n (click)=\"playback.togglePlayback()\"\n [attr.aria-label]=\"playback.isPlaying() ? 'Pausar' : 'Reproduzir'\"\n >\n @if (playback.isPlaying()) {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M6 19h4V5H6v14zm8-14v14h4V5h-4z\"/>\n </svg>\n } @else {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n }\n </button>\n\n <div class=\"scribe-timeline\">\n <input\n type=\"range\"\n class=\"scribe-timeline-slider\"\n [min]=\"0\"\n [max]=\"playback.duration()\"\n [value]=\"playback.currentTime()\"\n step=\"0.1\"\n (input)=\"onSeek($event)\"\n aria-label=\"Posição do áudio\"\n />\n <div class=\"scribe-time\">\n {{ playback.formatTime(playback.currentTime()) }} / {{ playback.formatTime(playback.duration()) }}\n </div>\n </div>\n\n <select\n class=\"scribe-speed\"\n [value]=\"playback.playbackRate()\"\n (change)=\"onPlaybackRateChange($event)\"\n aria-label=\"Velocidade de reprodução\"\n >\n <option value=\"0.5\">0.5x</option>\n <option value=\"0.75\">0.75x</option>\n <option value=\"1\">1x</option>\n <option value=\"1.25\">1.25x</option>\n <option value=\"1.5\">1.5x</option>\n <option value=\"2\">2x</option>\n </select>\n </div>\n\n <!-- Transcription with Highlight -->\n <div class=\"scribe-transcript-playback\">\n @for (segment of playback.segments; track segment.id; let idx = $index) {\n <div\n class=\"scribe-segment\"\n [class.scribe-segment--active]=\"playback.activeSegmentId() === segment.id\"\n [style.--speaker-color]=\"getSpeakerColor(segment.speaker)\"\n [attr.data-segment-id]=\"segment.id\"\n (click)=\"playback.seekToSegment(segment)\"\n >\n @if (segment.speaker !== undefined && shouldShowSpeakerLabel(idx)) {\n <span class=\"scribe-speaker-label\" [class]=\"'scribe-speaker--' + segment.speaker\">\n {{ getSpeakerLabel(segment.speaker) }}\n </span>\n }\n\n <p class=\"scribe-segment-text\">\n @if (segment.words?.length) {\n @for (word of segment.words; track $index; let i = $index) {\n <span\n class=\"scribe-word\"\n [class.scribe-word--active]=\"playback.activeSegmentId() === segment.id && playback.activeWordIndex() === i\"\n (click)=\"onWordClick(word, $event)\"\n >{{ word.word }}</span>{{ ' ' }}\n }\n } @else {\n {{ segment.text }}\n }\n </p>\n </div>\n }\n @if (playback.segments.length === 0) {\n <span class=\"scribe-placeholder\">Nenhuma transcrição disponível.</span>\n }\n </div>\n } @else {\n <div class=\"scribe-error\">\n <span>Não foi possível carregar a sessão.</span>\n </div>\n }\n </div>\n } @else {\n <!-- Recording Mode -->\n @if (isLoadingSession()) {\n <div class=\"scribe-loading\">\n <svg class=\"scribe-icon scribe-icon--spinner\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"32\" stroke-linecap=\"round\"/>\n </svg>\n <span>Carregando sessão...</span>\n </div>\n } @else {\n <div class=\"scribe-controls\">\n @if (!hasFinishedSession()) {\n <button\n class=\"scribe-btn scribe-btn--mic\"\n [class.scribe-btn--active]=\"isRecording() && !isPaused()\"\n [class.scribe-btn--paused]=\"isPaused()\"\n [class.scribe-btn--connecting]=\"connectionState() === 'connecting'\"\n [disabled]=\"connectionState() === 'connecting'\"\n (click)=\"toggleRecording()\"\n [attr.aria-label]=\"getMicButtonLabel()\"\n >\n @if (connectionState() === 'connecting') {\n <svg class=\"scribe-icon scribe-icon--spinner\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"32\" stroke-linecap=\"round\"/>\n </svg>\n } @else if (isPaused()) {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\"/>\n </svg>\n } @else if (isRecording()) {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M6 19h4V5H6v14zm8-14v14h4V5h-4z\"/>\n </svg>\n } @else {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"currentColor\">\n <path d=\"M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1-9c0-.55.45-1 1-1s1 .45 1 1v6c0 .55-.45 1-1 1s-1-.45-1-1V5z\"/>\n <path d=\"M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z\"/>\n </svg>\n }\n </button>\n\n <div class=\"scribe-level\" [class.scribe-level--active]=\"isRecording() && !isPaused()\">\n <div class=\"scribe-level__fill\" [style.width.%]=\"isPaused() ? 0 : audioLevel()\"></div>\n </div>\n\n <button\n class=\"scribe-btn scribe-btn--finish\"\n [disabled]=\"!isRecording() && !isPaused()\"\n (click)=\"finishSession()\"\n aria-label=\"Finalizar gravação\"\n >\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\">\n <path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>\n </svg>\n <span>Finalizar</span>\n </button>\n }\n\n @if (hasFinishedSession() && templates().length > 0) {\n <div class=\"scribe-generate-container\">\n <button\n class=\"scribe-btn scribe-btn--generate\"\n [disabled]=\"isGenerating()\"\n [attr.aria-expanded]=\"showTemplateMenu()\"\n aria-haspopup=\"menu\"\n (click)=\"toggleTemplateMenu()\"\n aria-label=\"Gerar resumo\"\n >\n @if (isGenerating()) {\n <svg class=\"scribe-icon scribe-icon--spinner\" viewBox=\"0 0 24 24\" width=\"20\" height=\"20\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"32\" stroke-linecap=\"round\"/>\n </svg>\n <span>Gerando...</span>\n } @else {\n <svg class=\"scribe-icon\" viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\">\n <path d=\"M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11zm-3-7h-2v2h-2v-2H9v-2h2V9h2v2h2v2z\"/>\n </svg>\n <span>Gerar Resumo</span>\n }\n </button>\n\n @if (showTemplateMenu()) {\n <div class=\"scribe-template-menu\" role=\"menu\">\n @for (template of templates(); track template.id) {\n <button\n class=\"scribe-template-item\"\n role=\"menuitem\"\n (click)=\"selectTemplate(template)\"\n >\n <span class=\"scribe-template-name\">{{ template.name }}</span>\n @if (template.description) {\n <span class=\"scribe-template-desc\">{{ template.description }}</span>\n }\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"scribe-transcript\" [class.scribe-transcript--empty]=\"speakerGroups().length === 0 && !partialText()\">\n @if (speakerGroups().length === 0 && !partialText()) {\n <span class=\"scribe-placeholder\">A transcrição aparecerá aqui...</span>\n } @else {\n @for (group of speakerGroups(); track $index) {\n <div class=\"scribe-speaker-block\" [attr.data-speaker]=\"group.speaker\">\n @if (group.speaker !== undefined && group.speaker !== null) {\n <span class=\"scribe-speaker-label-wrapper\">\n <button\n type=\"button\"\n class=\"scribe-speaker-label scribe-speaker-label--editable\"\n [class]=\"'scribe-speaker--' + group.speaker\"\n [class.scribe-speaker-label--low-confidence]=\"speakerService.hasLowConfidence(group.speaker)\"\n (click)=\"onSpeakerLabelClick($event, group.speaker)\"\n >\n {{ getSpeakerLabel(group.speaker) }}\n <svg class=\"scribe-chevron\" viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"currentColor\">\n <path d=\"M7 10l5 5 5-5z\"/>\n </svg>\n @if (speakerService.hasLowConfidence(group.speaker)) {\n <span class=\"scribe-warning\" title=\"Confiança baixa - verifique\">⚠️</span>\n }\n </button>\n @if (speakerService.editingSpeaker() === group.speaker) {\n <div class=\"scribe-speaker-dropdown\">\n <button type=\"button\" class=\"scribe-dropdown-item\" (click)=\"setSpeakerRole(group.speaker, 'doctor')\">\n <span class=\"scribe-dropdown-icon\">🩺</span> Médico\n </button>\n <button type=\"button\" class=\"scribe-dropdown-item\" (click)=\"setSpeakerRole(group.speaker, 'patient')\">\n <span class=\"scribe-dropdown-icon\">🙋</span> Paciente\n </button>\n <button type=\"button\" class=\"scribe-dropdown-item\" (click)=\"setSpeakerRole(group.speaker, 'companion')\">\n <span class=\"scribe-dropdown-icon\">👥</span> Acompanhante\n </button>\n <div class=\"scribe-dropdown-divider\"></div>\n <button type=\"button\" class=\"scribe-dropdown-item\" (click)=\"setSpeakerRole(group.speaker, 'other')\">\n <span class=\"scribe-dropdown-icon\">✏️</span> Outro\n </button>\n </div>\n }\n </span>\n }\n <div class=\"scribe-speaker-text\">\n @for (entry of group.entries; track entry.id) {\n <span class=\"scribe-text scribe-text--final\">{{ entry.text }} </span>\n }\n </div>\n </div>\n }\n @if (partialText()) {\n <div class=\"scribe-speaker-block scribe-speaker-block--partial\">\n @if (currentSpeaker() !== undefined && currentSpeaker() !== null) {\n <span class=\"scribe-speaker-label\" [class]=\"'scribe-speaker--' + currentSpeaker()\">\n {{ getSpeakerLabel(currentSpeaker()!) }}\n </span>\n }\n <div class=\"scribe-speaker-text\">\n <span class=\"scribe-text scribe-text--partial\">{{ partialText() }}</span>\n </div>\n </div>\n }\n }\n </div>\n }\n }\n </div>\n `,\n styles: [`\n :host {\n --scribe-primary: #4caf50;\n --scribe-primary-dark: #388e3c;\n --scribe-primary-light: #81c784;\n --scribe-danger: #f44336;\n --scribe-danger-dark: #d32f2f;\n --scribe-text-color: #212121;\n --scribe-text-partial: #9e9e9e;\n --scribe-font-family: inherit;\n --scribe-font-size: 1rem;\n --scribe-bg: #ffffff;\n --scribe-bg-transcript: #f5f5f5;\n --scribe-border-radius: 8px;\n --scribe-border-color: #e0e0e0;\n --scribe-level-bg: #e0e0e0;\n --scribe-level-fill: #4caf50;\n --scribe-speaker-0: #2196f3;\n --scribe-speaker-1: #9c27b0;\n --scribe-speaker-2: #ff9800;\n --scribe-speaker-3: #009688;\n display: block;\n font-family: var(--scribe-font-family);\n font-size: var(--scribe-font-size);\n }\n\n .scribe-recorder { background: var(--scribe-bg); border-radius: var(--scribe-border-radius); }\n .scribe-controls { display: flex; align-items: center; gap: 1rem; padding: 1rem; }\n\n .scribe-btn {\n display: flex; align-items: center; justify-content: center; gap: 0.5rem;\n padding: 0.75rem; border: none; border-radius: var(--scribe-border-radius);\n font-family: var(--scribe-font-family); font-size: 0.875rem; font-weight: 500;\n cursor: pointer; transition: all 0.2s ease;\n }\n .scribe-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n\n .scribe-btn--mic {\n width: 48px; height: 48px; border-radius: 50%;\n background: var(--scribe-bg-transcript); color: var(--scribe-text-color);\n }\n .scribe-btn--mic:hover:not(:disabled) { background: var(--scribe-border-color); }\n .scribe-btn--mic.scribe-btn--active {\n background: var(--scribe-danger); color: white;\n animation: pulse-recording 1.5s ease-in-out infinite;\n }\n .scribe-btn--mic.scribe-btn--paused { background: var(--scribe-primary); color: white; }\n .scribe-btn--mic.scribe-btn--paused:hover:not(:disabled) { background: var(--scribe-primary-dark); }\n .scribe-btn--mic.scribe-btn--connecting { background: var(--scribe-primary-light); color: white; }\n\n .scribe-btn--finish { padding: 0.75rem 1.25rem; background: var(--scribe-primary); color: white; }\n .scribe-btn--finish:hover:not(:disabled) { background: var(--scribe-primary-dark); }\n\n .scribe-icon { flex-shrink: 0; }\n .scribe-icon--spinner { animation: spin 1s linear infinite; }\n\n .scribe-level {\n flex: 1; height: 8px; background: var(--scribe-level-bg);\n border-radius: 4px; overflow: hidden; opacity: 0.5; transition: opacity 0.2s ease;\n }\n .scribe-level--active { opacity: 1; }\n .scribe-level__fill {\n height: 100%; background: var(--scribe-level-fill);\n border-radius: 4px; transition: width 0.05s ease-out;\n }\n\n .scribe-transcript {\n min-height: 120px; max-height: 400px; overflow-y: auto; padding: 1rem;\n margin: 0 1rem 1rem; background: var(--scribe-bg-transcript);\n border-radius: var(--scribe-border-radius); line-height: 1.6;\n }\n .scribe-transcript--empty { display: flex; align-items: center; justify-content: center; }\n .scribe-placeholder { color: var(--scribe-text-partial); font-style: italic; }\n\n .scribe-speaker-block {\n margin-bottom: 0.75rem; padding-left: 0.5rem;\n border-left: 3px solid var(--scribe-border-color);\n }\n .scribe-speaker-block--partial { opacity: 0.7; }\n .scribe-speaker-block[data-speaker=\"0\"] { border-left-color: var(--scribe-speaker-0); }\n .scribe-speaker-block[data-speaker=\"1\"] { border-left-color: var(--scribe-speaker-1); }\n .scribe-speaker-block[data-speaker=\"2\"] { border-left-color: var(--scribe-speaker-2); }\n .scribe-speaker-block[data-speaker=\"3\"] { border-left-color: var(--scribe-speaker-3); }\n\n .scribe-speaker-label {\n display: inline-block; font-size: 0.75rem; font-weight: 600;\n text-transform: uppercase; letter-spacing: 0.5px; padding: 0.125rem 0.5rem;\n border-radius: 4px; margin-bottom: 0.25rem; color: white; background: var(--scribe-border-color);\n }\n .scribe-speaker--0 { background: var(--scribe-speaker-0); }\n .scribe-speaker--1 { background: var(--scribe-speaker-1); }\n .scribe-speaker--2 { background: var(--scribe-speaker-2); }\n .scribe-speaker--3 { background: var(--scribe-speaker-3); }\n\n .scribe-speaker-text { margin-top: 0.25rem; }\n .scribe-text { word-wrap: break-word; }\n .scribe-text--final { color: var(--scribe-text-color); }\n .scribe-text--partial { color: var(--scribe-text-partial); font-style: italic; }\n\n .scribe-generate-container { position: relative; margin-left: 0.5rem; }\n .scribe-btn--generate {\n display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1.25rem;\n background: var(--scribe-primary); color: white; border: none;\n border-radius: var(--scribe-border-radius); font-family: var(--scribe-font-family);\n font-size: 0.875rem; font-weight: 500; cursor: pointer; transition: all 0.2s ease;\n }\n .scribe-btn--generate:hover:not(:disabled) { background: var(--scribe-primary-dark); }\n .scribe-btn--generate:disabled { opacity: 0.7; cursor: not-allowed; }\n\n .scribe-template-menu {\n position: absolute; top: 100%; left: 0; margin-top: 0.25rem;\n min-width: 220px; background: var(--scribe-bg);\n border: 1px solid var(--scribe-border-color); border-radius: var(--scribe-border-radius);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); z-index: 100; overflow: hidden;\n }\n .scribe-template-item {\n display: flex; flex-direction: column; align-items: flex-start;\n width: 100%; padding: 0.75rem 1rem; border: none; background: transparent;\n cursor: pointer; text-align: left; transition: background 0.15s ease;\n }\n .scribe-template-item:hover { background: var(--scribe-bg-transcript); }\n .scribe-template-item:not(:last-child) { border-bottom: 1px solid var(--scribe-border-color); }\n .scribe-template-name { font-weight: 500; color: var(--scribe-text-color); }\n .scribe-template-desc { font-size: 0.75rem; color: var(--scribe-text-partial); margin-top: 0.25rem; }\n\n @keyframes pulse-recording {\n 0%, 100% { box-shadow: 0 0 0 0 rgba(244, 67, 54, 0.4); }\n 50% { box-shadow: 0 0 0 8px rgba(244, 67, 54, 0); }\n }\n @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }\n\n .scribe-playback { padding: 1rem; }\n .scribe-loading, .scribe-error {\n display: flex; align-items: center; justify-content: center;\n gap: 0.5rem; padding: 2rem; color: var(--scribe-text-partial);\n }\n\n .scribe-player {\n display: flex; align-items: center; gap: 1rem; padding: 1rem;\n background: var(--scribe-bg-transcript); border-radius: var(--scribe-border-radius); margin-bottom: 1rem;\n }\n .scribe-btn--play {\n width: 48px; height: 48px; border-radius: 50%; background: var(--scribe-primary);\n color: white; border: none; cursor: pointer; display: flex; align-items: center;\n justify-content: center; transition: background 0.2s ease; flex-shrink: 0;\n }\n .scribe-btn--play:hover { background: var(--scribe-primary-dark); }\n\n .scribe-timeline { flex: 1; position: relative; }\n .scribe-timeline-slider {\n width: 100%; cursor: pointer; -webkit-appearance: none; appearance: none;\n background: var(--scribe-level-bg); border-radius: 3px; outline: none;\n }\n .scribe-timeline-slider::-webkit-slider-thumb {\n -webkit-appearance: none; appearance: none; width: 14px; height: 14px;\n background: var(--scribe-primary); border-radius: 50%; cursor: pointer;\n }\n .scribe-timeline-slider::-moz-range-thumb {\n width: 14px; height: 14px; background: var(--scribe-primary);\n border-radius: 50%; cursor: pointer; border: none;\n }\n .scribe-time {\n position: absolute; top: 20px; left: 50%; transform: translateX(-50%);\n font-size: 0.75rem; color: var(--scribe-text-partial); white-space: nowrap;\n }\n .scribe-speed {\n padding: 0.375rem 0.5rem; border-radius: 4px;\n border: 1px solid var(--scribe-border-color); background: var(--scribe-bg);\n font-size: 0.875rem; cursor: pointer;\n }\n\n .scribe-transcript-playback { max-height: 400px; overflow-y: auto; scroll-behavior: smooth; padding: 0.5rem; }\n .scribe-segment {\n padding: 0.75rem 1rem; margin-bottom: 0.5rem;\n border-left: 3px solid var(--speaker-color, var(--scribe-border-color));\n background: var(--scribe-bg); border-radius: 0 var(--scribe-border-radius) var(--scribe-border-radius) 0;\n cursor: pointer; transition: background 0.2s ease;\n }\n .scribe-segment:hover { background: var(--scribe-bg-transcript); }\n .scribe-segment--active { background: rgba(76, 175, 80, 0.1); border-left-color: var(--scribe-primary); }\n .scribe-segment-text { margin: 0.25rem 0 0 0; line-height: 1.6; }\n\n .scribe-word { transition: background 0.15s ease, color 0.15s ease; padding: 0 1px; border-radius: 2px; }\n .scribe-word:hover { background: rgba(0, 0, 0, 0.05); cursor: pointer; }\n .scribe-word--active { background: var(--scribe-primary); color: white; }\n\n .scribe-speaker-label-wrapper { position: relative; display: inline-block; }\n .scribe-speaker-label--editable {\n cursor: pointer; display: inline-flex; align-items: center; gap: 4px;\n border: 1px solid transparent; transition: all 0.15s ease;\n }\n .scribe-speaker-label--editable:hover { border-color: rgba(255, 255, 255, 0.3); }\n .scribe-speaker-label--low-confidence { border-color: var(--scribe-warning, #f59e0b) !important; }\n .scribe-chevron { opacity: 0.7; }\n .scribe-warning { font-size: 0.875rem; margin-left: 2px; }\n\n .scribe-speaker-dropdown {\n position: absolute; top: 100%; left: 0; z-index: 100; min-width: 140px;\n margin-top: 4px; background: var(--scribe-bg); border: 1px solid var(--scribe-border-color);\n border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); padding: 4px;\n }\n .scribe-dropdown-item {\n display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 12px;\n border: none; background: none; cursor: pointer; font-family: var(--scribe-font-family);\n font-size: 0.875rem; text-align: left; border-radius: 4px; color: var(--scribe-text-color);\n }\n .scribe-dropdown-item:hover { background: var(--scribe-bg-transcript); }\n .scribe-dropdown-icon { font-size: 1rem; }\n .scribe-dropdown-divider { height: 1px; background: var(--scribe-border-color); margin: 4px 0; }\n `],\n})\nexport class RecorderComponent implements OnDestroy {\n private audioCapture = inject(AudioCaptureService);\n private socket = inject(ScribeSocketService);\n private elementRef = inject(ElementRef);\n\n readonly speakerService = inject(SpeakerIdentificationService);\n readonly playback = inject(PlaybackService);\n\n private subscriptions: Subscription[] = [];\n private entryIdCounter = 0;\n private generateAbortController: AbortController | null = null;\n\n @HostListener('document:click', ['$event'])\n onDocumentClick(event: MouseEvent): void {\n const target = event.target as HTMLElement;\n const isInside = this.elementRef.nativeElement.contains(target);\n\n if (this.showTemplateMenu() && !isInside) {\n this.showTemplateMenu.set(false);\n }\n\n if (this.speakerService.editingSpeaker() !== null) {\n const isDropdownClick = target.closest('.scribe-speaker-dropdown') ||\n target.closest('.scribe-speaker-label--editable');\n if (!isDropdownClick) {\n this.speakerService.closeMenu();\n }\n }\n }\n\n wsUrl = input<string>('');\n token = input<string>('');\n speakerLabels = input<Record<number, string>>({});\n premium = input<boolean>(false);\n templates = input<TemplateOption[]>([]);\n lambdaUrl = input<string>('');\n sessionId = input<string | undefined>();\n apiUrl = input<string>('');\n resumeSessionId = input<string | undefined>();\n doctorName = input<string>('');\n patientName = input<string>('');\n companionName = input<string>('');\n\n sessionStarted = output<string>();\n sessionFinished = output<{ transcript: string; entries: TranscriptEntry[] }>();\n error = output<Error>();\n documentGenerated = output<GeneratedDocument>();\n generationError = output<Error>();\n\n isRecording = signal(false);\n isPaused = signal(false);\n audioLevel = signal(0);\n connectionState = signal<ConnectionState>('disconnected');\n entries = signal<TranscriptEntry[]>([]);\n partialText = signal('');\n currentSpeaker = signal<number | undefined>(undefined);\n showTemplateMenu = signal(false);\n isGenerating = signal(false);\n lastSessionId = signal<string | null>(null);\n isLoadingSession = signal(false);\n\n mode = computed<RecorderMode>(() => this.sessionId() ? 'playback' : 'recording');\n\n hasFinishedSession = computed(() =>\n this.lastSessionId() !== null && !this.isRecording() && !this.isPaused()\n );\n\n speakerGroups = computed<SpeakerGroup[]>(() => {\n const allEntries = this.entries();\n if (allEntries.length === 0) return [];\n\n const groups: SpeakerGroup[] = [];\n let currentGroup: SpeakerGroup | null = null;\n\n for (const entry of allEntries) {\n if (!currentGroup || currentGroup.speaker !== entry.speaker) {\n currentGroup = { speaker: entry.speaker, entries: [] };\n groups.push(currentGroup);\n }\n currentGroup.entries.push(entry);\n }\n\n return groups;\n });\n\n constructor() {\n this.playback.setElementRef(this.elementRef);\n\n this.subscriptions.push(\n this.audioCapture.audioLevel$.subscribe((level) => this.audioLevel.set(level)),\n this.socket.connectionState$.subscribe((state) => this.connectionState.set(state)),\n this.socket.transcription$.subscribe((event) => this.handleTranscription(event)),\n this.socket.error$.subscribe((err) => this.error.emit(err)),\n this.audioCapture.error$.subscribe((err) => this.error.emit(err)),\n this.audioCapture.audioChunk$.subscribe(({ data, isSilence }) => {\n this.socket.sendAudioChunk(data, isSilence);\n })\n );\n\n effect(() => {\n const sid = this.sessionId();\n const api = this.apiUrl();\n if (sid && api && this.mode() === 'playback') {\n this.loadPlaybackSession();\n }\n });\n\n effect(() => {\n const resumeId = this.resumeSessionId();\n const api = this.apiUrl();\n if (resumeId && api && this.mode() === 'recording') {\n this.resumeSession(resumeId);\n }\n });\n\n effect(() => {\n if (this.mode() !== 'recording') return;\n\n const allEntries = this.entries();\n if (this.speakerService.shouldIdentify(allEntries)) {\n this.speakerService.scheduleIdentification(() => this.triggerIdentification());\n }\n });\n }\n\n ngOnDestroy(): void {\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n this.generateAbortController?.abort();\n this.cleanup();\n this.playback.cleanup();\n this.speakerService.reset();\n }\n\n getSpeakerLabel(speaker: number): string {\n return this.speakerService.getLabel(\n speaker,\n this.speakerLabels(),\n this.doctorName(),\n this.patientName(),\n this.companionName()\n );\n }\n\n shouldShowSpeakerLabel(segmentIndex: number): boolean {\n const segs = this.playback.segments;\n if (segmentIndex === 0) return true;\n return segs[segmentIndex]?.speaker !== segs[segmentIndex - 1]?.speaker;\n }\n\n getMicButtonLabel(): string {\n if (this.isPaused()) return 'Retomar gravação';\n if (this.isRecording()) return 'Pausar gravação';\n return 'Iniciar gravação';\n }\n\n async toggleRecording(): Promise<void> {\n if (this.isPaused()) {\n this.resumeRecording();\n } else if (this.isRecording()) {\n this.pauseRecording();\n } else {\n await this.startRecording();\n }\n }\n\n pauseRecording(): void {\n if (!this.isRecording() || this.isPaused()) return;\n this.audioCapture.pauseCapture();\n this.isPaused.set(true);\n }\n\n resumeRecording(): void {\n if (!this.isPaused()) return;\n this.audioCapture.resumeCapture();\n this.isPaused.set(false);\n }\n\n async finishSession(): Promise<void> {\n if (!this.isRecording() && !this.isPaused()) return;\n\n const sessionId = this.socket.getSessionId();\n await this.stopRecording();\n\n const allEntries = this.entries();\n const fullTranscript = allEntries.map((e) => e.text).join(' ');\n\n this.sessionFinished.emit({ transcript: fullTranscript, entries: allEntries });\n this.partialText.set('');\n this.currentSpeaker.set(undefined);\n this.lastSessionId.set(sessionId);\n }\n\n toggleTemplateMenu(): void {\n this.showTemplateMenu.update((v) => !v);\n }\n\n async selectTemplate(template: TemplateOption): Promise<void> {\n if (this.isGenerating()) return;\n\n this.showTemplateMenu.set(false);\n\n const lambdaUrl = this.lambdaUrl();\n if (!lambdaUrl) {\n this.generationError.emit(new Error('Lambda URL not provided'));\n return;\n }\n\n const sessionId = this.lastSessionId();\n if (!sessionId) {\n this.generationError.emit(new Error('No session available'));\n return;\n }\n\n this.generateAbortController?.abort();\n this.generateAbortController = new AbortController();\n this.isGenerating.set(true);\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n const token = this.token();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${lambdaUrl}/generate`, {\n method: 'POST',\n headers,\n signal: this.generateAbortController.signal,\n body: JSON.stringify({ sessionId, outputSchema: template.content }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.error || `HTTP ${response.status}`);\n }\n\n const result = await response.json();\n\n this.documentGenerated.emit({\n sessionId,\n templateId: template.id,\n content: result.content,\n generatedAt: result.generatedAt,\n });\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') return;\n this.generationError.emit(err instanceof Error ? err : new Error(String(err)));\n } finally {\n this.isGenerating.set(false);\n }\n }\n\n onSeek(event: Event): void {\n const input = event.target as HTMLInputElement | null;\n if (input) {\n this.playback.seekTo(parseFloat(input.value));\n }\n }\n\n onPlaybackRateChange(event: Event): void {\n const select = event.target as HTMLSelectElement | null;\n if (select) {\n this.playback.setRate(parseFloat(select.value));\n }\n }\n\n onWordClick(word: TranscriptionWord, event: Event): void {\n event.stopPropagation();\n this.playback.seekToWord(word);\n }\n\n onSpeakerLabelClick(event: Event, speaker: number): void {\n event.stopPropagation();\n this.speakerService.toggleMenu(speaker);\n }\n\n setSpeakerRole(speaker: number, role: SpeakerRole): void {\n this.speakerService.setRole(speaker, role);\n }\n\n getSpeakerColor(speaker: number | undefined): string {\n if (speaker === undefined) return 'var(--scribe-border-color)';\n const colors = [\n 'var(--scribe-speaker-0)',\n 'var(--scribe-speaker-1)',\n 'var(--scribe-speaker-2)',\n 'var(--scribe-speaker-3)',\n ];\n return colors[speaker % colors.length];\n }\n\n private async loadPlaybackSession(): Promise<void> {\n const sid = this.sessionId();\n const api = this.apiUrl();\n if (!sid || !api) return;\n\n try {\n await this.playback.loadSession(api, sid, this.token());\n } catch (err) {\n this.error.emit(err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n private async resumeSession(sessionId: string): Promise<void> {\n const api = this.apiUrl();\n if (!api) return;\n\n this.isLoadingSession.set(true);\n\n try {\n const headers: Record<string, string> = {};\n const token = this.token();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${api}/session/${sessionId}`, { headers });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data = await response.json();\n\n const entries: TranscriptEntry[] = data.transcription.segments.map((seg: TranscriptSegment, idx: number) => ({\n id: idx + 1,\n text: seg.text,\n speaker: seg.speaker,\n isFinal: true,\n startTime: seg.startTime,\n endTime: seg.endTime,\n }));\n\n this.entryIdCounter = entries.length;\n this.entries.set(entries);\n this.lastSessionId.set(sessionId);\n } catch (err) {\n this.error.emit(err instanceof Error ? err : new Error(String(err)));\n } finally {\n this.isLoadingSession.set(false);\n }\n }\n\n private async startRecording(): Promise<void> {\n try {\n await this.socket.connect(this.wsUrl(), this.token(), this.premium());\n await this.audioCapture.startCapture();\n this.isRecording.set(true);\n this.isPaused.set(false);\n\n const sessionId = this.socket.getSessionId();\n if (sessionId) {\n this.sessionStarted.emit(sessionId);\n }\n } catch (err) {\n this.error.emit(err instanceof Error ? err : new Error('Failed to start recording'));\n await this.cleanup();\n }\n }\n\n private async stopRecording(): Promise<void> {\n await this.audioCapture.stopCapture();\n this.socket.disconnect();\n this.isRecording.set(false);\n this.isPaused.set(false);\n }\n\n private async cleanup(): Promise<void> {\n await this.audioCapture.stopCapture();\n this.socket.disconnect();\n this.isRecording.set(false);\n this.isPaused.set(false);\n }\n\n private handleTranscription(event: TranscriptionEvent): void {\n if (!event.transcript) return;\n\n if (event.type === 'final') {\n const entry: TranscriptEntry = {\n id: ++this.entryIdCounter,\n text: event.transcript,\n speaker: event.speaker,\n isFinal: true,\n startTime: event.start,\n endTime: event.end,\n };\n\n this.entries.update((entries) => [...entries, entry]);\n this.partialText.set('');\n this.currentSpeaker.set(undefined);\n } else if (event.type === 'partial') {\n this.partialText.set(event.transcript);\n this.currentSpeaker.set(event.speaker);\n }\n }\n\n private async triggerIdentification(): Promise<void> {\n const api = this.apiUrl() || this.lambdaUrl();\n const sessionId = this.socket.getSessionId() || this.lastSessionId();\n\n await this.speakerService.identify(\n this.entries(),\n api,\n this.token(),\n sessionId,\n this.premium()\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["DEFAULT_CONFIG"],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import { OnDestroy } from '@angular/core';
2
2
  import { ConnectionState } from '../../services/scribe-socket.service';
3
- import type { TemplateOption, GeneratedDocument, SessionPlaybackData, TranscriptSegment, TranscriptionWord } from '@medc-com-br/jaimes-shared';
3
+ import { SpeakerIdentificationService } from '../../services/speaker-identification.service';
4
+ import { PlaybackService } from '../../services/playback.service';
5
+ import type { TemplateOption, GeneratedDocument, TranscriptionWord, SpeakerRole } from '@medc-com-br/jaimes-shared';
4
6
  import * as i0 from "@angular/core";
5
7
  interface TranscriptEntry {
6
8
  id: number;
@@ -19,6 +21,8 @@ export declare class RecorderComponent implements OnDestroy {
19
21
  private audioCapture;
20
22
  private socket;
21
23
  private elementRef;
24
+ readonly speakerService: SpeakerIdentificationService;
25
+ readonly playback: PlaybackService;
22
26
  private subscriptions;
23
27
  private entryIdCounter;
24
28
  private generateAbortController;
@@ -32,6 +36,9 @@ export declare class RecorderComponent implements OnDestroy {
32
36
  sessionId: import("@angular/core").InputSignal<string>;
33
37
  apiUrl: import("@angular/core").InputSignal<string>;
34
38
  resumeSessionId: import("@angular/core").InputSignal<string>;
39
+ doctorName: import("@angular/core").InputSignal<string>;
40
+ patientName: import("@angular/core").InputSignal<string>;
41
+ companionName: import("@angular/core").InputSignal<string>;
35
42
  sessionStarted: import("@angular/core").OutputEmitterRef<string>;
36
43
  sessionFinished: import("@angular/core").OutputEmitterRef<{
37
44
  transcript: string;
@@ -50,24 +57,12 @@ export declare class RecorderComponent implements OnDestroy {
50
57
  showTemplateMenu: import("@angular/core").WritableSignal<boolean>;
51
58
  isGenerating: import("@angular/core").WritableSignal<boolean>;
52
59
  lastSessionId: import("@angular/core").WritableSignal<string>;
53
- isPlaying: import("@angular/core").WritableSignal<boolean>;
54
60
  isLoadingSession: import("@angular/core").WritableSignal<boolean>;
55
- audioCurrentTime: import("@angular/core").WritableSignal<number>;
56
- audioDuration: import("@angular/core").WritableSignal<number>;
57
- playbackRate: import("@angular/core").WritableSignal<number>;
58
- sessionData: import("@angular/core").WritableSignal<SessionPlaybackData>;
59
- activeSegmentId: import("@angular/core").WritableSignal<string>;
60
- activeWordIndex: import("@angular/core").WritableSignal<number>;
61
- private audioElement;
62
- private audioBlobUrl;
63
61
  mode: import("@angular/core").Signal<RecorderMode>;
64
- segments: import("@angular/core").Signal<TranscriptSegment[]>;
65
62
  hasFinishedSession: import("@angular/core").Signal<boolean>;
66
63
  speakerGroups: import("@angular/core").Signal<SpeakerGroup[]>;
67
64
  constructor();
68
65
  ngOnDestroy(): void;
69
- private audioEventHandlers;
70
- private cleanupPlayback;
71
66
  getSpeakerLabel(speaker: number): string;
72
67
  shouldShowSpeakerLabel(segmentIndex: number): boolean;
73
68
  getMicButtonLabel(): string;
@@ -77,23 +72,20 @@ export declare class RecorderComponent implements OnDestroy {
77
72
  finishSession(): Promise<void>;
78
73
  toggleTemplateMenu(): void;
79
74
  selectTemplate(template: TemplateOption): Promise<void>;
80
- loadSession(): Promise<void>;
81
- resumeSession(sessionId: string): Promise<void>;
82
- private loadAudio;
83
- togglePlayback(): void;
84
- seekTo(event: Event): void;
85
- setPlaybackRate(event: Event): void;
86
- seekToSegment(segment: TranscriptSegment): void;
87
- seekToWord(word: TranscriptionWord, event: Event): void;
88
- formatTimeDisplay(seconds: number): string;
75
+ onSeek(event: Event): void;
76
+ onPlaybackRateChange(event: Event): void;
77
+ onWordClick(word: TranscriptionWord, event: Event): void;
78
+ onSpeakerLabelClick(event: Event, speaker: number): void;
79
+ setSpeakerRole(speaker: number, role: SpeakerRole): void;
89
80
  getSpeakerColor(speaker: number | undefined): string;
90
- private updateActiveSegment;
91
- private scrollToActiveSegment;
81
+ private loadPlaybackSession;
82
+ private resumeSession;
92
83
  private startRecording;
93
84
  private stopRecording;
94
85
  private cleanup;
95
86
  private handleTranscription;
87
+ private triggerIdentification;
96
88
  static ɵfac: i0.ɵɵFactoryDeclaration<RecorderComponent, never>;
97
- static ɵcmp: i0.ɵɵComponentDeclaration<RecorderComponent, "ngx-jaimes-scribe-recorder", never, { "wsUrl": { "alias": "wsUrl"; "required": false; "isSignal": true; }; "token": { "alias": "token"; "required": false; "isSignal": true; }; "speakerLabels": { "alias": "speakerLabels"; "required": false; "isSignal": true; }; "premium": { "alias": "premium"; "required": false; "isSignal": true; }; "templates": { "alias": "templates"; "required": false; "isSignal": true; }; "lambdaUrl": { "alias": "lambdaUrl"; "required": false; "isSignal": true; }; "sessionId": { "alias": "sessionId"; "required": false; "isSignal": true; }; "apiUrl": { "alias": "apiUrl"; "required": false; "isSignal": true; }; "resumeSessionId": { "alias": "resumeSessionId"; "required": false; "isSignal": true; }; }, { "sessionStarted": "sessionStarted"; "sessionFinished": "sessionFinished"; "error": "error"; "documentGenerated": "documentGenerated"; "generationError": "generationError"; }, never, never, true, never>;
89
+ static ɵcmp: i0.ɵɵComponentDeclaration<RecorderComponent, "ngx-jaimes-scribe-recorder", never, { "wsUrl": { "alias": "wsUrl"; "required": false; "isSignal": true; }; "token": { "alias": "token"; "required": false; "isSignal": true; }; "speakerLabels": { "alias": "speakerLabels"; "required": false; "isSignal": true; }; "premium": { "alias": "premium"; "required": false; "isSignal": true; }; "templates": { "alias": "templates"; "required": false; "isSignal": true; }; "lambdaUrl": { "alias": "lambdaUrl"; "required": false; "isSignal": true; }; "sessionId": { "alias": "sessionId"; "required": false; "isSignal": true; }; "apiUrl": { "alias": "apiUrl"; "required": false; "isSignal": true; }; "resumeSessionId": { "alias": "resumeSessionId"; "required": false; "isSignal": true; }; "doctorName": { "alias": "doctorName"; "required": false; "isSignal": true; }; "patientName": { "alias": "patientName"; "required": false; "isSignal": true; }; "companionName": { "alias": "companionName"; "required": false; "isSignal": true; }; }, { "sessionStarted": "sessionStarted"; "sessionFinished": "sessionFinished"; "error": "error"; "documentGenerated": "documentGenerated"; "generationError": "generationError"; }, never, never, true, never>;
98
90
  }
99
91
  export {};