resolve merge

This commit is contained in:
Jordan 2025-03-03 05:46:00 -08:00
parent d00e6d62ff
commit d15916f3e3

View File

@ -1,6 +1,6 @@
import { Platform } from "react-native"; import { Platform } from "react-native";
import * as FileSystem from "expo-file-system"; import * as FileSystem from "expo-file-system";
import { File, Paths } from 'expo-file-system/next'; import { File, Paths } from "expo-file-system/next";
import { getDb } from "./db"; import { getDb } from "./db";
export const WHISPER_MODEL_PATH = Paths.join(FileSystem.documentDirectory || "file:///", "whisper"); export const WHISPER_MODEL_PATH = Paths.join(FileSystem.documentDirectory || "file:///", "whisper");
@ -71,9 +71,9 @@ export const WHISPER_MODELS = {
[key: whisper_model_tag_t]: { source: string; target: string; label: string }; [key: whisper_model_tag_t]: { source: string; target: string; label: string };
}; };
export function getWhisperTarget(key : whisper_model_tag_t) { export function getWhisperTarget(key: whisper_model_tag_t) {
const path = Paths.join(WHISPER_MODEL_DIR, WHISPER_MODELS[key].target); const path = Paths.join(WHISPER_MODEL_DIR, WHISPER_MODELS[key].target);
return new File(path) return new File(path);
} }
export type download_status = export type download_status =
@ -89,7 +89,7 @@ export type download_status =
}; };
export async function getModelFileSize(whisper_model: whisper_model_tag_t) { export async function getModelFileSize(whisper_model: whisper_model_tag_t) {
const target = getWhisperTarget(whisper_model) const target = getWhisperTarget(whisper_model);
if (!target.exists) return undefined; if (!target.exists) return undefined;
return target.size; return target.size;
} }
@ -131,26 +131,29 @@ export async function getWhisperDownloadStatus(
}; };
} }
export function whisperFileExists(whisper_model : whisper_model_tag_t) { export function whisperFileExists(whisper_model: whisper_model_tag_t) {
const target = getWhisperTarget(whisper_model); const target = getWhisperTarget(whisper_model);
return target.exists return target.exists;
} }
export type DownloadCallback = (arg0 : FileSystem.DownloadProgressData) => any; export type DownloadCallback = (arg0: FileSystem.DownloadProgressData) => any;
async function updateModelSize(model_label : string, size : number) { async function updateModelSize(model_label: string, size: number) {
const db = await getDb(); const db = await getDb();
const query = "INSERT OR REPLACE INTO whisper_models (model, bytes_total) VALUES (?, ?)" const query =
"INSERT OR REPLACE INTO whisper_models (model, bytes_total) VALUES (?, ?)";
const stmt = db.prepareSync(query); const stmt = db.prepareSync(query);
stmt.executeSync(model_label, size); stmt.executeSync(model_label, size);
} }
async function getExpectedModelSize(model_label : string) : Promise<number | undefined> { async function getExpectedModelSize(
model_label: string
): Promise<number | undefined> {
const db = await getDb(); const db = await getDb();
const query = "SELECT bytes_total FROM whisper_models WHERE model = ?" const query = "SELECT bytes_total FROM whisper_models WHERE model = ?";
const stmt = db.prepareSync(query); const stmt = db.prepareSync(query);
const curs = stmt.executeSync(model_label); const curs = stmt.executeSync(model_label);
const row = curs.getFirstSync() const row = curs.getFirstSync();
return row ? row.bytes_total : undefined; return row ? row.bytes_total : undefined;
} }
@ -164,54 +167,76 @@ export async function initiateWhisperDownload(
onDownload: undefined, onDownload: undefined,
} }
) { ) {
console.debug("Starting download of %s", whisper_model); console.debug("Starting download of %s", whisper_model);
await FileSystem.makeDirectoryAsync(WHISPER_MODEL_PATH, { if (!WHISPER_MODEL_DIR.exists) {
intermediates: true, try {
}); await FileSystem.makeDirectoryAsync(WHISPER_MODEL_PATH, {
intermediates: true,
const whisperTarget = getWhisperTarget(whisper_model); });
} catch (err) {
// If the target file exists, delete it. console.error("Could not create %s : %s", WHISPER_MODEL_PATH, err);
if (whisperTarget.exists) { throw err;
if (options.force_redownload) {
whisperTarget.delete()
} else {
const expected = await getExpectedModelSize(whisper_model);
if (whisperTarget.size === expected) {
console.warn("Whisper model for %s already exists", whisper_model);
return undefined;
}
} }
console.debug("Created %s", WHISPER_MODEL_DIR);
} }
// Initiate a new resumable download. try {
const spec = WHISPER_MODELS[whisper_model]; const whisperTarget = getWhisperTarget(whisper_model);
console.log("Downloading %s", spec.source); // If the target file exists, delete it.
try {
if (whisperTarget.exists) {
if (options.force_redownload) {
whisperTarget.delete();
} else {
const expected = await getExpectedModelSize(whisper_model);
if (whisperTarget.size === expected) {
console.warn("Whisper model for %s already exists", whisper_model);
return undefined;
}
}
}
} catch (err) {
console.error(
"Could not determine if %s exists: %s",
whisperTarget.uri,
err
);
throw err;
}
const resumable = FileSystem.createDownloadResumable( // Initiate a new resumable download.
spec.source, const spec = WHISPER_MODELS[whisper_model];
whisperTarget.uri,
{ console.log("Downloading %s", spec.source);
md5: true,
headers: { const resumable = FileSystem.createDownloadResumable(
'Content-Type': 'application/octet-stream', spec.source,
'Accept': 'application/octet-stream', whisperTarget.uri,
{},
// 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) => {
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);
}, },
sessionType: FileSystem.FileSystemSessionType.BACKGROUND whisperTarget.exists ? whisperTarget.base64() : 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) => {
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,
);
return resumable; return resumable;
} } catch (err) {
console.error(
"Could not get whisper target for %s: %s",
whisper_model,
err
);
}
}