项目是 Youka 中的顶层资源。每个项目都拥有其源文件、分离的 stem、同步歌词、导出结果以及项目设置。
创建项目
在大多数情况下,使用 client.projects.create() ——它会为你处理上传。
const operation = await client.projects.create({
source: { type: "path", path: "./song.mp3" },
lyricsSource: { type: "transcribe" },
});
// => ProjectOperation
Source 类型
从磁盘读取文件。source: {
type: "path",
path: "./song.mp3",
contentType: "audio/mpeg", // optional, inferred if omitted
}
内存中的 Blob、File、ArrayBuffer 或 Uint8Array。source: {
type: "bytes",
data: fileBuffer,
filename: "song.mp3",
contentType: "audio/mpeg", // optional
}
远程 HTTP 或 HTTPS URL。支持的托管页面取决于 yt-dlp。请参见支持的 URL 列表。source: {
type: "url",
url: "https://example.com/song.mp4",
maxVideoQuality: "1080p", // optional: "720p", "1080p", "4k", or "best"
}
maxVideoQuality 控制 URL source 的最大下载视频质量。默认值为 1080p。SDK 会在该上限之内使用可用的最佳质量;如果平台不提供带上限的流,则会回退到可用的最佳格式。若不设上限,请使用 best。在 Node.js 和 Bun 上,SDK 会在首次使用时自动确保所需的 URL 依赖二进制文件(ffmpeg、ffprobe、yt-dlp)。对应的 CLI 命令是 youka deps ensure --for url。
其他字段
Lyrics source
// 从音频转写歌词
lyricsSource: {
type: "transcribe",
syncModel: "audioshake-transcription", // optional
language: "en", // optional
}
// 将精确歌词与音频对齐
lyricsSource: {
type: "align",
lyrics: "First line\nSecond line\n...",
syncModel: "audioshake-alignment",
}
当你已经有上传好的 inputFileId 时,client.projects.create() 也接受更底层的 inputFile source。
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",
});
在不创建项目的情况下,报价创建项目所需的 credits。
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(...) 接受与 client.projects.create(...) 相同的 source 形式,包括 URL 的 maxVideoQuality。如果你已经知道媒体时长,并且不想为了报价而上传文件,可以传入更底层的 REST 形状:
const quote = await client.projects.quote({
durationSeconds: 210,
lyricsSource: null,
splitModel: "mdx23c",
});
client.uploads.create(body, options?)
分配一个上传槽位并获取签名 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 方式上传到签名 URL。
await client.uploads.upload(upload.uploadUrl, fileBuffer, {
contentType: "audio/mpeg",
signal: abortController.signal,
});
任何与 fetch 兼容的 body:Blob、File、ArrayBuffer、Uint8Array、ReadableStream 或 string。
如果上传返回非 2xx 状态,会抛出 code 为 UPLOAD_FAILED 的 YoukaRequestError。
client.projects.get(projectId, options?)
获取完整的项目状态,包括 stem、歌词和导出结果。
const project = await client.projects.get("prj_abc123");
console.log(project.title, project.stems, project.lyrics);
client.projects.update(projectId, body, options?)
对项目元数据打补丁更新。
const project = await client.projects.update("prj_abc123", {
title: "Updated title",
artists: ["Artist name"],
});
至少传入 title 或 artists 之一。
client.projects.list(options?)
列出经认证账户拥有的所有项目。
const projects = await client.projects.list();
projects.forEach((p) => console.log(p.id, p.title));
返回项目列表条目的数组(形状比 getProject 更精简)。
client.projects.delete(projectId, options?)
删除项目以及其关联的所有 stem、歌词和导出结果。
await client.projects.delete("prj_abc123", {
idempotencyKey: "delete-prj_abc123",
});
删除是永久性的。请配合幂等键使用,以便重试时安全。
接下来