目录
认证方式
所有开放接口均需在请求头中携带 X-User-No 与 X-API-Key 进行认证。
X-User-No:用户在小程序/Web 端注册后对应的用户名(即登录账号)。X-API-Key:以sk-cxcl-开头的密钥,可在「API 开放」页面生成或重新生成。
同时兼容 Authorization: Bearer sk-cxcl-xxx 方式传递 API-Key。
请求头示例
POST /open/v1/vsr/submitTask HTTP/1.1
Host: vtool.tookit.cn
Content-Type: application/json
X-User-No: your_user_no
X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx
认证失败响应格式
认证失败时,HTTP 状态码为 401,响应体格式与标准格式不同(使用 message 而非 msg,无 data 字段):
{
"code": 401,
"message": "API-Key 无效或已撤销"
}
基础信息
| 项 | 说明 |
|---|---|
| 协议 | HTTPS |
| Base URL | https://vtool.tookit.cn(生产环境) |
| 请求格式 | JSON(上传文件接口为 multipart/form-data) |
| 响应格式 | 统一包装:{ "code": 0, "msg": "...", "data": {...} } |
| 字符编码 | UTF-8 |
code 为 0 表示成功,非 0 表示失败,具体含义参考「错误码说明」。
全局说明
任务有效期
- 历史任务:任务记录保存 30 天,30 天后自动清理。
- 新任务结果:任务处理完成后的结果视频 URL 有效期为 2 天(48 小时),2 天后链接过期无法访问,请及时下载。
- 上传文件:通过
uploadVideo接口上传的视频文件 URL 有效期为 2 天,请在有效期内提交去字幕任务。
并发与限流
- 每个 API-Key 的请求频率受限,短时间大量请求可能触发 429 限流。
- 任务处理为异步模式,提交后通过轮询
taskDetail接口查询结果,建议轮询间隔 ≥ 3 秒。
积分退还
任务提交时即扣除积分。若任务处理失败(含提交失败和处理失败),已扣除的积分将自动退还至用户账户,无需人工介入。
视频限制
提交去字幕任务前,请确保视频满足以下条件:
| 限制项 | 规则 |
|---|---|
| 格式 | MP4 / MOV |
| 文件大小 | ≤ 1GB |
| 分辨率 | 长边 ≤ 1920(即 ≤ 1080P) |
| 时长 | ≤ 10 分钟(600 秒) |
服务端会自动探测视频的宽高和时长,无需客户端传入 duration、width、height 参数;探测失败将返回错误。
计费规则
计费方式
- 按视频时长和分辨率计费:以 921600 像素(宽 × 高,约 720P)为界,分两档倍率,按秒计费,向上取整。
- 提交时冻结扣费:任务提交成功后立即扣除对应积分。
- 失败自动退还:任务提交失败或处理失败(status=failed)时,已扣除的积分自动退还。
积分消耗
| 分辨率档位 | 积分倍率 | 示例 |
|---|---|---|
| width × height ≤ 921600 像素 (约 720P 及以下,如 1280×720) | 1 积分/秒 | 720P 30 秒 = ceil(30 × 1.0) = 30 积分 |
| width × height > 921600 像素 (高于 720P,最高 1080P,如 1920×1080) | 1.3 积分/秒 | 1080P 30 秒 = ceil(30 × 1.3) = 39 积分 |
实际扣费公式:积分 = ceil(视频时长 × 倍率)(向上取整)
purchasedCredits)中扣除。
积分套餐
积分可通过 Web 端充值页面购买,支持多种套餐。点击下方链接前往充值:
queryCredits 接口查询余额。
视频解析
解析短视频分享链接,返回视频地址。
服务协议
使用视频解析接口即代表您同意以下视频解析服务协议:
- 作品归平台及作者所有,创想视频去水印字幕平台作为提供技术服务的中立工具,不存储任何作品,提供的功能仅限帮助用户提取视频自行学习、观看,降低视频、图片浏览障碍。
- 提示:用户请合法使用,若用户滥用该功能实施侵权或违法行为,用户自行承担由此产生的法律责任。平台倡导与用户共同营造良好的网络环境!
计费规则
- 按次计费:每次成功解析扣除 1 付费积分。
- 失败不扣费:解析失败(含平台不支持、链接失效、解析结果为空)时不扣积分。
- 直链不扣费:若传入的链接可直接下载视频,校验通过后直接返回,不扣积分。
请求参数
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 短视频分享链接(支持文本中包含链接,服务端会自动提取) |
URL 编码说明
由于分享链接通常包含特殊字符(如 &、=、?、中文文案等),请求前必须对 url 参数值进行 URL 编码,否则可能导致参数解析失败或链接被截断。
- Python:
urllib.parse.quote(url, safe="") - PHP:
urlencode($url) - JavaScript:
encodeURIComponent(url) - Go:
url.QueryEscape(url)
响应字段
成功时 data 字段包含以下主要字段:
| 字段名 | 类型 | 说明 |
|---|---|---|
| title | string | 视频/图集标题或描述(可能为空) |
| cover_url | string | 视频封面地址(可能为空) |
| video_url | string | 无水印视频播放地址(视频类型时存在) |
| images | array[string] | 图集图片地址列表(图集类型时存在) |
| liveImages | array[object] | 实况照片列表(实况类型时存在) |
| author | object | 作者信息(可能为空),含 uid、name、avatar |
实况照片字段说明(目前只支持特定平台的实况图解析)
当作品类型为实况照片时,liveImages 数组中的每个对象包含以下字段:
| 字段名 | 类型 | 说明 |
|---|---|---|
| imageUrl | string | 实况照片的封面图片地址 |
| videoUrl | string | 实况照片的视频片段地址 |
成功响应示例
{
"code": 0,
"msg": "解析成功",
"data": {
"title": "示例视频标题",
"cover_url": "https://example.com/cover.jpg",
"video_url": "https://example.com/video.mp4",
"author": {
"uid": "123456",
"name": "作者名",
"avatar": "https://example.com/avatar.jpg"
}
}
}
上传视频文件 可选
上传视频文件并获取视频 URL 和封面 URL。适用于无自有存储服务的场景。
submitTask。
请求格式
Content-Type: multipart/form-data(区别于其他接口的 application/json)
请求参数
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file | file | 是 | 视频文件,最大 1GB,支持 mp4、mov 格式 |
userNo 与 apiKey 通过请求头 X-User-No / X-API-Key 传递,无需放在表单中。
业务限制
| 限制项 | 规则 |
|---|---|
| 文件大小上限 | 1GB |
| 支持的视频格式 | mp4、mov |
| 分辨率上限 | 1920 × 1080(约 2,073,600 像素) |
| 时长上限 | 600 秒(10 分钟) |
| 位深上限 | 8bit(不支持 10bit 及以上) |
| HDR 格式 | 不支持 HDR 格式视频 |
请求示例
curl -X POST https://vtool.tookit.cn/open/v1/vsr/uploadVideo \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@/path/to/video.mp4"
响应字段
| 字段名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200 表示成功 |
| message | string | 提示信息 |
| videoUrl | string | 视频访问 URL(有效期 2 天) |
| coverUrl | string | 封面图访问 URL(有效期 24 小时) |
| width | number | 视频宽度(像素) |
| height | number | 视频高度(像素) |
| duration | number | 视频时长(秒,向上取整) |
响应示例
{
"code": 200,
"msg": "上传成功",
"data": {
"videoUrl": "https://video.tookit.cn/file-xxxxxxxx.mp4",
"coverUrl": "https://video.tookit.cn/img-xxxxxxxx.jpg",
"width": 1920,
"height": 1080,
"duration": 59
}
}
接口特有错误
| HTTP 状态码 | 含义 | 说明 |
|---|---|---|
| 401 | 鉴权失败 | userNo 或 apiKey 不正确 |
| 400 | 参数不合法 | 文件为空、格式不支持、大小超过 1GB、分辨率超过 1080P、时长超过 10 分钟、位深超过 8bit、HDR 格式、无法解析视频文件 |
| 500 | 服务内部异常 | 文件保存或封面截取失败,建议稍后重试 |
提交单任务
提交一个视频去字幕任务,任务提交成功后将立即扣除对应积分。
请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| videoUrl | string | 是 | 待处理视频的可下载 URL,需保证服务端可直接访问 |
| fileName | string | 是 | 文件名(含扩展名),用于结果文件命名 |
| fileSize | string | 否 | 文件大小,例如 "15.2MB" |
| duration | number | 否 | 视频时长(秒),不传则由服务端自动探测,传入值也会被服务端探测结果覆盖 |
| width | int | 否 | 视频宽度(像素),不传则由服务端自动探测,传入值也会被服务端探测结果覆盖 |
| height | int | 否 | 视频高度(像素),不传则由服务端自动探测,传入值也会被服务端探测结果覆盖 |
| mode | string | 否 | 去字幕模式:"1" 通用 / "2" 裁剪 / "3" AI;默认 "1" |
| fixedMode | bool | 否 | 是否固定模式处理,默认 false |
| isMute | bool | 否 | 处理后是否静音,默认 false |
| regions | array | 否 | 框选区域数组,最多 5 个;裁剪模式(mode=2)和 AI 模式(mode=3)下必填,通用模式(mode=1)可省略 |
| protectArea | array | 否 | 保护区域 [ymin, ymax, xmin, xmax] |
| callbackUrl | string | 否 | Webhook 回调地址,以 http:// 或 https:// 开头,长度 ≤ 2048。传入后任务完成或失败时系统主动 POST 通知该地址,无需轮询 |
| memberTag | string | 否 | 团队成员标识,用于区分同一 API-Key 下不同成员提交的任务,长度 ≤ 64 |
| coverUrl | string | 否 | 封面图 URL,由 uploadVideo 接口返回的 coverUrl 传入 |
regions 区域对象
| 字段 | 类型 | 说明 |
|---|---|---|
| l | int | 左上角 x 坐标 |
| t | int | 左上角 y 坐标 |
| w | int | 区域宽度 |
| h | int | 区域高度 |
Webhook 回调通知
当传入 callbackUrl 参数时,任务完成后系统会向该地址发送 POST 请求,Content-Type 为 application/json,请求体格式如下:
{
"taskId": "vsr_xxxxxxxxxxxx",
"status": "completed",
"videoUrl": "https://cdn.tookit.cn/result/xxx.mp4",
"originUrl": "https://example.com/video.mp4",
"coverUrl": "https://video.tookit.cn/img-xxxxxxxx.jpg",
"duration": "0分钟58秒",
"resolution": "1920x1080"
}
| 字段 | 类型 | 说明 |
|---|---|---|
| taskId | string | 任务 ID |
| status | string | 任务状态:"completed" 或 "failed" |
| videoUrl | string | 处理结果视频 URL(仅 completed 时有值) |
| originUrl | string | 原始视频 URL |
| coverUrl | string | 封面图 URL |
| duration | string | 视频时长 |
| resolution | string | 视频分辨率 |
重试策略
| 第 N 次尝试 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| 延迟 | 0s(首次) | 2s | 4s | 8s | 16s |
5 次全部失败后不再重试,仅记录错误日志。建议回调方做好幂等处理,因为 5 次重试可能发送重复请求。
请求示例
{
"videoUrl": "https://example.com/video.mp4",
"fileName": "video.mp4",
"mode": "1",
"isMute": false,
"regions": [
{ "l": 100, "t": 900, "w": 1720, "h": 120 }
],
"callbackUrl": "https://your-server.com/webhook/vsr"
}
说明:duration、width、height 无需传入,服务端会自动探测视频元信息。
响应示例(720P 30 秒视频)
{
"code": 0,
"msg": "任务提交成功",
"data": {
"taskId": "vsr_xxxxxxxxxxxx",
"status": "processing",
"duration": 30,
"pointCost": 30
}
}
查询任务详情
根据任务 ID 查询去字幕任务的处理状态与结果。
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| taskId | string | 提交任务时返回的任务 ID |
响应示例
{
"code": 0,
"msg": "成功",
"data": {
"taskId": "vsr_xxxxxxxxxxxx",
"status": "completed",
"videoUrl": "https://cdn.tookit.cn/result/xxx.mp4",
"originUrl": "https://example.com/video.mp4",
"coverUrl": "https://video.tookit.cn/img-xxxxxxxx.jpg",
"duration": "0分钟58秒",
"resolution": "1920x1080",
"createdAt": "2026-06-24 10:00:00",
"completedAt": "2026-06-24 10:02:30"
}
}
status 取值
| 值 | 含义 | 说明 |
|---|---|---|
processing | 排队中 / 处理中 | 任务已提交,正在等待处理或正在处理中 |
completed | 已完成 | 任务处理成功,结果视频可通过 videoUrl 下载 |
failed | 处理失败 | 任务处理失败,已扣除积分自动退还 |
blocked | 处理失败(拦截) | 视频内容不符合处理要求,被系统拦截,已扣除积分自动退还 |
callbackUrl 参数,任务完成或失败时系统主动 POST 通知,无需轮询。
查询任务列表
查询当前 API-Key 所属用户的去字幕任务列表。
查询参数
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| page | int | 1 | 页码,从 1 开始 |
| pageSize | int | 20 | 每页数量,最大 100 |
| memberTag | string | 空 | 按团队成员标识筛选,仅返回该成员提交的任务 |
响应示例
{
"code": 0,
"msg": "成功",
"data": {
"total": 128,
"page": 1,
"pageSize": 20,
"items": [
{
"taskId": "vsr_xxxxxxxxxxxx",
"status": "completed",
"videoUrl": "https://cdn.tookit.cn/result/xxx.mp4",
"originUrl": "https://example.com/video.mp4",
"coverUrl": "https://video.tookit.cn/img-xxxxxxxx.jpg",
"duration": "0分钟58秒",
"fileSize": "15.2MB",
"resolution": "1920x1080",
"memberTag": "member-a",
"createdAt": "2026-06-24 10:00:00"
}
]
}
}
查询积分余额
查询当前 API-Key 所属用户的积分余额。
响应示例
{
"code": 0,
"msg": "成功",
"data": {
"totalCredits": 5000,
"freeCredits": 200,
"purchasedCredits": 4800,
"userLevel": 1
}
}
purchasedCredits)中扣除,不消耗免费积分。若付费积分不足,任务提交将返回积分不足错误(code=111002)。
团队去字幕
团队去字幕功能允许多人共用同一个 API-Key 的积分额度,同时按成员标识(memberTag)区分每个成员提交的任务,便于团队管理员进行用量统计与成本分摊。
使用流程
- 管理员生成 API-Key:在「API 开放」页面生成 API-Key,并将
userNo与apiKey分发给团队成员。 - 成员配置凭证:每位成员在客户端输入
userNo、apiKey以及自定义的memberTag(用于标识自己)。 - 成员提交任务:成员提交去字幕任务时,请求体中携带
memberTag,系统会将该任务归属到对应成员。 - 管理员查看统计:管理员通过团队概览、成员统计、使用趋势接口查看团队整体及每个成员的用量。
数据隔离说明
- 所有成员共享同一个 API-Key 的积分余额,任务扣费均从该账户扣除。
- 任务记录按
memberTag字段区分成员,便于统计与对账。 - 未传入
memberTag的任务不会计入团队成员统计,但会占用团队总任务数。
团队概览统计
查询团队去字幕整体数据,包括总任务数、团队成员数、近 7 天任务数、近 7 天积分消耗及剩余积分。
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| totalTasks | int64 | 团队累计去字幕任务总数 |
| totalMembers | int64 | 团队累计成员数(按 memberTag 去重) |
| weekTasks | int64 | 近 7 天任务数(含当天) |
| weekPoints | int64 | 近 7 天累计积分消耗 |
| remainPoints | int64 | 当前账户剩余积分(免费 + 付费) |
| weekStartDate | string | 近 7 天统计起始日期,格式 2006-01-02 |
响应示例
{
"code": 0,
"msg": "成功",
"data": {
"totalTasks": 128,
"totalMembers": 5,
"weekTasks": 32,
"weekPoints": 1840,
"remainPoints": 5000,
"weekStartDate": "2026-06-21"
}
}
团队成员统计
查询近 7 天每个团队成员的任务数与积分消耗,按 memberTag 聚合。
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| items | array | 成员统计列表 |
| weekStartDate | string | 近 7 天统计起始日期,格式 2006-01-02 |
items 成员对象
| 字段 | 类型 | 说明 |
|---|---|---|
| memberTag | string | 团队成员标识 |
| taskCount | int64 | 近 7 天任务数 |
| pointCost | int64 | 近 7 天积分消耗 |
响应示例
{
"code": 0,
"msg": "成功",
"data": {
"items": [
{ "memberTag": "member-a", "taskCount": 12, "pointCost": 720 },
{ "memberTag": "member-b", "taskCount": 8, "pointCost": 480 }
],
"weekStartDate": "2026-06-21"
}
}
团队使用趋势
按日期范围查询团队每日任务数与积分消耗,默认返回最近 7 天数据。
查询参数
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| startDate | string | 7 天前 | 开始日期,格式 2006-01-02 |
| endDate | string | 今天 | 结束日期,格式 2006-01-02 |
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| items | array | 每日统计列表 |
| startDate | string | 实际查询开始日期 |
| endDate | string | 实际查询结束日期 |
items 日统计对象
| 字段 | 类型 | 说明 |
|---|---|---|
| date | string | 日期,格式 2006-01-02 |
| taskCount | int64 | 当日任务数 |
| pointCost | int64 | 当日积分消耗 |
响应示例
{
"code": 0,
"msg": "成功",
"data": {
"items": [
{ "date": "2026-06-21", "taskCount": 2, "pointCost": 120 },
{ "date": "2026-06-22", "taskCount": 5, "pointCost": 310 },
{ "date": "2026-06-23", "taskCount": 3, "pointCost": 180 }
],
"startDate": "2026-06-21",
"endDate": "2026-06-27"
}
}
调用示例
cURL
视频解析
curl -X GET "https://vtool.tookit.cn/open/v1/parseVd?url=https%3A%2F%2Fv.douyin.com%2Fxxxxxxxx" \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx"
1. 上传视频
curl -X POST https://vtool.tookit.cn/open/v1/vsr/uploadVideo \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@/path/to/video.mp4"
2. 提交去字幕任务
curl -X POST https://vtool.tookit.cn/open/v1/vsr/submitTask \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"videoUrl": "https://video.tookit.cn/file-xxxxxxxx.mp4",
"fileName": "video.mp4",
"mode": "1",
"regions": [
{ "l": 100, "t": 900, "w": 1720, "h": 120 }
],
"callbackUrl": "https://your-server.com/webhook/vsr"
}'
3. 查询任务详情
curl -X GET "https://vtool.tookit.cn/open/v1/vsr/taskDetail/vsr_xxxxxxxxxxxx" \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx"
4. 查询任务列表
curl -X GET "https://vtool.tookit.cn/open/v1/vsr/taskList?page=1&pageSize=20" \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx"
5. 查询积分余额
curl -X GET https://vtool.tookit.cn/open/v1/vsr/queryCredits \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx"
7. 查询团队概览(团队去字幕)
curl -X GET https://vtool.tookit.cn/open/v1/vsr/teamOverview \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx"
8. 查询团队成员统计(团队去字幕)
curl -X GET https://vtool.tookit.cn/open/v1/vsr/teamMemberStats \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx"
9. 查询团队使用趋势(团队去字幕)
curl -X GET "https://vtool.tookit.cn/open/v1/vsr/teamUsageStats?startDate=2026-06-21&endDate=2026-06-27" \
-H "X-User-No: your_user_no" \
-H "X-API-Key: sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx"
Python
import urllib.parse
import requests
BASE_URL = "https://vtool.tookit.cn"
HEADERS = {
"X-User-No": "your_user_no",
"X-API-Key": "sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx",
}
# 视频解析(必须对 url 进行 URL 编码)
share_url = "https://v.douyin.com/xxxxxxxx"
encoded_url = urllib.parse.quote(share_url, safe="")
parse_resp = requests.get(
f"{BASE_URL}/open/v1/parseVd?url={encoded_url}",
headers=HEADERS,
)
parse_data = parse_resp.json()["data"]
print("视频标题:", parse_data.get("title"))
print("视频地址:", parse_data.get("video_url"))
print("图集地址:", parse_data.get("images", []))
# 1. 上传视频
with open("video.mp4", "rb") as f:
resp = requests.post(
f"{BASE_URL}/open/v1/vsr/uploadVideo",
headers=HEADERS,
files={"file": f},
)
video_url = resp.json()["data"]["videoUrl"]
# 2. 提交去字幕任务
resp = requests.post(
f"{BASE_URL}/open/v1/vsr/submitTask",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"videoUrl": video_url,
"fileName": "video.mp4",
"mode": "1",
"regions": [{"l": 100, "t": 900, "w": 1720, "h": 120}],
"callbackUrl": "https://your-server.com/webhook/vsr", # 可选:任务完成后主动通知
},
)
task_id = resp.json()["data"]["taskId"]
# 3. 查询任务状态(二选一)
import time
while True:
resp = requests.get(
f"{BASE_URL}/open/v1/vsr/taskDetail/{task_id}",
headers=HEADERS,
)
status = resp.json()["data"]["status"]
if status in ("completed", "failed"):
break
time.sleep(3)
print("任务状态:", status)
if status == "completed":
print("结果视频:", resp.json()["data"]["videoUrl"])
# 4. 查询任务列表
task_list = requests.get(
f"{BASE_URL}/open/v1/vsr/taskList",
headers=HEADERS,
params={"page": 1, "pageSize": 20},
).json()["data"]
print("任务列表:", task_list)
# 5. 查询积分余额
credits = requests.get(
f"{BASE_URL}/open/v1/vsr/queryCredits", headers=HEADERS
).json()["data"]
print("付费积分:", credits["purchasedCredits"])
# 6. 查询团队统计(团队去字幕)
team_overview = requests.get(
f"{BASE_URL}/open/v1/vsr/teamOverview", headers=HEADERS
).json()["data"]
print("团队总任务数:", team_overview["totalTasks"])
member_stats = requests.get(
f"{BASE_URL}/open/v1/vsr/teamMemberStats", headers=HEADERS
).json()["data"]["items"]
print("成员统计:", member_stats)
usage_stats = requests.get(
f"{BASE_URL}/open/v1/vsr/teamUsageStats",
headers=HEADERS,
params={"startDate": "2026-06-21", "endDate": "2026-06-27"},
).json()["data"]["items"]
print("使用趋势:", usage_stats)
Node.js
const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");
const BASE_URL = "https://vtool.tookit.cn";
const headers = {
"X-User-No": "your_user_no",
"X-API-Key": "sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx",
};
// 视频解析
const parseResp = await axios.get(
`${BASE_URL}/open/v1/parseVd`,
{
headers,
params: { url: "https://v.douyin.com/xxxxxxxx" },
},
);
const parseData = parseResp.data.data;
console.log("视频标题:", parseData.title);
console.log("视频地址:", parseData.video_url);
console.log("图集地址:", parseData.images || []);
// 1. 上传视频
const form = new FormData();
form.append("file", fs.createReadStream("video.mp4"));
const uploadResp = await axios.post(`${BASE_URL}/open/v1/vsr/uploadVideo`, form, {
headers: { ...headers, ...form.getHeaders() },
});
const videoUrl = uploadResp.data.data.videoUrl;
// 2. 提交去字幕任务
const taskResp = await axios.post(
`${BASE_URL}/open/v1/vsr/submitTask`,
{
videoUrl,
fileName: "video.mp4",
mode: "1",
regions: [{ l: 100, t: 900, w: 1720, h: 120 }],
callbackUrl: "https://your-server.com/webhook/vsr", // 可选:任务完成后主动通知
},
{ headers: { ...headers, "Content-Type": "application/json" } },
);
const taskId = taskResp.data.data.taskId;
// 3. 轮询任务状态
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
let status = "processing";
while (status === "processing") {
await delay(3000);
const detailResp = await axios.get(
`${BASE_URL}/open/v1/vsr/taskDetail/${taskId}`,
{ headers },
);
status = detailResp.data.data.status;
}
console.log("任务状态:", status);
// 4. 查询任务列表
const taskListResp = await axios.get(
`${BASE_URL}/open/v1/vsr/taskList`,
{ headers, params: { page: 1, pageSize: 20 } },
);
console.log("任务列表:", taskListResp.data.data);
// 5. 查询积分余额
const creditsResp = await axios.get(
`${BASE_URL}/open/v1/vsr/queryCredits`,
{ headers },
);
console.log("付费积分:", creditsResp.data.data.purchasedCredits);
// 6. 查询团队统计(团队去字幕)
const teamOverviewResp = await axios.get(
`${BASE_URL}/open/v1/vsr/teamOverview`,
{ headers },
);
console.log("团队总任务数:", teamOverviewResp.data.data.totalTasks);
const memberStatsResp = await axios.get(
`${BASE_URL}/open/v1/vsr/teamMemberStats`,
{ headers },
);
console.log("成员统计:", memberStatsResp.data.data.items);
const usageStatsResp = await axios.get(
`${BASE_URL}/open/v1/vsr/teamUsageStats`,
{ headers, params: { startDate: "2026-06-21", endDate: "2026-06-27" } },
);
console.log("使用趋势:", usageStatsResp.data.data.items);
PHP
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$baseUrl = 'https://vtool.tookit.cn';
$headers = [
'X-User-No' => 'your_user_no',
'X-API-Key' => 'sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx',
];
$client = new Client(['base_uri' => $baseUrl, 'headers' => $headers, 'verify' => false]);
// 视频解析(必须对 url 进行 urlencode)
$shareUrl = 'https://v.douyin.com/xxxxxxxx';
$parseResp = $client->get('/open/v1/parseVd', ['query' => ['url' => urlencode($shareUrl)]]);
$parseData = json_decode($parseResp->getBody(), true)['data'];
echo '视频标题: ' . ($parseData['title'] ?? '') . "\n";
echo '视频地址: ' . ($parseData['video_url'] ?? '') . "\n";
// 1. 上传视频
$videoPath = '/path/to/video.mp4';
$uploadResp = $client->post('/open/v1/vsr/uploadVideo', [
'multipart' => [
['name' => 'file', 'contents' => fopen($videoPath, 'rb'), 'filename' => basename($videoPath)],
],
]);
$videoUrl = json_decode($uploadResp->getBody(), true)['data']['videoUrl'];
// 2. 提交去字幕任务
$submitResp = $client->post('/open/v1/vsr/submitTask', [
'json' => [
'videoUrl' => $videoUrl,
'fileName' => 'video.mp4',
'mode' => '1',
'regions' => [['l' => 100, 't' => 900, 'w' => 1720, 'h' => 120]],
'callbackUrl' => 'https://your-server.com/webhook/vsr',
],
]);
$taskId = json_decode($submitResp->getBody(), true)['data']['taskId'];
// 3. 查询任务详情
$detailResp = $client->get("/open/v1/vsr/taskDetail/{$taskId}");
$status = json_decode($detailResp->getBody(), true)['data']['status'];
echo '任务状态: ' . $status . "\n";
// 4. 查询任务列表
$taskListResp = $client->get('/open/v1/vsr/taskList', ['query' => ['page' => 1, 'pageSize' => 20]]);
echo '任务列表: ' . $taskListResp->getBody() . "\n";
// 5. 查询积分余额
$creditsResp = $client->get('/open/v1/vsr/queryCredits');
echo '积分余额: ' . $creditsResp->getBody() . "\n";
// 6. 查询团队统计
$teamOverviewResp = $client->get('/open/v1/vsr/teamOverview');
echo '团队概览: ' . $teamOverviewResp->getBody() . "\n";
$memberStatsResp = $client->get('/open/v1/vsr/teamMemberStats');
echo '成员统计: ' . $memberStatsResp->getBody() . "\n";
$usageStatsResp = $client->get('/open/v1/vsr/teamUsageStats', [
'query' => ['startDate' => '2026-06-21', 'endDate' => '2026-06-27'],
]);
echo '使用趋势: ' . $usageStatsResp->getBody() . "\n";
?>
Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"os"
"time"
)
const (
baseURL = "https://vtool.tookit.cn"
userNo = "your_user_no"
apiKey = "sk-cxcl-xxxxxxxxxxxxxxxxxxxxxxxx"
)
func newRequest(method, path string, body io.Reader) (*http.Request, error) {
req, err := http.NewRequest(method, baseURL+path, body)
if err != nil {
return nil, err
}
req.Header.Set("X-User-No", userNo)
req.Header.Set("X-API-Key", apiKey)
return req, nil
}
func doRequest(req *http.Request) map[string]interface{} {
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
panic(err)
}
return result
}
func main() {
// 视频解析(必须对 url 进行 QueryEscape)
shareUrl := "https://v.douyin.com/xxxxxxxx"
req, _ := newRequest("GET", "/open/v1/parseVd?url="+url.QueryEscape(shareUrl), nil)
parseData := doRequest(req)["data"].(map[string]interface{})
fmt.Println("视频标题:", parseData["title"])
fmt.Println("视频地址:", parseData["video_url"])
// 1. 上传视频
videoPath := "/path/to/video.mp4"
file, _ := os.Open(videoPath)
defer file.Close()
var b bytes.Buffer
writer := multipart.NewWriter(&b)
part, _ := writer.CreateFormFile("file", videoPath)
io.Copy(part, file)
writer.Close()
uploadReq, _ := newRequest("POST", "/open/v1/vsr/uploadVideo", &b)
uploadReq.Header.Set("Content-Type", writer.FormDataContentType())
videoUrl := doRequest(uploadReq)["data"].(map[string]interface{})["videoUrl"].(string)
// 2. 提交去字幕任务
submitBody, _ := json.Marshal(map[string]interface{}{
"videoUrl": videoUrl,
"fileName": "video.mp4",
"mode": "1",
"regions": []map[string]int{{"l": 100, "t": 900, "w": 1720, "h": 120}},
"callbackUrl": "https://your-server.com/webhook/vsr",
})
submitReq, _ := newRequest("POST", "/open/v1/vsr/submitTask", bytes.NewReader(submitBody))
submitReq.Header.Set("Content-Type", "application/json")
taskId := doRequest(submitReq)["data"].(map[string]interface{})["taskId"].(string)
// 3. 查询任务详情
detailReq, _ := newRequest("GET", "/open/v1/vsr/taskDetail/"+taskId, nil)
status := doRequest(detailReq)["data"].(map[string]interface{})["status"].(string)
fmt.Println("任务状态:", status)
// 4. 查询任务列表
listReq, _ := newRequest("GET", "/open/v1/vsr/taskList?page=1&pageSize=20", nil)
fmt.Println("任务列表:", doRequest(listReq)["data"])
// 5. 查询积分余额
creditsReq, _ := newRequest("GET", "/open/v1/vsr/queryCredits", nil)
fmt.Println("积分余额:", doRequest(creditsReq)["data"])
// 6. 查询团队统计
overviewReq, _ := newRequest("GET", "/open/v1/vsr/teamOverview", nil)
fmt.Println("团队概览:", doRequest(overviewReq)["data"])
memberReq, _ := newRequest("GET", "/open/v1/vsr/teamMemberStats", nil)
fmt.Println("成员统计:", doRequest(memberReq)["data"])
usageReq, _ := newRequest("GET", "/open/v1/vsr/teamUsageStats?startDate=2026-06-21&endDate=2026-06-27", nil)
fmt.Println("使用趋势:", doRequest(usageReq)["data"])
}
错误码说明
| HTTP 状态码 | 含义 | 处理建议 |
|---|---|---|
| 200 | 请求成功(部分业务错误也返回 200,需判断 code 字段) | 检查响应体 code 是否为 0 |
| 400 | 请求参数错误或业务校验失败 | 检查请求参数,参考响应体 msg |
| 401 | 认证失败(缺少参数、Key 无效或已撤销、userNo 不匹配) | 检查 X-User-No 与 X-API-Key 是否正确,必要时重新生成 |
| 403 | 无权访问 | 确认任务属于当前用户 |
| 429 | 请求过于频繁 | 降低请求频率 |
| 500/502/503 | 服务异常 | 稍后重试 |
业务错误码(响应体 code 字段)
| 错误码 | HTTP 状态码 | 含义 |
|---|---|---|
| 0 | 200 | 成功 |
| 111002 | 200 | 付费积分不足(注意:HTTP 状态码为 200,需判断 code 字段) |
| 112602 | 400 | 视频去字幕失败(任务提交异常) |
| 112608 | 400 | 视频尺寸超出 1080P 限制(长边 > 1920) |
| 112610 | 400 | 视频时长超出 10 分钟限制 |
| 112611 | 400 | 同一用户最多同时提交 5 个去字幕任务 |
| 100101 | 500 | 数据库错误 |
| 100401 | 500 | 视频信息获取失败(远程探测失败) |
msg 为准。