GEN_VIDEO 接口 - 云渲染视频

📄 API_GEN_VIDEO.md 🕒 8/10/2025, 6:49:34 PM 📏 16KB

GEN_VIDEO 接口 - 云渲染视频

📋 接口信息

接口地址: POST /api/drafts/gen_video
功能描述: 提交视频草稿到云端进行渲染,生成最终的视频文件
版本: v1.0.0
更新时间: 2025年8月1日

🎯 功能特性

核心功能

高级特性

📝 请求参数

请求体 (JSON)

{
  "api_token": "1f0a1709-fa9e-4bf3-8180-6371b05f5fd6",
  "draft_url": "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/2025-03-01/draft/98598661-8583-4baa-89d1-1e27c688d695.json"
}

参数详解

参数名 类型 必填 说明
api_token string 渲染服务API访问令牌
draft_url string 草稿文件的完整URL地址

参数说明

draft_url 支持格式

# 剪映链接格式
https://ts.fyshark.com/#/cozeToJianyin?drafId=https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/xxx.json

# OSS直链格式  
https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/2025-03-01/draft/98598661-8583-4baa-89d1-1e27c688d695.json

📤 响应格式

成功响应 (200)

{
  "status": "success",
  "message": "视频渲染任务提交成功",
  "data": {
    "code": 0,
    "message": "Task submitted successfully",
    "task_id": "render_task_12345678",
    "estimated_time": 120,
    "render_status": "queued",
    "tip": "剪映小助手个人中心也可以查看状态和视频链接,计费详情请查看:https://www.51aigc.cc/#/plugins"
  }
}

错误响应 (400)

{
  "status": "error",
  "message": "参数验证失败",
  "errors": [
    "api_token是必填项",
    "draft_url是必填项"
  ]
}

错误响应 (401)

{
  "status": "error",
  "message": "API令牌无效或已过期",
  "data": {
    "code": 401,
    "message": "Unauthorized: Invalid API token"
  }
}

错误响应 (500)

{
  "status": "error",
  "message": "渲染服务请求失败",
  "data": {
    "code": 500,
    "message": "Internal server error"
  }
}

🔧 使用示例

cURL 示例

基本用法

curl -X POST https://jy-api.fyshark.com/api/drafts/gen_video \
  -H "Content-Type: application/json" \
  -d '{
    "api_token": "1f0a1709-fa9e-4bf3-8180-6371b05f5fd6",
    "draft_url": "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/2025-03-01/draft/98598661-8583-4baa-89d1-1e27c688d695.json"
  }'

使用剪映链接格式

curl -X POST https://jy-api.fyshark.com/api/drafts/gen_video \
  -H "Content-Type: application/json" \
  -d '{
    "api_token": "your-api-token-here",
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/draft/your-draft-id.json"
  }'

JavaScript 示例

基础使用

const generateVideo = async (apiToken, draftUrl) => {
  const response = await fetch('/api/drafts/gen_video', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      api_token: apiToken,
      draft_url: draftUrl
    })
  });
  
  const result = await response.json();
  
  if (result.status === 'success') {
    console.log('渲染任务提交成功:', result.data);
    return result.data;
  } else {
    throw new Error(result.message);
  }
};

// 使用示例
const apiToken = "1f0a1709-fa9e-4bf3-8180-6371b05f5fd6";
const draftUrl = "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/2025-03-01/draft/98598661-8583-4baa-89d1-1e27c688d695.json";

generateVideo(apiToken, draftUrl)
  .then(result => {
    console.log('任务ID:', result.task_id);
    console.log('预计时间:', result.estimated_time, '秒');
  })
  .catch(error => {
    console.error('渲染失败:', error.message);
  });

高级用法 - VideoRenderer 类

class VideoRenderer {
  constructor(apiToken, baseUrl = 'https://jy-api.fyshark.com') {
    this.apiToken = apiToken;
    this.baseUrl = baseUrl;
  }

  // 提交渲染任务
  async submitRenderTask(draftUrl) {
    const response = await fetch(`${this.baseUrl}/api/drafts/gen_video`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        api_token: this.apiToken,
        draft_url: draftUrl
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`渲染任务提交失败: ${result.message}`);
    }

    return result.data;
  }

  // 批量提交渲染任务
  async batchSubmitRenderTasks(draftUrls) {
    const results = [];
    
    for (const draftUrl of draftUrls) {
      try {
        const result = await this.submitRenderTask(draftUrl);
        results.push({
          success: true,
          draft_url: draftUrl,
          task_id: result.task_id,
          estimated_time: result.estimated_time
        });
      } catch (error) {
        results.push({
          success: false,
          draft_url: draftUrl,
          error: error.message
        });
      }
    }
    
    return results;
  }

  // 创建并渲染草稿(完整流程)
  async createAndRenderDraft(draftData) {
    try {
      // 1. 创建草稿
      const createResponse = await fetch(`${this.baseUrl}/api/drafts/create_draft`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(draftData)
      });

      const createResult = await createResponse.json();
      if (createResult.status !== 'success') {
        throw new Error(`草稿创建失败: ${createResult.message}`);
      }

      const draftUrl = createResult.data.draft_url;
      console.log('草稿创建成功:', draftUrl);

      // 2. 提交渲染任务  
      const renderResult = await this.submitRenderTask(draftUrl);
      console.log('渲染任务提交成功:', renderResult.task_id);

      return {
        draft_url: draftUrl,
        task_id: renderResult.task_id,
        estimated_time: renderResult.estimated_time
      };

    } catch (error) {
      throw new Error(`创建并渲染流程失败: ${error.message}`);
    }
  }

  // 渲染统计信息
  async getRenderStats() {
    // 这里可以扩展为查询渲染历史和统计信息的接口
    return {
      total_tasks: 0,
      completed_tasks: 0,
      failed_tasks: 0,
      total_render_time: 0
    };
  }
}

