GEN_VIDEO_STATUS 接口 - 查询视频渲染状态
📋 接口信息
接口地址: POST /api/drafts/gen_video_status
功能描述: 查询视频草稿的渲染状态,获取渲染进度和结果信息
版本: v1.0.0
更新时间: 2025年8月1日
🎯 功能特性
核心功能
- 状态查询: 实时查询视频渲染任务的当前状态
- 进度跟踪: 获取渲染进度百分比和预计完成时间
- 结果获取: 获取渲染完成后的视频下载链接
- 错误诊断: 查看渲染失败的详细错误信息
- 历史记录: 查询历史渲染任务的状态信息
高级特性
- 实时更新: 支持轮询查询获取最新状态
- 多状态支持: 支持排队、渲染中、完成、失败等多种状态
- 详细信息: 提供渲染开始时间、完成时间、文件大小等详细信息
- 快速响应: 高效的状态查询,响应时间通常在1秒内
- 兼容性: 支持所有通过 gen_video 接口提交的渲染任务
📝 请求参数
请求体 (JSON)
{
"draft_url": "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json"
}
参数详解
参数名 |
类型 |
必填 |
说明 |
draft_url |
string |
✅ |
草稿文件的完整URL地址 |
参数说明
- draft_url: 要查询状态的草稿文件URL,通常来自于
create_draft
接口的返回结果
draft_url 支持格式
# OSS直链格式(推荐)
https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json
# 剪映链接格式(自动转换)
https://ts.fyshark.com/#/cozeToJianyin?drafId=https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/xxx.json
📤 响应格式
成功响应 - 渲染中 (200)
{
"status": "success",
"message": "视频状态查询成功",
"data": {
"code": 0,
"message": "查询成功",
"status": "rendering",
"progress": 65,
"estimated_time": 180,
"start_time": "2025-08-01T10:30:00Z",
"task_id": "render_task_12345678",
"draft_url": "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json"
}
}
成功响应 - 渲染完成 (200)
{
"status": "success",
"message": "视频状态查询成功",
"data": {
"code": 0,
"message": "渲染完成",
"status": "completed",
"progress": 100,
"video_url": "https://video-output.example.com/videos/final_video_12345.mp4",
"file_size": 52428800,
"duration": 120,
"resolution": "1920x1080",
"start_time": "2025-08-01T10:30:00Z",
"end_time": "2025-08-01T10:35:00Z",
"render_time": 300,
"task_id": "render_task_12345678",
"draft_url": "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json"
}
}
成功响应 - 渲染失败 (200)
{
"status": "success",
"message": "视频状态查询成功",
"data": {
"code": 0,
"message": "渲染失败",
"status": "failed",
"error_code": "INVALID_MEDIA",
"error_message": "素材文件无法访问或格式不支持",
"start_time": "2025-08-01T10:30:00Z",
"end_time": "2025-08-01T10:32:00Z",
"task_id": "render_task_12345678",
"draft_url": "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json"
}
}
错误响应 (400)
{
"status": "error",
"message": "参数验证失败",
"errors": [
"draft_url是必填项"
]
}
错误响应 (404)
{
"status": "error",
"message": "未找到渲染任务",
"data": {
"code": 404,
"message": "Draft not found or no render task exists"
}
}
错误响应 (500)
{
"status": "error",
"message": "状态查询失败: 网络连接超时"
}
🔧 使用示例
cURL 示例
基本查询
curl -X POST https://jy-api.fyshark.com/api/drafts/gen_video_status \
-H "Content-Type: application/json" \
-d '{
"draft_url": "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json"
}'
使用剪映链接格式
curl -X POST https://jy-api.fyshark.com/api/drafts/gen_video_status \
-H "Content-Type: application/json" \
-d '{
"draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json"
}'
JavaScript 示例
基础使用
const queryVideoStatus = async (draftUrl) => {
const response = await fetch('/api/drafts/gen_video_status', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
draft_url: draftUrl
})
});
const result = await response.json();
if (result.status === 'success') {
return result.data;
} else {
throw new Error(result.message);
}
};
// 使用示例
const draftUrl = "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json";
queryVideoStatus(draftUrl)
.then(status => {
console.log('渲染状态:', status.status);
console.log('进度:', status.progress + '%');
if (status.video_url) {
console.log('视频地址:', status.video_url);
}
})
.catch(error => {
console.error('查询失败:', error.message);
});
高级用法 - VideoStatusTracker 类
class VideoStatusTracker {
constructor(baseUrl = 'https://jy-api.fyshark.com') {
this.baseUrl = baseUrl;
}
// 查询单个视频状态
async queryStatus(draftUrl) {
const response = await fetch(`${this.baseUrl}/api/drafts/gen_video_status`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ draft_url: draftUrl })
});
const result = await response.json();
if (result.status !== 'success') {
throw new Error(`状态查询失败: ${result.message}`);
}
return result.data;
}
// 轮询查询直到完成
async waitForCompletion(draftUrl, options = {}) {
const {
interval = 5000, // 轮询间隔 5秒
timeout = 600000, // 超时时间 10分钟
onProgress = null // 进度回调
} = options;
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
try {
const status = await this.queryStatus(draftUrl);
// 调用进度回调
if (onProgress) {
onProgress(status);
}
// 检查完成状态
if (status.status === 'completed') {
return {
success: true,
video_url: status.video_url,
duration: status.duration,
file_size: status.file_size,
render_time: status.render_time
};
}
// 检查失败状态
if (status.status === 'failed') {
return {
success: false,
error_code: status.error_code,
error_message: status.error_message
};
}
// 等待下次查询
await new Promise(resolve => setTimeout(resolve, interval));
} catch (error) {
console.warn('状态查询失败,重试中...', error.message);
await new Promise(resolve => setTimeout(resolve, interval));
}
}
throw new Error('等待渲染完成超时');
}
// 批量查询多个视频状态
async batchQuery(draftUrls) {
const results = [];
for (const draftUrl of draftUrls) {
try {
const status = await this.queryStatus(draftUrl);
results.push({
success: true,
draft_url: draftUrl,
status: status
});
} catch (error) {
results.push({
success: false,
draft_url: draftUrl,
error: error.message
});
}
}
return results;
}
// 获取渲染统计信息
async getRenderStats(draftUrls) {
const results = await this.batchQuery(draftUrls);
const stats = {
total: results.length,
completed: 0,
rendering: 0,
failed: 0,
queued: 0,
unknown: 0
};
results.forEach(result => {
if (result.success) {
const status = result.status.status;
if (stats.hasOwnProperty(status)) {
stats[status]++;
} else {
stats.unknown++;
}
} else {
stats.unknown++;
}
});
return stats;
}
}
// 使用示例
const tracker = new VideoStatusTracker();
// 单次查询
const status = await tracker.queryStatus(draftUrl);
console.log('当前状态:', status);
// 等待完成
const result = await tracker.waitForCompletion(draftUrl, {
onProgress: (status) => {
console.log(`渲染进度: ${status.progress}%`);
}
});
if (result.success) {
console.log('渲染完成!', result.video_url);
} else {
console.log('渲染失败:', result.error_message);
}
// 批量查询
const draftUrls = [
"https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/draft1.json",
"https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/draft2.json"
];
const batchResults = await tracker.batchQuery(draftUrls);
console.log('批量查询结果:', batchResults);
// 获取统计信息
const stats = await tracker.getRenderStats(draftUrls);
console.log('渲染统计:', stats);
Python 示例
import requests
import time
import json
class VideoStatusTracker:
def __init__(self, base_url="https://jy-api.fyshark.com"):
self.base_url = base_url
def query_status(self, draft_url):
"""查询视频渲染状态"""
url = f"{self.base_url}/api/drafts/gen_video_status"
headers = {"Content-Type": "application/json"}
data = {"draft_url": draft_url}
response = requests.post(url, headers=headers, json=data)
result = response.json()
if result["status"] == "success":
return result["data"]
else:
raise Exception(f"状态查询失败: {result['message']}")
def wait_for_completion(self, draft_url, interval=5, timeout=600, on_progress=None):
"""轮询查询直到渲染完成"""
start_time = time.time()
while time.time() - start_time < timeout:
try:
status = self.query_status(draft_url)
# 调用进度回调
if on_progress:
on_progress(status)
# 检查完成状态
if status["status"] == "completed":
return {
"success": True,
"video_url": status["video_url"],
"duration": status.get("duration"),
"file_size": status.get("file_size"),
"render_time": status.get("render_time")
}
# 检查失败状态
if status["status"] == "failed":
return {
"success": False,
"error_code": status.get("error_code"),
"error_message": status.get("error_message")
}
# 等待下次查询
time.sleep(interval)
except Exception as e:
print(f"状态查询失败,重试中... {e}")
time.sleep(interval)
raise Exception("等待渲染完成超时")
def batch_query(self, draft_urls):
"""批量查询多个视频状态"""
results = []
for draft_url in draft_urls:
try:
status = self.query_status(draft_url)
results.append({
"success": True,
"draft_url": draft_url,
"status": status
})
except Exception as e:
results.append({
"success": False,
"draft_url": draft_url,
"error": str(e)
})
return results
def get_render_stats(self, draft_urls):
"""获取渲染统计信息"""
results = self.batch_query(draft_urls)
stats = {
"total": len(results),
"completed": 0,
"rendering": 0,
"failed": 0,
"queued": 0,
"unknown": 0
}
for result in results:
if result["success"]:
status = result["status"]["status"]
if status in stats:
stats[status] += 1
else:
stats["unknown"] += 1
else:
stats["unknown"] += 1
return stats
# 使用示例
tracker = VideoStatusTracker()
# 单次查询
draft_url = "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/0b3de2f7-e263-4cfb-b811-79f337a3843c.json"
try:
status = tracker.query_status(draft_url)
print("当前状态:")
print(f" 状态: {status['status']}")
print(f" 进度: {status.get('progress', 0)}%")
if status.get('video_url'):
print(f" 视频地址: {status['video_url']}")
except Exception as e:
print(f"查询失败: {e}")
# 等待完成
try:
def progress_callback(status):
print(f"渲染进度: {status.get('progress', 0)}%")
result = tracker.wait_for_completion(
draft_url,
on_progress=progress_callback
)
if result["success"]:
print(f"渲染完成! 视频地址: {result['video_url']}")
else:
print(f"渲染失败: {result['error_message']}")
except Exception as e:
print(f"等待完成失败: {e}")
# 批量查询
draft_urls = [
"https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/draft1.json",
"https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/draft2.json"
]
batch_results = tracker.batch_query(draft_urls)
for result in batch_results:
if result["success"]:
print(f"✅ {result['draft_url']} - {result['status']['status']}")
else:
print(f"❌ {result['draft_url']} - {result['error']}")
# 获取统计信息
stats = tracker.get_render_stats(draft_urls)
print("渲染统计:", json.dumps(stats, indent=2))
📊 状态说明
渲染状态类型
状态 |
说明 |
progress |
操作建议 |
queued |
排队中 |
0 |
等待处理,可继续查询 |
preparing |
准备中 |
1-10 |
正在准备渲染资源 |
rendering |
渲染中 |
10-99 |
正在渲染,可定期查询进度 |
completed |
已完成 |
100 |
渲染成功,可获取视频链接 |
failed |
渲染失败 |
- |
检查错误信息,修复后重新提交 |
cancelled |
已取消 |
- |
任务被用户或系统取消 |
错误码说明
错误码 |
说明 |
解决方案 |
INVALID_DRAFT |
草稿文件无效 |
检查草稿文件格式和内容 |
INVALID_MEDIA |
素材文件无效 |
确认所有素材文件可访问 |
INSUFFICIENT_QUOTA |
配额不足 |
充值或联系管理员 |
RENDER_TIMEOUT |
渲染超时 |
简化草稿内容或重新提交 |
SYSTEM_ERROR |
系统错误 |
稍后重试或联系技术支持 |
⚠️ 注意事项
查询限制
- 查询频率: 建议查询间隔不少于5秒,避免过频查询
- 超时处理: 长时间未完成的任务可能需要重新提交
- 缓存时间: 状态信息可能有1-2秒的缓存延迟
- 并发限制: 同时查询的任务数量建议不超过50个
使用建议
- 轮询策略: 采用指数退避算法避免频繁查询
- 错误重试: 网络错误时应进行适当重试
- 状态存储: 建议本地存储任务状态减少查询次数
- 用户体验: 为用户提供清晰的进度和状态反馈
数据时效性
- 完成状态: 视频链接通常保存30天
- 失败信息: 错误信息保存7天后清理
- 历史记录: 建议及时下载完成的视频文件
- 状态变更: 状态变更通知可能有延迟
🎨 应用场景
用户界面集成
- 进度条显示: 实时显示渲染进度给用户
- 状态通知: 渲染完成后自动通知用户
- 批量管理: 管理多个渲染任务的状态
自动化流程
- 流水线监控: 监控批量渲染任务的执行状态
- 错误处理: 自动重试失败的渲染任务
- 结果收集: 自动收集完成的视频文件
系统集成
- 第三方系统: 与其他系统集成实现视频处理流程
- 数据统计: 收集渲染成功率和性能数据
- 报警监控: 监控渲染失败率和异常情况
🔄 工作流程
基本查询流程
1. 准备草稿URL
↓
2. 调用状态查询接口
↓
3. 解析返回的状态信息
↓
4. 根据状态决定后续操作
轮询等待流程
查询状态 → 检查状态 → 是否完成?
↑ ↓
←——— 等待间隔 ←——— 否
↓
是
↓
获取结果/处理错误
✨ 最佳实践
智能轮询
// ✅ 推荐:智能轮询策略
const smartPolling = async (draftUrl) => {
let interval = 5000; // 起始间隔5秒
let attempts = 0;
const maxInterval = 30000; // 最大间隔30秒
while (attempts < 120) { // 最多查询2小时
try {
const status = await queryVideoStatus(draftUrl);
if (status.status === 'completed' || status.status === 'failed') {
return status;
}
// 动态调整查询间隔
if (status.status === 'rendering' && status.progress > 50) {
interval = 10000; // 渲染后期减少查询频率
} else if (status.status === 'queued') {
interval = Math.min(interval * 1.2, maxInterval); // 排队时逐步增加间隔
}
await new Promise(resolve => setTimeout(resolve, interval));
attempts++;
} catch (error) {
console.warn('查询失败,重试...', error.message);
await new Promise(resolve => setTimeout(resolve, interval));
attempts++;
}
}
throw new Error('查询超时');
};
批量监控
// ✅ 推荐:批量任务监控
const monitorBatchRender = async (draftUrls) => {
const results = new Map();
const checkStatus = async () => {
const pendingUrls = draftUrls.filter(url => {
const result = results.get(url);
return !result || (result.status !== 'completed' && result.status !== 'failed');
});
if (pendingUrls.length === 0) {
return true; // 全部完成
}
for (const draftUrl of pendingUrls) {
try {
const status = await queryVideoStatus(draftUrl);
results.set(draftUrl, status);
console.log(`${draftUrl}: ${status.status} ${status.progress || 0}%`);
} catch (error) {
console.warn(`查询失败 ${draftUrl}:`, error.message);
}
}
return false;
};
// 定期检查
while (!(await checkStatus())) {
await new Promise(resolve => setTimeout(resolve, 10000));
}
return Array.from(results.entries()).map(([url, status]) => ({
draft_url: url,
status: status
}));
};
📖 版本历史
- v1.0.0 (2025-08-01)
- 初始版本发布
- 支持基本的状态查询功能
- 支持多种渲染状态类型
- 完整的错误处理和状态码
- 详细的进度和时间信息
接口开发: JY API Team
文档更新: 2025年8月1日
技术支持: GitHub Issues
相关接口: gen_video - 视频渲染接口