Offer Parakeet in the picker as English-only, hide it on phones, and explain the missing language controls
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
708fae5778
commit
12e0f6678b
+43
-14
@@ -36,9 +36,15 @@ import {
|
||||
estimatePeakLoadBytes,
|
||||
formatModelSize,
|
||||
getModel,
|
||||
modelFamily,
|
||||
resolveDefaultDtype,
|
||||
} from "./lib/models";
|
||||
import { shouldWarnBeforeLoad, type MobileMemoryHint } from "./lib/mobileMemoryGuard";
|
||||
import {
|
||||
isModelAllowedOnDevice,
|
||||
modelsForDevice,
|
||||
shouldWarnBeforeLoad,
|
||||
type MobileMemoryHint,
|
||||
} from "./lib/mobileMemoryGuard";
|
||||
import {
|
||||
applyLoadProgress,
|
||||
initialLoadProgress,
|
||||
@@ -68,6 +74,16 @@ interface AppErrorState {
|
||||
|
||||
const MODEL_IDS = MODELS.map((model) => model.id);
|
||||
|
||||
/** Device signals for the mobile memory guard (D-027) and desktop-only models (D-WS7a). */
|
||||
function memoryHint(): MobileMemoryHint {
|
||||
const nav = typeof navigator !== "undefined" ? navigator : undefined;
|
||||
return {
|
||||
userAgent: nav?.userAgent,
|
||||
maxTouchPoints: nav?.maxTouchPoints,
|
||||
deviceMemoryGB: (nav as (Navigator & { deviceMemory?: number }) | undefined)?.deviceMemory,
|
||||
};
|
||||
}
|
||||
|
||||
export function App() {
|
||||
const workerRef = useRef<Worker | null>(null);
|
||||
|
||||
@@ -260,15 +276,7 @@ export function App() {
|
||||
const targetModel = getModel(forModelId);
|
||||
if (!targetModel) return false;
|
||||
const peakBytes = estimatePeakLoadBytes(targetModel, resolveDefaultDtype(forModelId, device));
|
||||
const hint: MobileMemoryHint = {
|
||||
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : undefined,
|
||||
maxTouchPoints: typeof navigator !== "undefined" ? navigator.maxTouchPoints : undefined,
|
||||
deviceMemoryGB:
|
||||
typeof navigator !== "undefined"
|
||||
? (navigator as Navigator & { deviceMemory?: number }).deviceMemory
|
||||
: undefined,
|
||||
};
|
||||
return shouldWarnBeforeLoad(hint, peakBytes);
|
||||
return shouldWarnBeforeLoad(memoryHint(), peakBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,6 +289,9 @@ export function App() {
|
||||
function confirmRiskyMobileLoad(forModelId: string, preference: DevicePreference): boolean {
|
||||
const targetModel = getModel(forModelId);
|
||||
if (!targetModel) return true;
|
||||
// Desktop-only models are never offered on phones (D-WS7a); this guards
|
||||
// any path that could still name one (e.g. a stale selection).
|
||||
if (!isModelAllowedOnDevice(targetModel, memoryHint())) return false;
|
||||
const device = guessDevice(preference);
|
||||
const key = overrideKey(forModelId, device);
|
||||
if (mobileWarningAcknowledged.current.has(key)) return true;
|
||||
@@ -979,9 +990,15 @@ export function App() {
|
||||
const serverSelected =
|
||||
engineChoice === "server" && auth.user !== null && serverStatus?.available === true;
|
||||
|
||||
const availableModels = serverSelected
|
||||
? MODELS.filter((m) => m.fasterWhisperModel === "large-v3-turbo" || m.fasterWhisperModel === "medium.en")
|
||||
: MODELS;
|
||||
// Phones never see desktop-only models (Parakeet, D-WS7a); the server
|
||||
// engine only offers what the sidecar runs.
|
||||
const availableModels = modelsForDevice(
|
||||
serverSelected
|
||||
? MODELS.filter((m) => m.fasterWhisperModel === "large-v3-turbo" || m.fasterWhisperModel === "medium.en")
|
||||
: MODELS,
|
||||
memoryHint(),
|
||||
);
|
||||
const parakeetSelected = modelFamily(model) === "parakeet";
|
||||
|
||||
useEffect(() => {
|
||||
if (serverSelected) {
|
||||
@@ -1032,6 +1049,15 @@ export function App() {
|
||||
serverEngine={serverSelected}
|
||||
/>
|
||||
|
||||
{/* Parakeet has no language or task choice (D-WS7a) — say so where
|
||||
those controls would be, rather than leaving their absence unexplained. */}
|
||||
{parakeetSelected && (
|
||||
<p className="model-language-note">
|
||||
Parakeet understands English only, so there is no language or translation
|
||||
choice. For other languages, pick a Multilingual Whisper model.
|
||||
</p>
|
||||
)}
|
||||
|
||||
{model?.multilingual && (
|
||||
<TranscriptionOptions
|
||||
language={language}
|
||||
@@ -1069,7 +1095,10 @@ export function App() {
|
||||
models — every pass pads to a full 30 s Whisper window (D-024), so
|
||||
tentative text lags and the stop drain grows. Say so instead of
|
||||
looking frozen. */}
|
||||
{liveActive && activeDevice === "wasm" && (model?.encoderParamsM ?? 0) >= 300 && (
|
||||
{liveActive &&
|
||||
activeDevice === "wasm" &&
|
||||
!parakeetSelected &&
|
||||
(model?.encoderParamsM ?? 0) >= 300 && (
|
||||
<p className="live-hint" role="status">
|
||||
{model?.displayName} runs slower than real time on the WASM backend, so
|
||||
live text will lag behind speech. A smaller model (Tiny, Base or Small)
|
||||
|
||||
@@ -158,7 +158,16 @@ export function ModelPicker({
|
||||
disabled={disabled}
|
||||
onChange={() => onSelect(model.id)}
|
||||
/>
|
||||
<span className="model-option-name">{model.displayName}</span>
|
||||
<span className="model-option-name">
|
||||
{model.displayName}
|
||||
{model.family === "parakeet" && (
|
||||
// Not Whisper (D-WS7a): say what it is good for and
|
||||
// what it can't do, in plain words.
|
||||
<span className="model-option-note">
|
||||
Not Whisper · English only · fast on long recordings
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<span className="model-option-meta">
|
||||
{isDownloaded && (
|
||||
<span
|
||||
|
||||
+9
-1
@@ -423,6 +423,13 @@ body {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* One-line description under a model name (Parakeet, D-WS7a). */
|
||||
.model-option-note {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.model-option-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -640,7 +647,8 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
.live-hint {
|
||||
.live-hint,
|
||||
.model-language-note {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.9rem;
|
||||
|
||||
Reference in New Issue
Block a user