JY API 草稿与素材创建接口使用指南

📄 API_USAGE_GUIDE.md 🕒 8/10/2025, 6:55:15 PM 📏 52KB

JY API 草稿与素材创建接口使用指南

📋 概述

本文档详细介绍如何使用JY API的十个核心接口:

这些接口配合使用可以实现完整的视频草稿创建、多媒体素材添加、专业级动画制作、视觉效果处理、装饰元素添加和高级视频合成工作流程。

🌐 服务器信息

📑 接口目录

  1. 创建草稿接口 (create_draft)
  2. 创建素材接口 (easy_create_material)
  3. 批量添加音频接口 (add_audios)
  4. 批量添加字幕接口 (add_captions)
  5. 批量添加特效接口 (add_effects)
  6. 批量添加图片接口 (add_images)
  7. 批量添加关键帧接口 (add_keyframes)
  8. 批量添加遮罩接口 (add_masks)
  9. 添加贴纸接口 (add_sticker)
  10. 批量添加视频接口 (add_videos)
  11. 完整工作流程示例
  12. 错误处理
  13. 最佳实践

1. 创建草稿接口 (create_draft)

接口信息

POST /api/drafts/create_draft

功能描述

创建一个空白的视频草稿,设置基本的画布尺寸和配置。这是整个工作流程的第一步。

请求参数

{
  "width": 1080,        // 可选,草稿宽度,默认1080
  "height": 1920,       // 可选,草稿高度,默认1920
  "user_id": 12345      // 可选,用户ID,如果提供会保存草稿记录
}

参数说明

参数 类型 必填 默认值 说明
width number 1080 草稿画布宽度(像素)
height number 1920 草稿画布高度(像素)
user_id number - 用户ID,用于草稿记录关联

响应格式

成功响应 (200)

{
  "status": "success",
  "message": "草稿创建成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=https://video-snot-12220.oss-cn-shanghai.aliyuncs.com/2025-08-01/draft/a97ada87-d30e-4c26-8a91-b9595e319822.json",
    "tip_url": "快速入门必看指南,请访问:https://www.51aigc.cc/#/cozeTutorial/detail/13",
    "record_saved": false
  }
}

错误响应 (500)

{
  "status": "error",
  "message": "创建草稿失败",
  "error": "具体错误信息"
}

使用示例

1. 基本创建(使用默认尺寸)

curl -X POST https://jy-api.fyshark.com/api/drafts/create_draft \
  -H "Content-Type: application/json" \
  -d '{}'

2. 指定尺寸创建

curl -X POST https://jy-api.fyshark.com/api/drafts/create_draft \
  -H "Content-Type: application/json" \
  -d '{
    "width": 720,
    "height": 1280
  }'

3. 包含用户ID的创建

curl -X POST https://jy-api.fyshark.com/api/drafts/create_draft \
  -H "Content-Type: application/json" \
  -d '{
    "width": 1080,
    "height": 1920,
    "user_id": 12345
  }'

4. JavaScript 示例

const createDraft = async (width = 1080, height = 1920, userId = null) => {
  const response = await fetch('https://jy-api.fyshark.com/api/drafts/create_draft', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      width,
      height,
      user_id: userId
    })
  });

  const result = await response.json();
  
  if (result.status === 'success') {
    console.log('草稿创建成功:', result.data.draft_url);
    return result.data.draft_url;
  } else {
    throw new Error(result.message);
  }
};

// 使用示例
try {
  const draftUrl = await createDraft(1080, 1920, 12345);
  console.log('新草稿URL:', draftUrl);
} catch (error) {
  console.error('创建失败:', error.message);
}

2. 创建素材接口 (easy_create_material)

接口信息

POST /api/drafts/easy_create_material

功能描述

在现有草稿中添加音频、视频、图片和文字素材。支持多种媒体类型的组合添加,自动处理素材的时长、尺寸和样式。

请求参数

{
  "text": "示例文字",                     // 可选,文字内容
  "img_url": "https://example.com/image.jpg",  // 可选,图片URL
  "video_url": "https://example.com/video.mp4", // 可选,视频URL
  "audio_url": "https://example.com/audio.mp3", // 必填,音频URL
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...", // 必填,目标草稿URL
  "text_color": "#ffffff",           // 可选,文字颜色,默认白色
  "font_size": 15,                   // 可选,字体大小,默认15
  "text_transform_y": 100            // 可选,文字Y轴位置偏移
}

参数说明

参数 类型 必填 默认值 说明
audio_url string - 音频文件URL,系统会自动获取时长
draft_url string - 目标草稿的完整URL
text string - 要添加的文字内容
img_url string - 图片URL,系统会自动获取尺寸
video_url string - 视频URL
text_color string "#ffffff" 文字颜色,十六进制格式
font_size number 15 字体大小
text_transform_y number - 文字在Y轴的位置偏移

响应格式

成功响应 (200)

{
  "status": "success",
  "message": "素材创建成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=..."
  }
}

错误响应

{
  "status": "error",
  "message": "错误信息",
  "draft_url": "原始草稿URL(如果提供)"
}

常见错误信息

使用示例

1. 基本素材添加(音频+文字)

curl -X POST https://jy-api.fyshark.com/api/drafts/easy_create_material \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hello World",
    "audio_url": "https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/artist/image/24631f7d1dd449e594097b6586b7d1b0.mp3",
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=YOUR_DRAFT_URL"
  }'

2. 完整素材添加(所有类型)

curl -X POST https://jy-api.fyshark.com/api/drafts/easy_create_material \
  -H "Content-Type: application/json" \
  -d '{
    "text": "完整测试",
    "img_url": "https://s.coze.cn/t/JTa5Ne6_liY/",
    "video_url": "https://example.com/video.mp4",
    "audio_url": "https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/artist/image/24631f7d1dd449e594097b6586b7d1b0.mp3",
    "draft_url": "YOUR_DRAFT_URL",
    "text_color": "#ff0000",
    "font_size": 20,
    "text_transform_y": 150
  }'

3. JavaScript 示例

const addMaterialToDraft = async (draftUrl, materials) => {
  const response = await fetch('https://jy-api.fyshark.com/api/drafts/easy_create_material', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      draft_url: draftUrl,
      ...materials
    })
  });

  const result = await response.json();
  
  if (result.status === 'success') {
    console.log('素材添加成功:', result.data.draft_url);
    return result.data.draft_url;
  } else {
    throw new Error(result.message);
  }
};

