📄 scripts/download-models.ts
const BASE_URL =
  "https://birdnet-team.github.io/real-time-pwa/models/birdnet";
const OUT_DIR = "static/models/birdnet";

async function download(url: string, dest: string) {
  console.log(`Downloading ${url}`);
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HTTP ${res.status} for ${url}`);
  await Deno.mkdir(dest.split("/").slice(0, -1).join("/"), { recursive: true });
  await Deno.writeFile(dest, new Uint8Array(await res.arrayBuffer()));
}

const modelJson = await fetch(`${BASE_URL}/model.json`).then((r) => r.json());
await Deno.mkdir(OUT_DIR, { recursive: true });
await Deno.writeTextFile(
  `${OUT_DIR}/model.json`,
  JSON.stringify(modelJson, null, 2),
);

const shards: string[] = modelJson.weightsManifest.flatMap(
  (m: { paths: string[] }) => m.paths,
);
for (const shard of shards) {
  await download(`${BASE_URL}/${shard}`, `${OUT_DIR}/${shard}`);
}

await download(
  `${BASE_URL}/labels/en_us.txt`,
  `${OUT_DIR}/labels/en_us.txt`,
);

console.log("Done. Model saved to", OUT_DIR);