function updateGetModelProgress(name, loaded, total) { const progressElement = document.getElementById('model-progress'); if (total === 0) { progressElement.innerHTML = `Model ${name} is already in local cache`; return; } const percent = ((loaded / total) * 100).toFixed(2); let progress; if (loaded >= total) { progress = "Downloaded"; } else { progress = "Downloading"; } progressElement.innerHTML = `${progress} model ${name}: Total ${total} bytes, loaded ${loaded} bytes, ${percent}%`; } // Get model via Origin Private File System async function getModelOPFS(name, url, updateModel) { const root = await navigator.storage.getDirectory(); let fileHandle; async function updateFile() { const response = await fetch(url); const buffer = await readResponse(name, response, updateGetModelProgress); fileHandle = await root.getFileHandle(name, {create: true}); const writable = await fileHandle.createWritable(); await writable.write(buffer); await writable.close(); return buffer; } if (updateModel) { return await updateFile(); } try { fileHandle = await root.getFileHandle(name); const blob = await fileHandle.getFile(); updateGetModelProgress(name, 0, 0); return await blob.arrayBuffer(); } catch (e) { return await updateFile(); } } async function readResponse(name, response, progressCallback) { const contentLength = response.headers.get('Content-Length'); let total = parseInt(contentLength ?? '0'); let buffer = new Uint8Array(total); let loaded = 0; const reader = response.body.getReader(); async function read() { const {done, value} = await reader.read(); if (done) return; let newLoaded = loaded + value.length; if (newLoaded > total) { total = newLoaded; let newBuffer = new Uint8Array(total); newBuffer.set(buffer); buffer = newBuffer; } buffer.set(value, loaded); loaded = newLoaded; if (progressCallback) { progressCallback(name, loaded, total); } return read(); } await read(); return buffer; }