detemine root cause of download issue.
This commit is contained in:
parent
87446784ae
commit
4549442bd8
@ -136,12 +136,32 @@ export function whisperFileExists(whisper_model : whisper_model_tag_t) {
|
||||
return target.exists
|
||||
}
|
||||
|
||||
export async function downloadWhisperModel(
|
||||
export type DownloadCallback = (arg0 : FileSystem.DownloadProgressData) => any;
|
||||
|
||||
async function updateModelSize(model_label : string, size : number) {
|
||||
const db = await getDb();
|
||||
const query = "INSERT OR REPLACE INTO whisper_models (model, bytes_total) VALUES (?, ?)"
|
||||
const stmt = db.prepareSync(query);
|
||||
stmt.executeSync(model_label, size);
|
||||
}
|
||||
|
||||
async function getExpectedModelSize(model_label : string) : Promise<number | undefined> {
|
||||
const db = await getDb();
|
||||
const query = "SELECT bytes_total FROM whisper_models WHERE model = ?"
|
||||
const stmt = db.prepareSync(query);
|
||||
const curs = stmt.executeSync(model_label);
|
||||
const row = curs.getFirstSync()
|
||||
return row ? row.bytes_total : undefined;
|
||||
}
|
||||
|
||||
export async function initiateWhisperDownload(
|
||||
whisper_model: whisper_model_tag_t,
|
||||
options: {
|
||||
force_redownload: boolean;
|
||||
force_redownload?: boolean;
|
||||
onDownload?: DownloadCallback | undefined;
|
||||
} = {
|
||||
force_redownload: false,
|
||||
onDownload: undefined,
|
||||
}
|
||||
) {
|
||||
|
||||
@ -161,34 +181,33 @@ export async function downloadWhisperModel(
|
||||
if (options.force_redownload) {
|
||||
whisperTarget.delete()
|
||||
} else {
|
||||
console.warn("Whisper model for %s already exists", whisper_model);
|
||||
return;
|
||||
const expected = await getExpectedModelSize(whisper_model);
|
||||
if (whisperTarget.size === expected) {
|
||||
console.warn("Whisper model for %s already exists", whisper_model);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initiate a new resumable download.
|
||||
const spec = WHISPER_MODELS[whisper_model];
|
||||
|
||||
console.log("Downloading %s", spec.source);
|
||||
|
||||
const resumable = FileSystem.createDownloadResumable(
|
||||
spec.source,
|
||||
whisperTarget.uri,
|
||||
undefined,
|
||||
{},
|
||||
// On each data write, update the whisper model download status.
|
||||
// Note that since createDownloadResumable callback only works in the foreground,
|
||||
// a background process will also be updating the file size.
|
||||
async (data) => {
|
||||
const db = await getDb();
|
||||
const args = [
|
||||
whisper_model,
|
||||
data.totalBytesWritten,
|
||||
data.totalBytesExpectedToWrite,
|
||||
];
|
||||
console.log("%s, %s of %s", whisper_model, data.totalBytesWritten, data.totalBytesExpectedToWrite);
|
||||
await db.runAsync(
|
||||
`INSERT OR REPLACE INTO whisper_models (model, bytes_done, bytes_remaining) VALUES (?, ?, ?)`,
|
||||
args
|
||||
);
|
||||
}
|
||||
console.log("%s: %d bytes of %d", whisperTarget.uri, data.totalBytesWritten, data.totalBytesExpectedToWrite);
|
||||
await updateModelSize(whisper_model, data.totalBytesExpectedToWrite)
|
||||
if (options.onDownload) await options.onDownload(data);
|
||||
},
|
||||
whisperTarget.exists ? whisperTarget.base64() : undefined,
|
||||
);
|
||||
|
||||
await resumable.downloadAsync();
|
||||
return resumable;
|
||||
}
|
@ -6,11 +6,12 @@ import { Settings } from "@/app/lib/settings";
|
||||
import { LanguageServer, fetchWithTimeout } from "@/app/i18n/api";
|
||||
import { Picker } from "@react-native-picker/picker";
|
||||
import { longLang } from "@/app/i18n/lang";
|
||||
import FileSystem, { DownloadResumable } from "expo-file-system";
|
||||
import { LIBRETRANSLATE_BASE_URL } from "@/constants/api";
|
||||
import {
|
||||
WHISPER_MODELS,
|
||||
WHISPER_MODEL_DIR,
|
||||
downloadWhisperModel,
|
||||
initiateWhisperDownload,
|
||||
download_status,
|
||||
getWhisperDownloadStatus,
|
||||
getWhisperTarget,
|
||||
@ -53,6 +54,10 @@ const SettingsComponent: React.FC = () => {
|
||||
const [langServerConn, setLangServerConn] = useState<
|
||||
undefined | connection_test_t
|
||||
>();
|
||||
const [whisperDownloadProgress, setWhisperDownloadProgress] = useState<
|
||||
FileSystem.DownloadProgressData | undefined
|
||||
>();
|
||||
const [downloader, setDownloader] = useState<DownloadResumable | undefined>();
|
||||
|
||||
const fillHostLanguageOptions = async () => {
|
||||
const settings = await Settings.getDefault();
|
||||
@ -73,7 +78,7 @@ const SettingsComponent: React.FC = () => {
|
||||
error: `Could not connect to ${libretranslateBaseUrl}: ${err}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
@ -147,12 +152,25 @@ const SettingsComponent: React.FC = () => {
|
||||
|
||||
const doReadownload = async () => {
|
||||
if (!whisperModel) return;
|
||||
await downloadWhisperModel(whisperModel, { force_redownload: true });
|
||||
await initiateWhisperDownload(whisperModel, {
|
||||
force_redownload: true,
|
||||
onDownload: setWhisperDownloadProgress,
|
||||
});
|
||||
};
|
||||
|
||||
const doDownload = async () => {
|
||||
if (!whisperModel) return;
|
||||
await downloadWhisperModel(whisperModel);
|
||||
try {
|
||||
setDownloader(
|
||||
await initiateWhisperDownload(whisperModel, {
|
||||
onDownload: setWhisperDownloadProgress,
|
||||
})
|
||||
);
|
||||
await downloader?.downloadAsync();
|
||||
console.log("completed download");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleHostLanguageChange = async (value: string) => {
|
||||
@ -217,28 +235,18 @@ const SettingsComponent: React.FC = () => {
|
||||
<Picker.Item key={key} label={label} value={key} />
|
||||
))}
|
||||
</Picker>
|
||||
{whisperModel && (
|
||||
<View>
|
||||
{downloadStatus?.status === "complete" ? (
|
||||
<Pressable onPress={doReadownload}>Re-Download</Pressable>
|
||||
) : downloadStatus?.status === "in_progress" ? (
|
||||
<Text>
|
||||
{(downloadStatus.bytes.done / downloadStatus.bytes.total) * 100.0}{" "}
|
||||
% complete
|
||||
{downloadStatus.bytes.done} bytes of {downloadStatus.bytes.total}
|
||||
</Text>
|
||||
) : (
|
||||
<View>
|
||||
<Pressable onPress={doDownload} style={styles.button}>
|
||||
<Text style={styles.buttonText}>Download</Text>
|
||||
</Pressable>
|
||||
<Text>
|
||||
This will download to {Paths.join(WHISPER_MODEL_DIR, WHISPER_MODELS[whisperModel].target)}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
<View>
|
||||
{ /* If there's a downloader, that means we're in the middle of a download */}
|
||||
{downloader && whisperDownloadProgress && (
|
||||
<Text>
|
||||
{whisperDownloadProgress.totalBytesWritten} of {whisperDownloadProgress.totalBytesExpectedToWrite}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
<Pressable onPress={doDownload} style={styles.button}>
|
||||
<Text style={styles.buttonText}>Download</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View>
|
||||
|
0
components/ui/WhisperDownloadButton.tsx
Normal file
0
components/ui/WhisperDownloadButton.tsx
Normal file
33
components/ui/WhisperDownloader.tsx
Normal file
33
components/ui/WhisperDownloader.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { Settings } from "@/app/lib/settings"
|
||||
import { WHISPER_MODELS } from "@/app/lib/whisper"
|
||||
import { Picker } from "@react-native-picker/picker"
|
||||
import { useEffect, useState } from "react"
|
||||
import { Pressable, View } from "react-native"
|
||||
|
||||
const WhisperDownloader = () => {
|
||||
|
||||
const [whisperModel, setWhisperModel] = useState<string|undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
const settings = await Settings.getDefault();
|
||||
setWhisperModel((await settings.getWhisperModel()) || "small");
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Picker
|
||||
selectedValue={whisperModel || ""}
|
||||
style={{ height: 50, width: "100%" }}
|
||||
onValueChange={setWhisperModel}
|
||||
accessibilityHint="whisper model"
|
||||
>
|
||||
{Object.entries(WHISPER_MODELS).map(([key, { label }]) => (
|
||||
<Picker.Item key={key} label={label} value={key} />
|
||||
))}
|
||||
</Picker>
|
||||
|
||||
<WhisperDownloadButton whisperModel={whisperModel} />
|
||||
|
||||
<WhisperDownloadInfo whisperModel={whisperModel} />
|
||||
</View>
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user