// 使用示例
const materials = {
  text: "我的视频标题",
  audio_url: "https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/artist/image/24631f7d1dd449e594097b6586b7d1b0.mp3",
  img_url: "https://s.coze.cn/t/JTa5Ne6_liY/",
  text_color: "#00ff00",
  font_size: 18
};

try {
  const updatedDraftUrl = await addMaterialToDraft(draftUrl, materials);
  console.log('更新后的草稿:', updatedDraftUrl);
} catch (error) {
  console.error('添加素材失败:', error.message);
}

3. 批量添加音频接口 (add_audios)

接口信息

POST /api/drafts/add_audios

功能描述

向现有草稿中批量添加音频轨道和音频片段。支持多个音频文件的同时添加,每个音频可以设置不同的时间范围、音量和音效。

请求参数

{
  "audio_infos": "[{\"audio_url\":\"https://example.com/audio.mp3\",\"duration\":23184000,\"end\":23184000,\"start\":0,\"volume\":1.0}]",
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=..."
}

参数说明

参数 类型 必填 默认值 说明
audio_infos string - JSON字符串格式的音频信息数组
draft_url string - 目标草稿的完整URL

audio_infos 数组元素说明

参数名 类型 必填 默认值 说明
audio_url string - 音频文件URL
duration number - 音频总时长(微秒)
start number - 音频片段开始时间(微秒)
end number - 音频片段结束时间(微秒)
volume number 1.0 音频音量(0.0-2.0)
audio_effect string - 音频效果名称

响应格式

成功响应 (200)

{
  "status": "success",
  "message": "音频添加成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
    "track_id": "audio_track_123",
    "audio_ids": ["audio_001", "audio_002"]
  }
}

错误响应

{
  "status": "error",
  "message": "音频信息验证失败",
  "errors": ["audio_infos[0].audio_url is required"]
}

使用示例

1. 基本音频添加

curl -X POST https://jy-api.fyshark.com/api/drafts/add_audios \
  -H "Content-Type: application/json" \
  -d '{
    "audio_infos": "[{\"audio_url\":\"https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/sami/tts/fe9baa8f474e4a20a293b7228707ff9c.mp3\",\"duration\":23184000,\"end\":23184000,\"start\":0}]",
    "draft_url": "YOUR_DRAFT_URL"
  }'

2. 多音频批量添加

curl -X POST https://jy-api.fyshark.com/api/drafts/add_audios \
  -H "Content-Type: application/json" \
  -d '{
    "audio_infos": "[{\"audio_url\":\"https://example.com/audio1.mp3\",\"duration\":10000000,\"start\":0,\"end\":10000000,\"volume\":0.8},{\"audio_url\":\"https://example.com/audio2.mp3\",\"duration\":15000000,\"start\":5000000,\"end\":15000000,\"volume\":1.2}]",
    "draft_url": "YOUR_DRAFT_URL"
  }'

3. JavaScript 示例

const addAudios = async (audioInfos, draftUrl) => {
  const response = await fetch('https://jy-api.fyshark.com/api/drafts/add_audios', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      audio_infos: JSON.stringify(audioInfos),
      draft_url: draftUrl
    })
  });

  const result = await response.json();
  return result;
};

// 使用示例
const audioInfos = [
  {
    audio_url: "https://example.com/audio1.mp3",
    duration: 23184000,
    start: 0,
    end: 23184000,
    volume: 1.0
  },
  {
    audio_url: "https://example.com/audio2.mp3", 
    duration: 15000000,
    start: 5000000,
    end: 15000000,
    volume: 0.8
  }
];

try {
  const result = await addAudios(audioInfos, draftUrl);
  console.log('音频添加成功:', result.data);
} catch (error) {
  console.error('添加失败:', error);
}

4. 批量添加字幕接口 (add_captions)

接口信息

POST /api/drafts/add_captions

功能描述

向现有草稿中添加字幕轨道和字幕片段。支持丰富的字幕样式设置,包括关键词高亮、字体样式、边框效果、对齐方式、透明度和动画效果等。

请求参数

{
  "captions": "[{\"start\":0,\"end\":10000000,\"text\":\"你好,剪映\",\"keyword\":\"好\",\"keyword_color\":\"#457616\",\"keyword_font_size\":15}]",
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
  "text_color": "#ff1837",
  "border_color": "#fe8a80",
  "alignment": 2,
  "alpha": 0.5
}

参数说明

参数 类型 必填 默认值 说明
captions string - JSON字符串格式的字幕信息数组
draft_url string - 目标草稿的完整URL
text_color string "#ffffff" 文本颜色(十六进制)
border_color string - 边框颜色(十六进制)
alignment number 1 文本对齐方式(0-5)
alpha number 1.0 文本透明度(0.0-1.0)

响应格式

成功响应 (200)

{
  "status": "success",
  "message": "字幕添加成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
    "track_id": "text_track_123",
    "text_ids": ["text_001", "text_002"],
    "segment_ids": ["seg_001", "seg_002"],
    "segment_infos": [
      {
        "id": "seg_001",
        "start": 0,
        "end": 10000000
      }
    ]
  }
}

使用示例

1. 基本字幕添加

curl -X POST https://jy-api.fyshark.com/api/drafts/add_captions \
  -H "Content-Type: application/json" \
  -d '{
    "captions": "[{\"start\":0,\"end\":10000000,\"text\":\"你好,剪映\",\"keyword\":\"好\",\"keyword_color\":\"#457616\"}]",
    "draft_url": "YOUR_DRAFT_URL",
    "text_color": "#ff1837",
    "alignment": 2
  }'

2. 带动画效果的字幕

curl -X POST https://jy-api.fyshark.com/api/drafts/add_captions \
  -H "Content-Type: application/json" \
  -d '{
    "captions": "[{\"start\":0,\"end\":10000000,\"text\":\"欢迎使用字幕功能\",\"in_animation\":\"fade_in\",\"out_animation\":\"fade_out\"}]",
    "draft_url": "YOUR_DRAFT_URL",
    "text_color": "#ffffff",
    "alpha": 0.8
  }'

3. JavaScript 示例

const addCaptions = async (captionsData, draftUrl, options = {}) => {
  const response = await fetch('https://jy-api.fyshark.com/api/drafts/add_captions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      captions: JSON.stringify(captionsData),
      draft_url: draftUrl,
      text_color: options.textColor || "#ffffff",
      border_color: options.borderColor,
      alignment: options.alignment || 1,
      alpha: options.alpha || 1.0
    })
  });

  const result = await response.json();
  return result;
};