// 使用示例
const renderer = new VideoRenderer("1f0a1709-fa9e-4bf3-8180-6371b05f5fd6");

// 单个渲染任务
const draftUrl = "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/2025-03-01/draft/98598661-8583-4baa-89d1-1e27c688d695.json";
const result = await renderer.submitRenderTask(draftUrl);
console.log('任务提交成功:', result);

// 批量渲染任务
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 renderer.batchSubmitRenderTasks(draftUrls);
console.log('批量渲染结果:', batchResults);

// 完整流程
const draftData = {
  title: "我的视频项目",
  description: "测试视频描述"
};
const fullResult = await renderer.createAndRenderDraft(draftData);
console.log('完整流程结果:', fullResult);

Python 示例

import requests
import json
import time

class VideoRenderer:
    def __init__(self, api_token, base_url="https://jy-api.fyshark.com"):
        self.api_token = api_token
        self.base_url = base_url
    
    def submit_render_task(self, draft_url):
        """提交渲染任务"""
        
        url = f"{self.base_url}/api/drafts/gen_video"
        headers = {"Content-Type": "application/json"}
        data = {
            "api_token": self.api_token,
            "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 batch_submit_render_tasks(self, draft_urls):
        """批量提交渲染任务"""
        results = []
        
        for draft_url in draft_urls:
            try:
                result = self.submit_render_task(draft_url)
                results.append({
                    "success": True,
                    "draft_url": draft_url,
                    "task_id": result["task_id"],
                    "estimated_time": result["estimated_time"]
                })
            except Exception as e:
                results.append({
                    "success": False,
                    "draft_url": draft_url,
                    "error": str(e)
                })
        
        return results
    
    def create_and_render_draft(self, draft_data):
        """创建并渲染草稿(完整流程)"""
        try:
            # 1. 创建草稿
            create_url = f"{self.base_url}/api/drafts/create_draft"
            create_response = requests.post(
                create_url,
                headers={"Content-Type": "application/json"},
                json=draft_data
            )
            
            create_result = create_response.json()
            if create_result["status"] != "success":
                raise Exception(f"草稿创建失败: {create_result['message']}")
            
            draft_url = create_result["data"]["draft_url"]
            print(f"草稿创建成功: {draft_url}")
            
            # 2. 提交渲染任务
            render_result = self.submit_render_task(draft_url)
            print(f"渲染任务提交成功: {render_result['task_id']}")
            
            return {
                "draft_url": draft_url,
                "task_id": render_result["task_id"],
                "estimated_time": render_result["estimated_time"]
            }
            
        except Exception as e:
            raise Exception(f"创建并渲染流程失败: {str(e)}")

# 使用示例
renderer = VideoRenderer("1f0a1709-fa9e-4bf3-8180-6371b05f5fd6")

# 单个渲染任务
try:
    draft_url = "https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/2025-03-01/draft/98598661-8583-4baa-89d1-1e27c688d695.json"
    result = renderer.submit_render_task(draft_url)
    print("任务提交成功:")
    print(f"  任务ID: {result['task_id']}")
    print(f"  预计时间: {result['estimated_time']}秒")
    print(f"  提示: {result['tip']}")
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 = renderer.batch_submit_render_tasks(draft_urls)
for result in batch_results:
    if result["success"]:
        print(f"✅ {result['draft_url']} - 任务ID: {result['task_id']}")
    else:
        print(f"❌ {result['draft_url']} - 错误: {result['error']}")

# 完整流程示例
draft_data = {
    "title": "Python生成的视频项目",
    "description": "自动化视频制作测试"
}

try:
    full_result = renderer.create_and_render_draft(draft_data)
    print("完整流程执行成功:")
    print(f"  草稿URL: {full_result['draft_url']}")
    print(f"  任务ID: {full_result['task_id']}")
    print(f"  预计时间: {full_result['estimated_time']}秒")
except Exception as e:
    print(f"完整流程失败: {e}")

📊 错误码说明

状态码 错误类型 说明 解决方案
400 参数错误 必填参数缺失 检查 api_token 和 draft_url 参数
400 参数错误 draft_url 格式错误 使用有效的草稿URL格式
401 认证错误 API令牌无效 检查并更新API令牌
403 权限错误 令牌权限不足 联系管理员获取足够权限的令牌
404 资源错误 草稿文件不存在 确认草稿URL是否正确和文件是否存在
429 限制错误 请求频率过高 降低请求频率,添加重试机制
500 服务器错误 渲染服务异常 稍后重试或联系技术支持

⚠️ 注意事项

参数要求

  1. api_token: 必须是有效的云渲染服务令牌
  2. draft_url: 必须是可访问的草稿文件URL
  3. 文件格式: 草稿文件必须是有效的JSON格式
  4. 文件大小: 草稿文件大小建议不超过10MB

使用限制

  1. 令牌管理: API令牌需要妥善保管,避免泄露
  2. 并发限制: 同一令牌同时进行的渲染任务有数量限制
  3. 文件访问: 草稿文件必须公开可访问或提供正确的访问权限
  4. 计费规则: 每次渲染任务都会产生费用,请注意成本控制

渲染要求

  1. 草稿完整性: 确保草稿包含所有必要的素材和配置
  2. 素材可用性: 草稿中引用的所有素材文件必须可访问
  3. 格式兼容性: 素材格式必须被渲染服务支持
  4. 时长限制: 单个视频渲染时长可能有上限限制

性能考虑

  1. 渲染时间: 根据视频复杂度,渲染时间从几分钟到几小时不等
  2. 队列等待: 高峰期可能需要排队等待渲染资源
  3. 网络稳定: 确保网络连接稳定,避免传输中断
  4. 重试机制: 建议实现自动重试机制处理网络波动

🎨 应用场景

自动化视频制作

内容创作平台

企业应用

教育培训

🔄 工作流程

基本流程

1. 准备草稿文件
   ↓
2. 获取API令牌
   ↓
3. 提交渲染任务
   ↓
4. 获取任务ID
   ↓
5. 等待渲染完成
   ↓
6. 获取视频结果

完整流程示例

创建草稿 → 添加素材 → 设置样式 → 提交渲染 → 查询状态 → 下载视频
    ↓         ↓         ↓         ↓         ↓         ↓
create_draft  add_*     add_*   gen_video  查询API   结果通知

🔗 相关接口

草稿管理系列

内容编辑系列

样式设计系列

🚀 最佳实践

草稿准备

// ✅ 推荐:确保草稿完整性
const prepareDraft = async () => {
  // 1. 创建基础草稿
  const draft = await createDraft({ title: "测试视频" });
  
  // 2. 添加必要素材
  await addImages(draft.url, imageData);
  await addAudios(draft.url, audioData);
  await addCaptions(draft.url, captionData);
  
  // 3. 验证草稿完整性
  const isComplete = await validateDraft(draft.url);
  if (!isComplete) {
    throw new Error('草稿不完整,无法渲染');
  }
  
  return draft.url;
};

错误处理

// ✅ 推荐:完善的错误处理
const renderWithRetry = async (apiToken, draftUrl, maxRetries = 3) => {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const result = await generateVideo(apiToken, draftUrl);
      return result;
    } catch (error) {
      console.log(`渲染尝试 ${i + 1} 失败:`, error.message);
      
      if (i === maxRetries - 1) {
        throw new Error(`渲染失败,已重试 ${maxRetries} 次: ${error.message}`);
      }
      
      // 等待后重试
      await new Promise(resolve => setTimeout(resolve, 2000 * (i + 1)));
    }
  }
};

