File size: 2,151 Bytes
78e34bc
7be4bb6
 
78e34bc
7be4bb6
 
 
 
 
 
 
 
 
78e34bc
7be4bb6
 
 
 
 
 
 
 
 
78e34bc
7be4bb6
 
 
 
 
 
 
 
 
 
 
 
 
 
78e34bc
7be4bb6
 
 
 
 
 
78e34bc
7be4bb6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78e34bc
7be4bb6
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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;
}