const baseUrl = "https://apis.viggle.ai/v1";
const headers = {
Authorization: `Bearer ${process.env.VIGGLE_API_KEY}`,
"Content-Type": "application/json",
};
async function createMotion() {
const response = await fetch(`${baseUrl}/motions`, {
method: "POST",
headers,
body: JSON.stringify({
text: "a person doing a cartwheel",
duration_seconds: 5,
}),
});
if (!response.ok) {
const body = await response.json().catch(() => ({}));
throw new Error(`HTTP ${response.status}: ${JSON.stringify(body.error ?? body)}`);
}
return response.json();
}
async function waitForMotion(id) {
for (let attempt = 0; attempt < 60; attempt++) {
const response = await fetch(`${baseUrl}/motions/${id}`, {
headers: { Authorization: headers.Authorization },
});
if (!response.ok) {
const body = await response.json().catch(() => ({}));
throw new Error(`HTTP ${response.status}: ${JSON.stringify(body.error ?? body)}`);
}
const motion = await response.json();
if (["ready", "failed"].includes(motion.status)) return motion;
await new Promise((resolve) => setTimeout(resolve, 5000));
}
throw new Error(`Timed out waiting for motion ${id}`);
}
const created = await createMotion();
const motion = await waitForMotion(created.id);
if (motion.status !== "ready") {
throw new Error(`Motion failed: ${JSON.stringify(motion.error)}`);
}
const exportResponse = await fetch(
`${baseUrl}/motions/${motion.id}/export?download_type=mixamo`,
{ headers: { Authorization: headers.Authorization } },
);
if (!exportResponse.ok) {
const body = await exportResponse.json().catch(() => ({}));
throw new Error(`HTTP ${exportResponse.status}: ${JSON.stringify(body.error ?? body)}`);
}
const exported = await exportResponse.json();
console.log(exported.glb_url);