批量处理

// ✅ 推荐:批量处理优化
const batchRenderWithLimit = async (drafts, apiToken, limit = 3) => {
  const results = [];
  
  // 分批处理,避免并发过多
  for (let i = 0; i < drafts.length; i += limit) {
    const batch = drafts.slice(i, i + limit);
    
    const batchPromises = batch.map(async (draft) => {
      try {
        const result = await generateVideo(apiToken, draft.url);
        return { success: true, draft, result };
      } catch (error) {
        return { success: false, draft, error: error.message };
      }
    });
    
    const batchResults = await Promise.all(batchPromises);
    results.push(...batchResults);
    
    // 批次间添加延迟
    if (i + limit < drafts.length) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }
  
  return results;
};

成本控制

// ✅ 推荐:渲染前成本评估
const estimateRenderCost = (draftUrl) => {
  // 根据草稿复杂度估算渲染成本
  // 这里可以调用成本估算API或使用本地算法
  return {
    estimated_cost: 0.5, // 美元
    estimated_time: 120, // 秒
    complexity: 'medium' // low/medium/high
  };
};

const renderWithCostControl = async (apiToken, draftUrl, maxCost = 1.0) => {
  const estimate = estimateRenderCost(draftUrl);
  
  if (estimate.estimated_cost > maxCost) {
    throw new Error(`预估成本 $${estimate.estimated_cost} 超过限制 $${maxCost}`);
  }
  
  console.log(`预估成本: $${estimate.estimated_cost}, 预估时间: ${estimate.estimated_time}秒`);
  return await generateVideo(apiToken, draftUrl);
};

📖 版本历史


接口开发: JY API Team
文档更新: 2025年8月1日
技术支持: GitHub Issues
计费详情: https://www.51aigc.cc/#/plugins