49 lines
2.0 KiB
JavaScript
49 lines
2.0 KiB
JavaScript
// Run in Node.js 22+ or a trusted backend, not in a browser with a private key.
|
|
import { writeFile } from "node:fs/promises";
|
|
|
|
const baseUrl = process.env.FASTVIDEO_BASE_URL || "http://127.0.0.1:8000/v1";
|
|
const headers = {
|
|
Authorization: `Bearer ${process.env.FASTVIDEO_API_KEY || "local"}`,
|
|
"Content-Type": "application/json",
|
|
};
|
|
const body = {
|
|
model: process.env.FASTVIDEO_MODEL || "stable-audio",
|
|
prompt: process.env.FASTVIDEO_PROMPT || "Rain on a metal roof, distant thunder.",
|
|
seconds: Number(process.env.FASTVIDEO_SECONDS || 6),
|
|
};
|
|
if (process.env.FASTVIDEO_VIDEO_REFERENCE) {
|
|
body.video_reference = { video_url: process.env.FASTVIDEO_VIDEO_REFERENCE };
|
|
}
|
|
|
|
let response = await fetch(`${baseUrl}/videos`, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify(body),
|
|
});
|
|
if (!response.ok) throw new Error(`Submit failed (${response.status}): ${await response.text()}`);
|
|
let job = await response.json();
|
|
console.log(`Submitted ${job.id}`);
|
|
|
|
const deadline = performance.now() + 1_800_000;
|
|
while (job.status === "queued" || job.status === "in_progress") {
|
|
const remaining = deadline - performance.now();
|
|
if (remaining <= 0) throw new Error(`Polling timed out; job ${job.id} may still be running`);
|
|
await new Promise((resolve) => setTimeout(resolve, Math.min(2000, remaining)));
|
|
response = await fetch(`${baseUrl}/videos/${job.id}`, { headers });
|
|
if (!response.ok) throw new Error(`Poll failed (${response.status}): ${await response.text()}`);
|
|
job = await response.json();
|
|
}
|
|
|
|
if (job.status !== "completed") {
|
|
throw new Error(`Audio job ${job.id} failed: ${job.error?.message || job.status}`);
|
|
}
|
|
if (job.media_type !== "audio/wav") {
|
|
throw new Error(`Expected audio/wav, got ${job.media_type}`);
|
|
}
|
|
|
|
response = await fetch(`${baseUrl}/videos/${job.id}/content`, { headers });
|
|
if (!response.ok) throw new Error(`Download failed (${response.status}): ${await response.text()}`);
|
|
const output = `${job.id}.wav`;
|
|
await writeFile(output, Buffer.from(await response.arrayBuffer()));
|
|
console.log(`Saved ${output}`);
|