// 使用示例
const captions = [
  {
    start: 0,
    end: 10000000,
    text: "你好,剪映",
    keyword: "好|剪映",
    keyword_color: "#457616",
    keyword_font_size: 15
  },
  {
    start: 10000000,
    end: 20000000,
    text: "欢迎使用字幕功能",
    in_animation: "fade_in",
    out_animation: "fade_out"
  }
];

try {
  const result = await addCaptions(captions, draftUrl, {
    textColor: "#ff1837",
    borderColor: "#fe8a80",
    alignment: 2,
    alpha: 0.8
  });
  console.log('字幕添加成功:', result.data);
} catch (error) {
  console.error('添加失败:', error);
}

高级功能

关键词高亮

{
  "text": "你好,剪映",
  "keyword": "好|剪映",
  "keyword_color": "#ff0000",
  "keyword_font_size": 18
}

动画效果

{
  "in_animation": "fade_in",
  "out_animation": "fade_out",
  "in_animation_duration": 1000000,
  "out_animation_duration": 1000000
}

5. 批量添加特效接口 (add_effects)

接口信息

POST /api/drafts/add_effects

功能描述

向现有草稿中添加视频特效轨道和特效片段。支持批量添加多种视频特效,包括边框特效、滤镜特效、动态特效等,为视频内容增加丰富的视觉效果。

请求参数

{
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
  "effect_infos": "[{\"effect_title\":\"录制边框 III\",\"end\":5000000,\"start\":0}]"
}

参数说明

参数 类型 必填 默认值 说明
draft_url string - 目标草稿的完整URL
effect_infos string - JSON字符串格式的特效信息数组

响应格式

成功响应 (200)

{
  "status": "success",
  "message": "特效添加成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
    "track_id": "effect_track_123",
    "effect_ids": ["effect_001", "effect_002"],
    "segment_ids": ["seg_001", "seg_002"]
  }
}

使用示例

1. 基本特效添加

curl -X POST https://jy-api.fyshark.com/api/drafts/add_effects \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "effect_infos": "[{\"effect_title\":\"录制边框 III\",\"end\":5000000,\"start\":0}]"
  }'

2. 多特效添加

curl -X POST https://jy-api.fyshark.com/api/drafts/add_effects \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "effect_infos": "[{\"effect_title\":\"录制边框\",\"end\":10000000,\"start\":2000000},{\"effect_title\":\"淡入效果\",\"end\":5000000,\"start\":0}]"
  }'

3. JavaScript 示例

const addEffects = async (effectsData, draftUrl) => {
  const response = await fetch('https://jy-api.fyshark.com/api/drafts/add_effects', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      effect_infos: JSON.stringify(effectsData),
      draft_url: draftUrl
    })
  });

  const result = await response.json();
  return result;
};

// 使用示例
const effects = [
  {
    effect_title: "录制边框 III",
    start: 0,
    end: 5000000
  },
  {
    effect_title: "复古滤镜",
    start: 2000000,
    end: 8000000
  }
];

try {
  const result = await addEffects(effects, draftUrl);
  console.log('特效添加成功:', result.data);
} catch (error) {
  console.error('添加失败:', error);
}

常见特效类型

边框特效

{
  "effect_title": "录制边框 III",
  "start": 0,
  "end": 10000000
}

滤镜特效

{
  "effect_title": "复古滤镜",
  "start": 0,
  "end": 15000000
}

动态特效

{
  "effect_title": "粒子效果",
  "start": 5000000,
  "end": 20000000
}

6. 批量添加图片接口 (add_images)

接口信息

POST /api/drafts/add_images

功能描述

向现有草稿中批量添加图片素材,支持丰富的视觉效果设置。该接口可以一次性添加多张图片到视频轨道,支持透明度控制、动画效果、缩放变换、位置调整以及转场效果,为视频创作提供强大的图片处理能力。

请求参数

{
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
  "image_infos": "[{\"image_url\":\"https://s.coze.cn/t/XpufYwc2_u4/\",\"width\":1024,\"height\":1024,\"start\":0,\"end\":1000000}]",
  "alpha": 0.5,
  "scale_x": 1.0,
  "scale_y": 1.0,
  "transform_x": 0,
  "transform_y": 0
}

参数说明

参数 类型 必填 默认值 说明
draft_url string - 目标草稿的完整URL
image_infos string - JSON字符串格式的图片信息数组
alpha number 1.0 全局透明度,范围0-1
scale_x number 1.0 X轴缩放比例
scale_y number 1.0 Y轴缩放比例
transform_x number 0 X轴位置偏移(像素)
transform_y number 0 Y轴位置偏移(像素)

响应格式

成功响应 (200)

{
  "status": "success",
  "message": "图片添加成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
    "track_id": "video_track_123",
    "image_ids": ["image_001", "image_002"],
    "segment_ids": ["seg_001", "seg_002"],
    "segment_infos": [
      {
        "id": "seg_001",
        "start": 0,
        "end": 1000000
      }
    ]
  }
}

使用示例

1. 基本图片添加

curl -X POST https://jy-api.fyshark.com/api/drafts/add_images \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "image_infos": "[{\"image_url\":\"https://s.coze.cn/t/XpufYwc2_u4/\",\"width\":1024,\"height\":1024,\"start\":0,\"end\":1000000}]"
  }'

2. 带动画效果的多图片

curl -X POST https://jy-api.fyshark.com/api/drafts/add_images \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "image_infos": "[{\"image_url\":\"https://example.com/image1.jpg\",\"width\":800,\"height\":600,\"start\":0,\"end\":2000000,\"in_animation\":\"淡入\",\"out_animation\":\"淡出\"},{\"image_url\":\"https://example.com/image2.jpg\",\"width\":1024,\"height\":1024,\"start\":2500000,\"end\":4500000}]",
    "alpha": 0.8,
    "scale_x": 1.2,
    "scale_y": 1.2
  }'

3. JavaScript 示例

const addImages = async (imagesData, draftUrl, options = {}) => {
  const response = await fetch('https://jy-api.fyshark.com/api/drafts/add_images', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      image_infos: JSON.stringify(imagesData),
      draft_url: draftUrl,
      ...options
    })
  });

  const result = await response.json();
  return result;
};

// 使用示例
const images = [
  {
    image_url: "https://example.com/image1.jpg",
    width: 1024,
    height: 1024,
    start: 0,
    end: 2000000,
    in_animation: "淡入",
    in_animation_duration: 500000
  },
  {
    image_url: "https://example.com/image2.jpg",
    width: 800,
    height: 600,
    start: 2500000,
    end: 4500000,
    transition: "淡入淡出",
    transition_duration: 1000000
  }
];

