Name Message Date
📄 download-models.ts Locales 1 month ago
📄 scripts/download-models.ts
const BASE_URL = "https://github.com/birdnet-team/real-time-pwa/raw/refs/heads/main/public/models/birdnet";
const OUT_DIR = "static/models/birdnet";
const locales = [
  "af",
  "ar",
  "cs",
  "da",
  "de",
  "en_uk",
  "en_us",
  "es",
  "fi",
  "fr",
  "hu",
  "it",
  "ja",
  "ko",
  "nl",
  "no",
  "pl",
  "pt",
  "ro",
  "ru",
  "sk",
  "sl",
  "sv",
  "th",
  "tr",
  "uk",
  "zh",
];

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 Deno.mkdir(`${OUT_DIR}/labels`, { recursive: true });
for (const locale of locales) {
  const url = `${BASE_URL}/labels/${locale}.txt`;
  console.log(`Downloading labels: ${url}`);
  const text = await fetch(url).then((r) => {
    if (!r.ok) throw new Error(`HTTP ${r.status} for ${url}`);
    return r.text();
  });
  const labels = text
    .split("\n")
    .filter(Boolean)
    .map((line) => {
      const idx = line.indexOf("_");
      return {
        scientificName: idx >= 0 ? line.slice(0, idx) : line,
        commonName: idx >= 0 ? line.slice(idx + 1) : line,
      };
    });
  await Deno.writeTextFile(
    `${OUT_DIR}/labels/${locale}.json`,
    JSON.stringify(labels),
  );
}

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