Skip to content

Commit 8a849ec

Browse files
committed
chore: alert dialogs in case of recording attempt without any models
1 parent 02447b6 commit 8a849ec

2 files changed

Lines changed: 76 additions & 11 deletions

File tree

apps/desktop/src/main/managers/recording-manager.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { ipcMain, app } from "electron";
1+
import { ipcMain, app, dialog } from "electron";
2+
import type { TranscriptionService } from "../../services/transcription-service";
23
import { EventEmitter } from "node:events";
34
import { logger, logPerformance } from "../logger";
45
import { ServiceManager } from "./service-manager";
@@ -154,6 +155,30 @@ export class RecordingManager extends EventEmitter {
154155

155156
public async startRecording(mode: "ptt" | "hands-free") {
156157
await this.recordingMutex.runExclusive(async () => {
158+
// Check if transcription service is available and has models
159+
const transcriptionService = this.serviceManager.getService(
160+
"transcriptionService",
161+
);
162+
if (!transcriptionService) {
163+
logger.audio.error("Transcription service not available");
164+
// Show error dialog
165+
dialog.showErrorBox(
166+
"Recording Failed",
167+
"Transcription service is not available. Please restart the application.",
168+
);
169+
return;
170+
}
171+
172+
const hasModels = await transcriptionService.isModelAvailable();
173+
if (!hasModels) {
174+
logger.audio.error("No transcription models available");
175+
// Show error dialog
176+
dialog.showErrorBox(
177+
"No Models Available",
178+
"Please download a transcription model from Speech Models before recording.",
179+
);
180+
return;
181+
}
157182
// if we were previously in ptt mode, we override
158183
// priority is given to hands-free mode
159184
// we don't need to check the other way around

apps/desktop/src/services/transcription-service.ts

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { logger } from "../main/logger";
1414
import { v4 as uuid } from "uuid";
1515
import { VADService } from "./vad-service";
1616
import { Mutex } from "async-mutex";
17+
import { app, dialog } from "electron";
1718

1819
/**
1920
* Service for audio transcription and optional formatting
@@ -22,7 +23,7 @@ export class TranscriptionService {
2223
private whisperProvider: WhisperProvider;
2324
private openRouterProvider: OpenRouterProvider | null = null;
2425
private formatterEnabled = false;
25-
private streamingSessions: Map<string, StreamingSession> = new Map();
26+
private streamingSessions = new Map<string, StreamingSession>();
2627
private vadService: VADService | null;
2728
private settingsService: SettingsService;
2829
private vadMutex: Mutex;
@@ -53,9 +54,29 @@ export class TranscriptionService {
5354
const shouldPreload = transcriptionSettings?.preloadWhisperModel !== false; // Default to true
5455

5556
if (shouldPreload) {
56-
logger.transcription.info("Preloading Whisper model...");
57-
await this.preloadWhisperModel();
58-
logger.transcription.info("Whisper model preloaded successfully");
57+
// Check if models are available for preloading
58+
const hasModels = await this.isModelAvailable();
59+
if (hasModels) {
60+
logger.transcription.info("Preloading Whisper model...");
61+
await this.preloadWhisperModel();
62+
logger.transcription.info("Whisper model preloaded successfully");
63+
} else {
64+
logger.transcription.info(
65+
"Whisper model preloading skipped - no models available",
66+
);
67+
if (app.isReady()) {
68+
setTimeout(() => {
69+
dialog.showMessageBox({
70+
type: "warning",
71+
title: "No Transcription Models",
72+
message: "No transcription models are available.",
73+
detail:
74+
"To use voice transcription, please download a model from Speech Models.",
75+
buttons: ["OK"],
76+
});
77+
}, 2000); // Delay to ensure windows are ready
78+
}
79+
}
5980
} else {
6081
logger.transcription.info("Whisper model preloading disabled");
6182
}
@@ -77,6 +98,20 @@ export class TranscriptionService {
7798
}
7899
}
79100

101+
/**
102+
* Check if transcription models are available (real-time check)
103+
*/
104+
public async isModelAvailable(): Promise<boolean> {
105+
try {
106+
const modelManager = this.whisperProvider["modelManager"];
107+
const availableModels = await modelManager.getValidDownloadedModels();
108+
return Object.keys(availableModels).length > 0;
109+
} catch (error) {
110+
logger.transcription.error("Failed to check model availability:", error);
111+
return false;
112+
}
113+
}
114+
80115
/**
81116
* Handle model change - dispose old model and load new one if preloading is enabled
82117
*/
@@ -85,19 +120,24 @@ export class TranscriptionService {
85120
// Dispose current model
86121
await this.whisperProvider.dispose();
87122

88-
// Check if preloading is enabled
123+
// Check if preloading is enabled and models are available
89124
if (this.settingsService) {
90125
const transcriptionSettings =
91126
await this.settingsService.getTranscriptionSettings();
92127
const shouldPreload =
93128
transcriptionSettings?.preloadWhisperModel !== false;
94129

95130
if (shouldPreload) {
96-
logger.transcription.info(
97-
"Reloading Whisper model after model change...",
98-
);
99-
await this.whisperProvider.preloadModel();
100-
logger.transcription.info("Whisper model reloaded successfully");
131+
const hasModels = await this.isModelAvailable();
132+
if (hasModels) {
133+
logger.transcription.info(
134+
"Reloading Whisper model after model change...",
135+
);
136+
await this.whisperProvider.preloadModel();
137+
logger.transcription.info("Whisper model reloaded successfully");
138+
} else {
139+
logger.transcription.info("No models available to preload");
140+
}
101141
}
102142
}
103143
} catch (error) {

0 commit comments

Comments
 (0)