const options = {
  alpha: 0.9,
  scale_x: 1.1,
  scale_y: 1.1,
  transform_y: 100
};

try {
  const result = await addImages(images, draftUrl, options);
  console.log('图片添加成功:', result.data);
} catch (error) {
  console.error('添加失败:', error);
}

图片动画类型

入场动画

{
  "in_animation": "淡入",
  "in_animation_duration": 500000
}

出场动画

{
  "out_animation": "淡出", 
  "out_animation_duration": 500000
}

循环动画

{
  "loop_animation": "呼吸",
  "loop_animation_duration": 2000000
}

转场效果

{
  "transition": "淡入淡出",
  "transition_duration": 1000000
}

7. 批量添加关键帧接口 (add_keyframes)

接口信息

POST /api/drafts/add_keyframes

功能描述

向现有草稿中的指定片段添加关键帧动画。关键帧动画是视频编辑中的高级功能,通过在时间轴上设置不同时间点的属性值,系统会自动计算中间过渡效果,创造出平滑的动画变化。支持位置、缩放、旋转、透明度等多种属性的关键帧动画。

请求参数

{
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
  "keyframes": "[{\"offset\":0,\"property\":\"KFTypePositionX\",\"segment_id\":\"d62994b4-25fe-422a-a123-87ef05038558\",\"value\":-0.1}]"
}

参数说明

参数名 类型 必填 默认值 说明
draft_url string - 目标草稿的完整URL
keyframes string - JSON字符串格式的关键帧信息数组

keyframes 数组元素说明

参数名 类型 必填 默认值 说明
segment_id string - 目标片段的唯一标识ID
property string - 动画属性类型
offset number - 关键帧在片段中的时间偏移(0-1范围)
value number - 属性在该时间点的值

支持的动画属性类型

属性类型 描述 值范围 示例
KFTypePositionX X轴位置 -1.0 到 1.0 0.0 (居中), -0.5 (左移), 0.5 (右移)
KFTypePositionY Y轴位置 -1.0 到 1.0 0.0 (居中), -0.5 (上移), 0.5 (下移)
KFTypeScaleX X轴缩放 0.1 到 10.0 1.0 (原始), 0.5 (缩小), 2.0 (放大)
KFTypeScaleY Y轴缩放 0.1 到 10.0 1.0 (原始), 0.5 (缩小), 2.0 (放大)
KFTypeRotation 旋转角度 -360 到 360 0 (无旋转), 90 (顺时针90度)
KFTypeAlpha 透明度 0.0 到 1.0 1.0 (不透明), 0.5 (半透明), 0.0 (透明)

响应格式

成功响应 (200)

{
  "status": "success",
  "message": "关键帧添加成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
    "keyframes_added": 3,
    "affected_segments": ["segment_001", "segment_002"]
  }
}

使用示例

1. 基本位置动画

curl -X POST https://jy-api.fyshark.com/api/drafts/add_keyframes \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "keyframes": "[{\"offset\":0,\"property\":\"KFTypePositionX\",\"segment_id\":\"your-segment-id\",\"value\":-0.5},{\"offset\":1,\"property\":\"KFTypePositionX\",\"segment_id\":\"your-segment-id\",\"value\":0.5}]"
  }'

2. 缩放呼吸动画

curl -X POST https://jy-api.fyshark.com/api/drafts/add_keyframes \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "keyframes": "[{\"offset\":0,\"property\":\"KFTypeScaleX\",\"segment_id\":\"your-segment-id\",\"value\":0.8},{\"offset\":0.5,\"property\":\"KFTypeScaleX\",\"segment_id\":\"your-segment-id\",\"value\":1.2},{\"offset\":1,\"property\":\"KFTypeScaleX\",\"segment_id\":\"your-segment-id\",\"value\":1.0}]"
  }'

3. JavaScript 示例

const addKeyframes = async (keyframesData, draftUrl) => {
  const response = await fetch('https://jy-api.fyshark.com/api/drafts/add_keyframes', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      keyframes: JSON.stringify(keyframesData),
      draft_url: draftUrl
    })
  });

  const result = await response.json();
  return result;
};

// 使用示例 - 位置移动动画
const positionKeyframes = [
  {
    segment_id: "your-segment-id",
    property: "KFTypePositionX",
    offset: 0,
    value: -0.5  // 开始位置:左侧
  },
  {
    segment_id: "your-segment-id", 
    property: "KFTypePositionX",
    offset: 1,
    value: 0.5   // 结束位置:右侧
  }
];

try {
  const result = await addKeyframes(positionKeyframes, draftUrl);
  console.log('关键帧添加成功:', result.data);
} catch (error) {
  console.error('添加失败:', error);
}

关键帧动画类型

位置动画

{
  "property": "KFTypePositionX",
  "offset": 0,
  "value": -0.5
}

缩放动画

{
  "property": "KFTypeScaleX", 
  "offset": 0.5,
  "value": 1.2
}

旋转动画

{
  "property": "KFTypeRotation",
  "offset": 1,
  "value": 360
}

透明度动画

{
  "property": "KFTypeAlpha",
  "offset": 0,
  "value": 0.0
}

8. 批量添加遮罩接口 (add_masks)

接口信息

POST /api/drafts/add_masks

功能描述

向现有草稿中的指定片段添加遮罩效果。遮罩是视频编辑中的重要功能,通过遮罩可以控制图像的可见区域,创造出各种视觉效果。支持多种遮罩类型(线性、镜面、圆形、矩形、爱心、星形),每种遮罩都可以精确配置位置、大小、羽化、旋转等属性。

请求参数

{
  "X": 100,
  "Y": 30,
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
  "feather": 22,
  "name": "线性",
  "rotation": 20,
  "segment_ids": [
    "1381ae8d-4acf-49af-b3cc-26e3c5ff648b"
  ],
  "width": 512,
  "height": 512,
  "invert": false,
  "roundCorner": 0
}

参数说明

参数名 类型 必填 默认值 说明
draft_url string - 目标草稿的完整URL
segment_ids array - 要应用遮罩的片段ID数组
name string "线性" 遮罩类型名称
X number 0 遮罩中心X坐标(像素)
Y number 0 遮罩中心Y坐标(像素)
width number 512 遮罩宽度(像素)
height number 512 遮罩高度(像素)
feather number 0 羽化程度(0-100)
rotation number 0 旋转角度(度)
invert boolean false 是否反转遮罩
roundCorner number 0 圆角半径(0-100)

