comparison dictation/transcriber.py @ 280:49e9e591c9bb

Add persistent dictation, prewarmed WebRTC speech input, Copilot SDK routing, animated conversation lifecycle controls, parking, and architecture coverage.
author MrJuneJune <me@mrjunejune.com>
date Tue, 18 Aug 2026 19:14:53 -0700
parents 78699f810817
children
comparison
equal deleted inserted replaced
279:b3b547563ec7 280:49e9e591c9bb
47 if self._model is not None: 47 if self._model is not None:
48 return 48 return
49 loop = asyncio.get_running_loop() 49 loop = asyncio.get_running_loop()
50 self._model = await loop.run_in_executor( 50 self._model = await loop.run_in_executor(
51 self._executor, 51 self._executor,
52 self._load, 52 self._load_and_warmup,
53 ) 53 )
54 54
55 def _load(self): 55 def _load_and_warmup(self):
56 from faster_whisper import WhisperModel 56 from faster_whisper import WhisperModel
57 57
58 if not (self._model_dir / "model.bin").is_file(): 58 if not (self._model_dir / "model.bin").is_file():
59 raise FileNotFoundError( 59 raise FileNotFoundError(
60 f"Model not found at {self._model_dir}. " 60 f"Model not found at {self._model_dir}. "
61 "Run: bazel run //dictation:download_model" 61 "Run: bazel run //dictation:download_model"
62 ) 62 )
63 return WhisperModel( 63 model = WhisperModel(
64 str(self._model_dir), 64 str(self._model_dir),
65 device="cuda", 65 device="cuda",
66 compute_type=self._compute_type, 66 compute_type=self._compute_type,
67 local_files_only=True, 67 local_files_only=True,
68 ) 68 )
69 # Loading weights does not initialize all CUDA kernels. Execute and
70 # consume one short silent inference now so the user's first utterance
71 # does not pay the one-time GPU setup cost.
72 segments, _ = model.transcribe(
73 np.zeros(8000, dtype=np.float32),
74 beam_size=1,
75 best_of=1,
76 condition_on_previous_text=False,
77 vad_filter=False,
78 without_timestamps=True,
79 )
80 list(segments)
81 return model
69 82
70 async def transcribe( 83 async def transcribe(
71 self, 84 self,
72 samples: np.ndarray, 85 samples: np.ndarray,
73 *, 86 *,
87 samples: np.ndarray, 100 samples: np.ndarray,
88 final: bool, 101 final: bool,
89 ) -> Transcript: 102 ) -> Transcript:
90 segments, info = self._model.transcribe( 103 segments, info = self._model.transcribe(
91 samples, 104 samples,
92 beam_size=5 if final else 1, 105 beam_size=1,
93 best_of=5 if final else 1, 106 best_of=1,
94 condition_on_previous_text=False, 107 condition_on_previous_text=False,
95 vad_filter=False, 108 vad_filter=False,
109 without_timestamps=True,
96 ) 110 )
97 text = "".join(segment.text for segment in segments).strip() 111 text = "".join(segment.text for segment in segments).strip()
98 return Transcript( 112 return Transcript(
99 text=text, 113 text=text,
100 language=info.language or "", 114 language=info.language or "",