import fs from 'fs'; import path from 'path'; import os from 'os'; import https from 'https'; import yauzl from 'yauzl'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const URL = "https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip"; const MODEL_DIR = path.resolve(__dirname, "model"); async function main() { if (!fs.existsSync(MODEL_DIR)) { fs.mkdirSync(MODEL_DIR, { recursive: true }); } if (fs.existsSync(path.resolve(MODEL_DIR, "DONE"))) { console.log("Model already downloaded"); return; } const zip = path.resolve(os.tmpdir(), path.basename(URL)); await download(URL, zip); console.log("Downloaded model to", zip); await unzip(zip, MODEL_DIR); fs.unlinkSync(zip); } function download(url, to, redirect = 0) { if (redirect === 0) { console.log(`Downloading ${url} to ${to}`); } else { console.log(`Redirecting to ${url}`); } return new Promise((resolve, reject) => { if (!fs.existsSync(path.dirname(to))) { fs.mkdirSync(path.dirname(to), { recursive: true }); } let done = true; const file = fs.createWriteStream(to); const request = https.get(url, (res) => { if (res.statusCode === 302 && res.headers.location !== undefined) { done = false; file.close(); resolve(download(res.headers.location, to, redirect + 1)); return; } res.pipe(file); }); file.on("finish", () => { if (done) { resolve(to); } }); request.on("error", (err) => { fs.unlink(to, () => reject(err)); }); file.on("error", (err) => { fs.unlink(to, () => reject(err)); }); request.end(); }); } function unzip(zip, dest) { const dir = path.basename(zip, ".zip"); return new Promise((resolve, reject) => { yauzl.open(zip, { lazyEntries: true }, (err, zipfile) => { if (err) { reject(err); } zipfile.readEntry(); zipfile .on("entry", (entry) => { if (/\/$/.test(entry.fileName)) { zipfile.readEntry(); } else { zipfile.openReadStream(entry, (err, stream) => { if (err) { reject(err); } const f = path.resolve(dest, entry.fileName.replace(`${dir}/`, "")); if (!fs.existsSync(path.dirname(f))) { fs.mkdirSync(path.dirname(f), { recursive: true }); console.log("Created directory", path.dirname(f)); } stream.pipe(fs.createWriteStream(f)); stream .on("end", () => { console.log("Extracted", f); zipfile.readEntry(); }) .on("error", (err) => { reject(err); }); }); } }) .on("error", (err) => { reject(err); }) .on("end", () => { console.log("Extracted all files"); fs.writeFileSync(path.resolve(dest, "DONE"), ""); }) .on("close", () => { resolve(); }); }); }); } main().catch(console.error);