支持的遮罩类型

遮罩名称 描述 适用场景
线性 线性渐变遮罩 线性过渡效果、渐变显示隐藏
镜面 镜像对称遮罩 对称效果、镜像反射
圆形 圆形遮罩 聚光灯效果、圆形裁剪
矩形 矩形遮罩 窗口效果、矩形裁剪
爱心 爱心形状遮罩 浪漫场景、特殊形状裁剪
星形 星形遮罩 闪光效果、装饰性裁剪

响应格式

成功响应 (200)

{
  "status": "success",
  "message": "遮罩添加成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
    "masks_added": 2,
    "affected_segments": ["segment_001", "segment_002"],
    "mask_ids": ["mask_001", "mask_002"]
  }
}

使用示例

1. 基本线性遮罩

curl -X POST https://jy-api.fyshark.com/api/drafts/add_masks \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "segment_ids": ["your-segment-id"],
    "name": "线性",
    "X": 100,
    "Y": 50,
    "feather": 20
  }'

2. 圆形聚光灯遮罩

curl -X POST https://jy-api.fyshark.com/api/drafts/add_masks \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "segment_ids": ["your-segment-id"],
    "name": "圆形",
    "X": 200,
    "Y": 200,
    "width": 300,
    "height": 300,
    "feather": 50
  }'

3. JavaScript 示例

const addMasks = async (maskConfig, draftUrl) => {
  const response = await fetch('https://jy-api.fyshark.com/api/drafts/add_masks', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      draft_url: draftUrl,
      ...maskConfig
    })
  });

  const result = await response.json();
  return result;
};

// 使用示例 - 线性渐变遮罩
const linearMask = {
  segment_ids: ["your-segment-id"],
  name: "线性",
  X: 100,
  Y: 50,
  width: 600,
  height: 100,
  feather: 25,
  rotation: 0
};

// 使用示例 - 圆形聚光灯效果
const spotlightMask = {
  segment_ids: ["your-segment-id"],
  name: "圆形",
  X: 200,
  Y: 200,
  width: 300,
  height: 300,
  feather: 40,
  invert: false
};

try {
  const result = await addMasks(linearMask, draftUrl);
  console.log('遮罩添加成功:', result.data);
} catch (error) {
  console.error('添加失败:', error);
}

遮罩效果类型

线性遮罩

{
  "name": "线性",
  "X": 100,
  "Y": 50,
  "feather": 25
}

圆形遮罩

{
  "name": "圆形",
  "X": 200,
  "Y": 200,
  "width": 300,
  "height": 300
}

矩形遮罩

{
  "name": "矩形",
  "X": 150,
  "Y": 100,
  "width": 400,
  "height": 200,
  "roundCorner": 20
}

装饰遮罩

{
  "name": "爱心",
  "X": 250,
  "Y": 200,
  "rotation": 15,
  "invert": true
}

9. 添加贴纸接口 (add_sticker)

接口信息

请求参数

{
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
  "sticker_id": "7326810673609018675",
  "start": 0,
  "end": 5000000,
  "scale": 2,
  "transform_x": 500,
  "transform_y": 900
}

参数说明

参数名 类型 必填 默认值 说明
draft_url string - 目标草稿的完整URL
sticker_id string - 贴纸的唯一标识ID
start number - 贴纸开始时间(微秒)
end number - 贴纸结束时间(微秒)
scale number 1.0 贴纸缩放比例
transform_x number 0 X轴位置偏移(像素)
transform_y number 0 Y轴位置偏移(像素)

使用示例

基本贴纸添加

curl -X POST https://jy-api.fyshark.com/api/drafts/add_sticker \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "sticker_id": "7326810673609018675",
    "start": 0,
    "end": 5000000
  }'

带缩放和位置的贴纸

curl -X POST https://jy-api.fyshark.com/api/drafts/add_sticker \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "sticker_id": "7326810673609018675",
    "start": 0,
    "end": 5000000,
    "scale": 2,
    "transform_x": 500,
    "transform_y": 900
  }'

JavaScript示例

const addSticker = async (draftUrl, stickerConfig) => {
  const response = await fetch('/api/drafts/add_sticker', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      draft_url: draftUrl,
      ...stickerConfig
    })
  });
  return response.json();
};

// 角落装饰贴纸
const cornerSticker = {
  sticker_id: "7326810673609018675",
  start: 0,
  end: 10000000,
  scale: 0.8,
  transform_x: 400,
  transform_y: -300
};

// 中心强调贴纸
const centerSticker = {
  sticker_id: "7326810673609018675", 
  start: 5000000,
  end: 8000000,
  scale: 2.0,
  transform_x: 0,
  transform_y: 0
};

await addSticker(draftUrl, cornerSticker);
await addSticker(draftUrl, centerSticker);

响应格式

{
  "status": "success",
  "message": "贴纸添加成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
    "sticker_id": "7326810673609018675",
    "track_id": "track-uuid",
    "segment_id": "segment-uuid", 
    "duration": 5000000
  }
}

应用场景

注意事项

  1. 时间单位: start和end使用微秒(1秒 = 1,000,000微秒)
  2. 坐标系统: transform_x和transform_y以画布中心为原点
  3. 缩放范围: 建议scale值在0.1-5.0之间
  4. 性能考虑: 建议单个视频贴纸数量不超过10个

10. 批量添加视频接口 (add_videos)

接口信息

请求参数

{
  "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
  "video_infos": "[{\"video_url\":\"https://example.com/video1.mp4\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":5000000,\"duration\":10000000,\"mask\":\"圆形\",\"transition\":\"淡入淡出\",\"transition_duration\":500000,\"volume\":0.8}]",
  "alpha": 0.8,
  "scale_x": 1.2,
  "scale_y": 1.2,
  "transform_x": 100,
  "transform_y": 200
}

参数说明

参数名 类型 必填 默认值 说明
draft_url string - 目标草稿的完整URL
video_infos string - 视频信息数组的JSON字符串
alpha number 1.0 全局透明度(0-1)
scale_x number 1.0 X轴缩放比例
scale_y number 1.0 Y轴缩放比例
transform_x number 0 X轴位置偏移(像素)
transform_y number 0 Y轴位置偏移(像素)

video_infos 数组中每个视频的参数

