Projects are the top-level resource in Youka. Each project owns its source file, separated stems, synced lyrics, exports, and project settings.
Creating a project
For most cases, use client.projects.create() — it handles uploads for you.
const operation = await client.projects.create({
source: { type: "path", path: "./song.mp3" },
lyricsSource: { type: "transcribe" },
});
// => ProjectOperation
Source types
Reads a file from disk.source: {
type: "path",
path: "./song.mp3",
contentType: "audio/mpeg", // optional, inferred if omitted
}
In-memory Blob, File, ArrayBuffer, or Uint8Array.source: {
type: "bytes",
data: fileBuffer,
filename: "song.mp3",
contentType: "audio/mpeg", // optional
}
Remote HTTP or HTTPS URL.Supported hosted pages depend on yt-dlp. See the supported URLs list.source: {
type: "url",
url: "https://example.com/song.mp4",
maxVideoQuality: "1080p", // optional: "720p", "1080p", "4k", or "best"
}
maxVideoQuality controls the maximum downloaded video quality for URL
sources. It defaults to 1080p. The SDK uses the best available quality up
to that limit, and falls back to the best available format if the platform
does not expose a capped stream. Use best for no cap.On Node.js and Bun, the SDK automatically ensures the required URL
dependency binaries (ffmpeg, ffprobe, yt-dlp) on first use. The
CLI equivalent is youka deps ensure --for url.
Other fields
Project title. Defaults to the source filename.
Apply a reusable preset at creation time.
Configure lyrics sync. See below.
Lyrics sources
// Transcribe lyrics from the audio
lyricsSource: {
type: "transcribe",
syncModel: "audioshake-transcription", // optional
language: "en", // optional
}
// Align exact lyrics to the audio
lyricsSource: {
type: "align",
lyrics: "First line\nSecond line\n...",
syncModel: "audioshake-alignment",
}
client.projects.create() also accepts a low-level inputFile source when you already have an uploaded inputFileId.
const upload = await client.uploads.create({
filename: "song.mp3",
contentType: "audio/mpeg",
contentLength: buffer.byteLength,
});
await client.uploads.upload(upload.uploadUrl, buffer, {
contentType: "audio/mpeg",
});
const operation = await client.projects.create({
source: {
type: "inputFile",
inputFileId: upload.inputFileId,
filename: "song.mp3",
},
title: "My Song",
});
Quote the credits required to create a project without creating it.
const quote = await client.projects.quote({
source: { type: "path", path: "./song.mp3" },
lyricsSource: { type: "transcribe", language: "en" },
splitModel: "mdx23c",
});
console.log(quote.creditsRequired, quote.sufficientBalance);
client.projects.quote(...) accepts the same source forms as
client.projects.create(...), including URL maxVideoQuality. If you already
know the media duration and do not want to upload the file just to quote, pass
the low-level REST shape:
const quote = await client.projects.quote({
durationSeconds: 210,
lyricsSource: null,
splitModel: "mdx23c",
});
client.uploads.create(body, options?)
Allocate an upload slot and get a signed URL.
const upload = await client.uploads.create({
filename: "song.mp3",
contentType: "audio/mpeg",
contentLength: 4_521_344,
});
// => { inputFileId, uploadUrl }
client.uploads.upload(uploadUrl, body, options?)
PUT the file bytes to the signed URL.
await client.uploads.upload(upload.uploadUrl, fileBuffer, {
contentType: "audio/mpeg",
signal: abortController.signal,
});
Any fetch-compatible body: Blob, File, ArrayBuffer, Uint8Array,
ReadableStream, or string.
Throws YoukaRequestError with code UPLOAD_FAILED if the upload returns a non-2xx status.
client.projects.get(projectId, options?)
Fetch the full project state, including stems, lyrics, and exports.
const project = await client.projects.get("prj_abc123");
console.log(project.title, project.stems, project.lyrics);
client.projects.update(projectId, body, options?)
Patch project metadata.
const project = await client.projects.update("prj_abc123", {
title: "Updated title",
artists: ["Artist name"],
});
Pass at least one of title or artists.
client.projects.list(options?)
List every project owned by the authenticated account.
const projects = await client.projects.list();
projects.forEach((p) => console.log(p.id, p.title));
Returns an array of project list items (a leaner shape than getProject).
client.projects.delete(projectId, options?)
Delete a project and all its associated stems, lyrics, and exports.
await client.projects.delete("prj_abc123", {
idempotencyKey: "delete-prj_abc123",
});
Deletion is permanent. Pair with an idempotency key so retries are safe.
What’s next
- Stems — re-run stem separation
- Lyrics sync — re-sync lyrics
- Exports — render finished videos
- Tasks — wait on project operations with
client.projects.wait