Skip to content

Manual job flow

Use this flow when you need more control — for example, submitting many jobs and downloading their results later from a separate process.

import { VyonicaClient } from 'vyonica';
import fs from 'fs';
const client = new VyonicaClient({ apiKey: 'nvsk_...' });
const refWav = fs.readFileSync('reference.wav');
// Submit job
const job = await client.createCloneJob(refWav, {
text: 'Hello from Vyonica',
language: 'en',
name: 'my-voice',
});
console.log('Job created:', job.jobId);
// Poll manually
let status = await client.getJob(job.jobId);
while (status.status === 'pending' || status.status === 'processing') {
console.log('Status:', status.status);
await new Promise((r) => setTimeout(r, 2000));
status = await client.getJob(job.jobId);
}
// Download result
if (status.status === 'completed') {
const audio = await client.downloadOutput(job.jobId);
fs.writeFileSync('output.wav', audio);
console.log('Done!');
}

When to prefer this over clone()

  • You’re queuing many jobs in parallel and want to fan out submissions without holding open connections during inference.
  • You want to persist the jobId and download the result from a different process / machine.
  • You’re building a long-running worker that needs to inspect intermediate statuses.

For a single synchronous clone, client.clone() is simpler and uses the same primitives under the hood.