字段名 类型 必填 说明
video_url string 视频文件的URL地址
width number 视频宽度(像素)
height number 视频高度(像素)
start number 视频开始播放时间(微秒)
end number 视频结束播放时间(微秒)
duration number 视频总时长(微秒)
mask string 遮罩类型(圆形、爱心、星形、矩形、线性、镜面)
transition string 转场效果名称
transition_duration number 转场持续时间(100000-2500000微秒)
volume number 音量大小(0-1)

使用示例

基本视频添加

curl -X POST https://jy-api.fyshark.com/api/drafts/add_videos \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "video_infos": "[{\"video_url\":\"https://example.com/video1.mp4\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":5000000,\"duration\":10000000}]"
  }'

多视频序列

curl -X POST https://jy-api.fyshark.com/api/drafts/add_videos \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "video_infos": "[{\"video_url\":\"https://example.com/intro.mp4\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":3000000,\"duration\":5000000,\"transition\":\"淡入淡出\"},{\"video_url\":\"https://example.com/main.mp4\",\"width\":1920,\"height\":1080,\"start\":3000000,\"end\":13000000,\"duration\":15000000,\"volume\":0.8}]",
    "alpha": 1.0
  }'

画中画效果

curl -X POST https://jy-api.fyshark.com/api/drafts/add_videos \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL",
    "video_infos": "[{\"video_url\":\"https://example.com/background.mp4\",\"width\":1920,\"height\":1080,\"start\":0,\"end\":10000000,\"duration\":15000000},{\"video_url\":\"https://example.com/overlay.mp4\",\"width\":640,\"height\":360,\"start\":2000000,\"end\":8000000,\"duration\":10000000,\"mask\":\"圆形\"}]",
    "scale_x": 0.8,
    "scale_y": 0.8,
    "transform_x": 200,
    "transform_y": -150
  }'

JavaScript示例

const addVideos = async (draftUrl, videoConfig) => {
  const response = await fetch('/api/drafts/add_videos', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      draft_url: draftUrl,
      ...videoConfig
    })
  });
  return response.json();
};

// 视频序列配置
const videoSequence = {
  video_infos: JSON.stringify([
    {
      video_url: "https://example.com/intro.mp4",
      width: 1920,
      height: 1080,
      start: 0,
      end: 3000000,
      duration: 5000000,
      transition: "淡入淡出",
      transition_duration: 500000
    },
    {
      video_url: "https://example.com/main.mp4",
      width: 1920,
      height: 1080,
      start: 3000000,
      end: 15000000,
      duration: 20000000,
      volume: 0.8
    }
  ]),
  alpha: 1.0
};

// 画中画配置
const pipConfig = {
  video_infos: JSON.stringify([
    {
      video_url: "https://example.com/background.mp4",
      width: 1920,
      height: 1080,
      start: 0,
      end: 10000000,
      duration: 15000000
    },
    {
      video_url: "https://example.com/overlay.mp4",
      width: 640,
      height: 360,
      start: 2000000,
      end: 8000000,
      duration: 10000000,
      mask: "圆形"
    }
  ]),
  scale_x: 0.3,
  scale_y: 0.3,
  transform_x: 300,
  transform_y: -200,
  alpha: 0.9
};

try {
  const result1 = await addVideos(draftUrl, videoSequence);
  const result2 = await addVideos(draftUrl, pipConfig);
  
  console.log('视频添加成功:', {
    sequence: result1.data,
    pip: result2.data
  });
} catch (error) {
  console.error('添加失败:', error);
}

响应格式

{
  "status": "success",
  "message": "视频批量添加成功",
  "data": {
    "draft_url": "https://ts.fyshark.com/#/cozeToJianyin?drafId=...",
    "track_id": "video-track-uuid",
    "video_ids": ["video1-uuid", "video2-uuid"],
    "segment_ids": ["segment1-uuid", "segment2-uuid"],
    "videos_count": 2,
    "total_duration": 10000000
  }
}

应用场景

注意事项

  1. JSON格式: video_infos必须是合法的JSON字符串
  2. 时间单位: 所有时间参数使用微秒(1秒 = 1,000,000微秒)
  3. 视频格式: 确保视频文件格式被支持
  4. 网络访问: 视频URL必须可以正常访问
  5. 遮罩类型: 支持6种预定义遮罩类型
  6. 转场时长: 范围限制在100000-2500000微秒之间
  7. 性能考虑: 批量添加大量视频可能影响性能

11. 完整工作流程示例

工作流程图

1. 创建草稿 → 2. 获取草稿URL → 3a. 添加素材   → 4. 添加动画   → 5. 添加视效   → 6. 添加装饰 → 7. 完成制作
                              ↘ 3b. 批量添加音频 ↗ ↘ 4a. 关键帧动画 ↗ ↘ 5a. 遮罩效果 ↗ ↘ 6a. 添加贴纸 ↗
                              ↘ 3c. 批量添加字幕 ↗
                              ↘ 3d. 批量添加特效 ↗
                              ↘ 3e. 批量添加图片 ↗
                              ↘ 3f. 批量添加视频 ↗

