Youka 的设计理念是由代理来驱动。每条 CLI 命令都会返回机器可读的 JSON 信封(envelope),每次写入都支持幂等键(idempotency keys),并且公共 API 暴露的能力面与语义保持一致。本页面汇总了代理作者在将 Youka 接入工作流之前需要了解的操作规则。
快速开始
如果你是第一次为代理做接入,请先安装 Youka CLI,然后安装 Youka 卡拉 OK 技能:
npm install -g @youka/cli
npx skills add https://github.com/youka-io/skills --skill youka-karaoke
这样会为代理提供一个由 CLI 驱动的现成 Youka skill。安装完成后,使用下面的工作流模式来创建卡拉 OK 视频、自定义样式,并安全导出 MP4 文件。
给你的代理下指令
安装好 CLI 和 skill 之后,你可以这样给代理一个直接任务:
使用 Youka 从 /path/to/song.mp3 创建一个卡拉 OK 视频。将歌词转录为英文,使用干净的卡拉 OK 字幕风格,导出最终视频为 1080p,并保存为 ./karaoke.mp4。
使用 Youka 从 https://example.com/song.mp4 创建一个卡拉 OK 视频。如果缺少 URL 依赖项,先安装它们。然后自动转录歌词,使用干净的卡拉 OK 字幕风格,导出最终视频,并保存为 ./karaoke.mp4。
操作规则
始终使用 --json 在 CLI 中,始终传 --json。在 API 中,始终设置 Accept: application/json。不要解析面向人类的输出。
始终发送幂等键 每次写入都应携带稳定的幂等键,这样在超时后重试会返回原始结果,而不是重复执行工作。
重新读取持久化状态 不要信任过时的变更响应。在终态任务之后,重新读取 project 或 export 以获取最终状态。
使用退避轮询 从 2–3 秒的间隔开始。对于长任务使用指数退避。尊重 429 响应。
输出约定
每个以 --json 模式运行的 CLI 命令都会向 stdout 写入且只写入一个信封(envelope)。
成功:
{
"schemaVersion" : "1" ,
"ok" : true ,
"data" : { "id" : "prj_abc123" , "title" : "My Song" }
}
失败:
{
"schemaVersion" : "1" ,
"ok" : false ,
"error" : {
"code" : "CONFLICT" ,
"message" : "A request with this Idempotency-Key is already in progress." ,
"retryable" : true
}
}
退出码:
Code Meaning Retry? 0成功。 N/A 1运行时错误(网络、API、渲染)。 检查 error.retryable。 2输入无效(错误 flags、不可读 payload)。 否 — 修复输入。
端到端工作流
规范的代理工作流是:创建 project、等待、导出、下载结果。下面给出 CLI 与 SDK 的完整模式实现。
# 1. Create the project and wait for stems + lyrics sync to finish
PROJECT_JSON = $( youka project create ./song.mp3 \
--mode transcribe \
--lang en \
--wait \
--idempotency-key "create-song-2026-04-08-001" \
--json )
PROJECT_ID = $( echo " $PROJECT_JSON " | jq -r '.data.projectId' )
# 2. Start and wait for an export
EXPORT_JSON = $( youka export create " $PROJECT_ID " \
--resolution 1080p \
--quality high \
--wait \
--download \
--output ./karaoke.mp4 \
--idempotency-key "export- $PROJECT_ID -v1" \
--json )
echo "Done:" "$( echo " $EXPORT_JSON " | jq -r '.data.fileUrl')"
import { YoukaClient , YoukaRequestError , YoukaTaskError } from "@youka/zh/sdk" ;
const client = new YoukaClient ({ apiKey: process . env . YOUKA_API_KEY ! });
async function createAndExport () {
// 1. Create the project and wait for stems + lyrics sync
const created = await client . projects . create (
{
source: { type: "path" , path: "./song.mp3" },
lyricsSource: { type: "transcribe" , language: "en" },
},
{ idempotencyKey: "create-song-2026-04-08-001" },
);
const { project } = await client . projects . wait ( created );
// 2. Start and wait for an export
const exportResult = await client . exports . create (
project . id ,
{ resolution: "1080p" , quality: "high" },
{ idempotencyKey: `export- ${ project . id } -v1` },
);
const finalized = await client . exports . wait ( exportResult );
// 3. Download the file
await client . exports . download ( finalized , {
output: "./karaoke.mp4" ,
});
}
createAndExport (). catch (( error ) => {
if ( error instanceof YoukaRequestError && error . retryable ) {
// Retry with the same idempotency keys
}
if ( error instanceof YoukaTaskError ) {
console . error ( "Task failed:" , error . code , error . task . error );
}
throw error ;
});
轮询建议
在 SDK 中,大多数写操作都会返回 operation handles。优先使用 client.projects.wait(...) 和 client.exports.wait(...),只有在你明确需要更底层的 task 访问时才使用 client.tasks.*。
Job type Recommended initial interval Max wait Project create (stems + lyrics sync) 3 s 15 min Stem separation only 3 s 10 min Lyrics sync only 2 s 5 min Export render 3 s 30 min
在 CLI 中,--wait 会为你处理轮询。在 SDK 中,wait helpers 默认使用 2 s 间隔,并接受 pollIntervalMs。
尊重 429 响应。遇到限流时,至少按 Retry-After
header(如果没有则按 30 s)进行退避。
幂等键
每个 create 与 update 操作都支持幂等键。规则如下:
为每一次“逻辑变更”使用 稳定、唯一、确定性 的 key。好例子:create-song-${sourceHash}。坏例子:每次重试都生成一个新的 UUID。
在重试时复用 相同 的 key。服务端会识别重放并返回原始结果。
Key 的作用域是 per-account,并在 24 小时后过期。
如果服务端返回 IDEMPOTENT_REPLAY_IN_PROGRESS(HTTP 202),说明原始请求仍在运行。等待后使用相同 key 重试。
示例模式:
const key = `create- ${ sha256 ( sourceBytes ) } ` ;
try {
return await client . projects . create ( body , { idempotencyKey: key });
} catch ( error ) {
if ( error instanceof YoukaRequestError && error . retryable ) {
// Safe to retry with the same key
return await client . projects . create ( body , { idempotencyKey: key });
}
throw error ;
}
完整约定请参见 API idempotency 。
错误恢复
根据 error.code 与 error.retryable 分支处理。常见情况如下:
Code Cause Action INVALID_REQUEST请求体未通过 schema 校验。 修复 payload。不重试。 UNAUTHORIZED缺少或无效的 API key。 反馈给调用方。不重试。 NOT_FOUND资源不存在或你没有访问权限。 不重试。 CONFLICT (409)版本冲突或幂等冲突。 使用相同幂等键重试。 TOO_MANY_REQUESTS (429)限流。 按 Retry-After 或 30 s 退避。 INTERNAL_SERVER_ERROR (500)暂时性的服务端故障。 退避重试最多 3 次。 IDEMPOTENT_REPLAY_IN_PROGRESS (202)之前的请求仍在运行。 等待并使用相同 key 重试。 TASK_FAILED异步任务以失败结束。 将 error.task.error 反馈给调用方。不重试。 TASK_TIMED_OUT异步任务超出预算时间。 可安全重试一次。
发现可变字段
在修改 presets 之前,先获取 preset schema,让模型知道有效字段与取值类型:
# Preset body schema
youka preset schema --json
import { KaraokePresetSchema } from "@youka/zh/sdk" ;
const presetSchema = KaraokePresetSchema . toJSONSchema ();
对于 project settings,优先先读取当前 project settings,然后通过 youka project settings <id> --body ... 提交一个最小化的 update body。
每个代理会话获取一次并缓存结果。
并行代理
当多个代理并发对同一账号运行时:
将幂等键同时限定到 代理身份 与 逻辑变更 :agent-${agentId}-create-${sourceHash}。这可以防止某个代理的重试与另一个代理的新请求发生冲突。
保持读取操作不受限制 — GET 请求很便宜且没有副作用。
如果你需要有序的导出历史,每个 project 对 POST /projects/{projectId}/exports 使用单一队列;否则导出结果可能会乱序到达。
下一步