完整的JavaScript工作流程

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

  // 步骤1: 创建草稿
  async createDraft(width = 1080, height = 1920, userId = null) {
    const response = await fetch(`${this.baseUrl}/api/drafts/create_draft`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ width, height, user_id: userId })
    });

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

    console.log('✅ 草稿创建成功');
    return result.data.draft_url;
  }

  // 步骤2a: 添加综合素材
  async addMaterials(draftUrl, materials) {
    // 验证必要参数
    if (!materials.audio_url) {
      throw new Error('音频URL是必需的');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/easy_create_material`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        draft_url: draftUrl,
        ...materials
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加素材失败: ${result.message}`);
    }

    console.log('✅ 素材添加成功');
    return result.data.draft_url;
  }

  // 步骤2b: 批量添加音频
  async addAudios(draftUrl, audioInfos) {
    // 验证必要参数
    if (!Array.isArray(audioInfos) || audioInfos.length === 0) {
      throw new Error('音频信息数组不能为空');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/add_audios`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        audio_infos: JSON.stringify(audioInfos),
        draft_url: draftUrl
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加音频失败: ${result.message}`);
    }

    console.log('✅ 音频添加成功');
    return {
      draft_url: result.data.draft_url,
      track_id: result.data.track_id,
      audio_ids: result.data.audio_ids
    };
  }

  // 步骤2c: 批量添加字幕
  async addCaptions(draftUrl, captions, options = {}) {
    // 验证必要参数
    if (!Array.isArray(captions) || captions.length === 0) {
      throw new Error('字幕信息数组不能为空');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/add_captions`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        captions: JSON.stringify(captions),
        draft_url: draftUrl,
        text_color: options.textColor || "#ffffff",
        border_color: options.borderColor,
        alignment: options.alignment || 1,
        alpha: options.alpha || 1.0,
        font: options.font,
        font_size: options.fontSize || 15
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加字幕失败: ${result.message}`);
    }

    console.log('✅ 字幕添加成功');
    return {
      draft_url: result.data.draft_url,
      track_id: result.data.track_id,
      text_ids: result.data.text_ids,
      segment_ids: result.data.segment_ids,
      segment_infos: result.data.segment_infos
    };
  }

  // 步骤2d: 批量添加特效
  async addEffects(draftUrl, effects) {
    // 验证必要参数
    if (!Array.isArray(effects) || effects.length === 0) {
      throw new Error('特效信息数组不能为空');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/add_effects`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        effect_infos: JSON.stringify(effects),
        draft_url: draftUrl
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加特效失败: ${result.message}`);
    }

    console.log('✅ 特效添加成功');
    return {
      draft_url: result.data.draft_url,
      track_id: result.data.track_id,
      effect_ids: result.data.effect_ids,
      segment_ids: result.data.segment_ids
    };
  }

  // 步骤2e: 批量添加图片
  async addImages(draftUrl, images, options = {}) {
    // 验证必要参数
    if (!Array.isArray(images) || images.length === 0) {
      throw new Error('图片信息数组不能为空');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/add_images`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        image_infos: JSON.stringify(images),
        draft_url: draftUrl,
        ...options
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加图片失败: ${result.message}`);
    }

    console.log('✅ 图片添加成功');
    return {
      draft_url: result.data.draft_url,
      track_id: result.data.track_id,
      image_ids: result.data.image_ids,
      segment_ids: result.data.segment_ids,
      segment_infos: result.data.segment_infos
    };
  }

  // 步骤2f: 批量添加关键帧
  async addKeyframes(draftUrl, keyframes) {
    // 验证必要参数
    if (!Array.isArray(keyframes) || keyframes.length === 0) {
      throw new Error('关键帧信息数组不能为空');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/add_keyframes`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        keyframes: JSON.stringify(keyframes),
        draft_url: draftUrl
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加关键帧失败: ${result.message}`);
    }

    console.log('✅ 关键帧添加成功');
    return {
      draft_url: result.data.draft_url,
      keyframes_added: result.data.keyframes_added,
      affected_segments: result.data.affected_segments
    };
  }

  // 步骤2g: 批量添加遮罩
  async addMasks(draftUrl, maskConfig) {
    // 验证必要参数
    if (!maskConfig.segment_ids || !Array.isArray(maskConfig.segment_ids) || maskConfig.segment_ids.length === 0) {
      throw new Error('segment_ids数组不能为空');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/add_masks`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        draft_url: draftUrl,
        ...maskConfig
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加遮罩失败: ${result.message}`);
    }

    console.log('✅ 遮罩添加成功');
    return {
      draft_url: result.data.draft_url,
      masks_added: result.data.masks_added,
      affected_segments: result.data.affected_segments,
      mask_ids: result.data.mask_ids
    };
  }

  // 步骤2h: 添加贴纸
  async addSticker(draftUrl, stickerConfig) {
    // 验证必要参数
    if (!stickerConfig.sticker_id) {
      throw new Error('sticker_id是必需的');
    }

    if (typeof stickerConfig.start !== 'number' || typeof stickerConfig.end !== 'number') {
      throw new Error('start和end必须是数字类型(微秒)');
    }

    if (stickerConfig.start >= stickerConfig.end) {
      throw new Error('end必须大于start');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/add_sticker`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        draft_url: draftUrl,
        ...stickerConfig
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加贴纸失败: ${result.message}`);
    }

    console.log('✅ 贴纸添加成功');
    return {
      draft_url: result.data.draft_url,
      sticker_id: result.data.sticker_id,
      track_id: result.data.track_id,
      segment_id: result.data.segment_id,
      duration: result.data.duration
    };
  }

  // 步骤2i: 批量添加视频
  async addVideos(draftUrl, videoConfig) {
    // 验证必要参数
    if (!videoConfig.video_infos) {
      throw new Error('video_infos是必需的');
    }

    // 验证JSON格式
    let videoInfos;
    try {
      videoInfos = JSON.parse(videoConfig.video_infos);
    } catch (e) {
      throw new Error('video_infos必须是有效的JSON字符串');
    }

    if (!Array.isArray(videoInfos) || videoInfos.length === 0) {
      throw new Error('video_infos必须是非空数组');
    }

    const response = await fetch(`${this.baseUrl}/api/drafts/add_videos`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        draft_url: draftUrl,
        ...videoConfig
      })
    });

    const result = await response.json();
    if (result.status !== 'success') {
      throw new Error(`添加视频失败: ${result.message}`);
    }

    console.log('✅ 视频批量添加成功');
    return {
      draft_url: result.data.draft_url,
      track_id: result.data.track_id,
      video_ids: result.data.video_ids,
      segment_ids: result.data.segment_ids,
      videos_count: result.data.videos_count,
      total_duration: result.data.total_duration
    };
  }

  // 完整工作流程
  async createVideoProject(config) {
    try {
      console.log('🚀 开始创建视频项目...');

      // 第1步: 创建草稿
      const draftUrl = await this.createDraft(
        config.width,
        config.height,
        config.userId
      );

      // 第2步: 添加素材
      const finalDraftUrl = await this.addMaterials(draftUrl, config.materials);

      console.log('🎉 视频项目创建完成!');
      console.log('📄 草稿URL:', finalDraftUrl);

      return {
        success: true,
        draftUrl: finalDraftUrl,
        message: '视频项目创建成功'
      };

    } catch (error) {
      console.error('❌ 创建失败:', error.message);
      return {
        success: false,
        error: error.message
      };
    }
  }
}

// 使用示例
const videoCreator = new VideoCreator();

const projectConfig = {
  width: 1080,
  height: 1920,
  userId: 12345,
  materials: {
    text: "我的第一个视频",
    audio_url: "https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/artist/image/24631f7d1dd449e594097b6586b7d1b0.mp3",
    img_url: "https://s.coze.cn/t/JTa5Ne6_liY/",
    text_color: "#ffffff",
    font_size: 22,
    text_transform_y: 100
  }
};

// 执行完整工作流程
videoCreator.createVideoProject(projectConfig).then(result => {
  if (result.success) {
    console.log('项目创建成功,可以在剪映中打开:', result.draftUrl);
  } else {
    console.log('项目创建失败:', result.error);
  }
});

Bash 脚本工作流程

#!/bin/bash

# 配置
API_BASE="https://jy-api.fyshark.com"
AUDIO_URL="https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/artist/image/24631f7d1dd449e594097b6586b7d1b0.mp3"
IMG_URL="https://s.coze.cn/t/JTa5Ne6_liY/"

echo "🚀 开始创建视频项目..."

# 步骤1: 创建草稿
echo "📝 创建草稿中..."
DRAFT_RESPONSE=$(curl -s -X POST $API_BASE/api/drafts/create_draft \
  -H "Content-Type: application/json" \
  -d '{"width": 1080, "height": 1920, "user_id": 12345}')

# 提取草稿URL
DRAFT_URL=$(echo $DRAFT_RESPONSE | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['draft_url'])")

if [ -z "$DRAFT_URL" ]; then
    echo "❌ 创建草稿失败"
    exit 1
fi

echo "✅ 草稿创建成功: $DRAFT_URL"

# 步骤2: 添加素材
echo "🎬 添加素材中..."
MATERIAL_RESPONSE=$(curl -s -X POST $API_BASE/api/drafts/easy_create_material \
  -H "Content-Type: application/json" \
  -d "{
    \"text\": \"Bash脚本创建的视频\",
    \"audio_url\": \"$AUDIO_URL\",
    \"img_url\": \"$IMG_URL\",
    \"draft_url\": \"$DRAFT_URL\",
    \"text_color\": \"#00ff00\",
    \"font_size\": 20
  }")

# 检查结果
STATUS=$(echo $MATERIAL_RESPONSE | python3 -c "import sys, json; print(json.load(sys.stdin)['status'])")

if [ "$STATUS" = "success" ]; then
    echo "🎉 视频项目创建完成!"
    echo "📄 最终草稿URL: $DRAFT_URL"
else
    echo "❌ 添加素材失败"
    echo $MATERIAL_RESPONSE
    exit 1
fi

4. 错误处理

常见错误类型

1. 参数验证错误 (400)

{
  "status": "error",
  "message": "draft_url是必填项"
}

解决方案: 检查请求参数是否完整和正确

2. 资源访问错误 (400)

{
  "status": "error",
  "message": "音频链接无效或无法获取音频时长",
  "draft_url": "原始草稿URL"
}

解决方案:

3. 草稿处理错误 (500)

{
  "status": "error",
  "message": "草稿处理失败: 具体错误信息",
  "draft_url": "原始草稿URL"
}

解决方案:

错误处理最佳实践

const handleApiCall = async (apiCall) => {
  try {
    const result = await apiCall();
    return { success: true, data: result };
  } catch (error) {
    console.error('API调用失败:', error);
    
    // 根据错误类型进行不同处理
    if (error.message.includes('音频链接')) {
      return { 
        success: false, 
        error: '音频文件问题,请检查URL或文件格式',
        type: 'audio_error'
      };
    } else if (error.message.includes('草稿处理')) {
      return { 
        success: false, 
        error: '草稿处理失败,请重试或检查草稿URL',
        type: 'draft_error'
      };
    } else {
      return { 
        success: false, 
        error: error.message,
        type: 'unknown_error'
      };
    }
  }
};

5. 最佳实践

5.1 参数优化建议

画布尺寸选择

const canvasSizes = {
  vertical: { width: 1080, height: 1920 },    // 竖屏 (9:16)
  horizontal: { width: 1920, height: 1080 },  // 横屏 (16:9)
  square: { width: 1080, height: 1080 },      // 方形 (1:1)
  instagram: { width: 1080, height: 1350 }    // Instagram (4:5)
};

文字样式建议

const textStyles = {
  title: { font_size: 28, text_color: "#ffffff" },
  subtitle: { font_size: 20, text_color: "#cccccc" },
  body: { font_size: 16, text_color: "#ffffff" },
  caption: { font_size: 14, text_color: "#999999" }
};

5.2 性能优化

1. 音频预处理

// 在添加素材前验证音频
const validateAudio = async (audioUrl) => {
  try {
    const response = await fetch(audioUrl, { method: 'HEAD' });
    return response.ok && response.headers.get('content-type')?.includes('audio');
  } catch {
    return false;
  }
};

2. 批量处理

// 如果需要创建多个项目,建议复用草稿
const batchCreateProjects = async (projects) => {
  const results = [];
  
  for (const project of projects) {
    try {
      // 每个项目创建独立草稿
      const result = await videoCreator.createVideoProject(project);
      results.push(result);
      
      // 避免请求过于频繁
      await new Promise(resolve => setTimeout(resolve, 1000));
    } catch (error) {
      results.push({ success: false, error: error.message });
    }
  }
  
  return results;
};

5.3 安全考虑

URL 验证

const isValidUrl = (url) => {
  try {
    const urlObj = new URL(url);
    return ['http:', 'https:'].includes(urlObj.protocol);
  } catch {
    return false;
  }
};

// 使用前验证所有URL
const validateUrls = (materials) => {
  const urlFields = ['audio_url', 'img_url', 'video_url'];
  
  for (const field of urlFields) {
    if (materials[field] && !isValidUrl(materials[field])) {
      throw new Error(`无效的${field}: ${materials[field]}`);
    }
  }
};

5.4 监控和日志

const createWithLogging = async (config) => {
  const startTime = Date.now();
  
  try {
    console.log('开始创建项目:', {
      timestamp: new Date().toISOString(),
      config: config
    });
    
    const result = await videoCreator.createVideoProject(config);
    
    console.log('项目创建完成:', {
      duration: Date.now() - startTime,
      success: result.success,
      draftUrl: result.draftUrl
    });
    
    return result;
  } catch (error) {
    console.error('项目创建失败:', {
      duration: Date.now() - startTime,
      error: error.message,
      config: config
    });
    throw error;
  }
};

📞 技术支持

接口状态检查

# 健康检查
curl https://jy-api.fyshark.com/health

# 服务信息
curl https://jy-api.fyshark.com/

调试模式

如果遇到问题,可以查看服务器日志获取详细错误信息。

联系方式


📈 版本历史


🎉 恭喜!你现在已经掌握了JY API的完整使用方法。开始创建你的第一个视频项目吧!