ADD_IMAGES API 接口文档

📄 API_ADD_IMAGES.md 🕒 8/10/2025, 6:48:25 PM 📏 14KB

ADD_IMAGES API 接口文档

接口信息

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轴位置偏移(像素)

image_infos 数组元素说明

参数名 类型 必填 默认值 说明
image_url string - 图片文件URL
width number - 图片宽度(像素)
height number - 图片高度(像素)
start number - 显示开始时间(微秒)
end number - 显示结束时间(微秒)
in_animation string - 入场动画类型
out_animation string - 出场动画类型
loop_animation string - 循环动画类型
in_animation_duration number - 入场动画时长(微秒)
out_animation_duration number - 出场动画时长(微秒)
loop_animation_duration number - 循环动画时长(微秒)
transition string - 转场效果类型
transition_duration number 500000 转场效果时长(微秒,范围100000-2500000)

常见动画类型

动画类别 动画名称示例
入场动画 "淡入", "飞入", "缩放进入", "旋转进入"
出场动画 "淡出", "飞出", "缩放退出", "旋转退出"
循环动画 "呼吸", "摆动", "闪烁", "浮动"
转场效果 "淡入淡出", "推拉门", "马赛克", "百叶窗"

响应格式

成功响应 (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
      },
      {
        "id": "seg_002", 
        "start": 1000000,
        "end": 2000000
      }
    ]
  }
}

错误响应 (4xx/5xx)

{
  "status": "error",
  "message": "错误信息",
  "error": "详细错误描述"
}

使用示例

cURL 示例

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/image.jpg\",\"width\":800,\"height\":600,\"start\":0,\"end\":2000000}]",
    "alpha": 0.7,
    "scale_x": 1.2,
    "scale_y": 1.2
  }'

3. 带动画效果的图片

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/image.jpg\",\"width\":1024,\"height\":1024,\"start\":0,\"end\":3000000,\"in_animation\":\"淡入\",\"out_animation\":\"淡出\",\"in_animation_duration\":500000,\"out_animation_duration\":500000}]"
  }'

4. 多图片带转场效果

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\":1024,\"height\":1024,\"start\":0,\"end\":2000000,\"transition\":\"淡入淡出\",\"transition_duration\":1000000},{\"image_url\":\"https://example.com/image2.jpg\",\"width\":1024,\"height\":1024,\"start\":2000000,\"end\":4000000}]"
  }'

JavaScript 示例

const addImages = async (imagesData, draftUrl, options = {}) => {
  const response = await fetch('/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: 2000000,
    end: 4000000,
    out_animation: "淡出",
    out_animation_duration: 500000
  }
];

const options = {
  alpha: 0.8,
  scale_x: 1.1,
  scale_y: 1.1,
  transform_y: 50
};

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

高级JavaScript示例

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

  async addImages(config) {
    const {
      draftUrl,
      images,
      globalOptions = {}
    } = config;

    const payload = {
      draft_url: draftUrl,
      image_infos: JSON.stringify(images),
      alpha: globalOptions.alpha || 1.0,
      scale_x: globalOptions.scaleX || 1.0,
      scale_y: globalOptions.scaleY || 1.0,
      transform_x: globalOptions.transformX || 0,
      transform_y: globalOptions.transformY || 0
    };

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

    return response.json();
  }

  // 便捷方法:创建图片幻灯片
  async createSlideshow(draftUrl, imageUrls, slideDuration = 3000000) {
    const images = imageUrls.map((url, index) => ({
      image_url: url,
      width: 1024,
      height: 1024,
      start: index * slideDuration,
      end: (index + 1) * slideDuration,
      in_animation: "淡入",
      out_animation: "淡出",
      in_animation_duration: 500000,
      out_animation_duration: 500000,
      transition: index < imageUrls.length - 1 ? "淡入淡出" : null,
      transition_duration: 1000000
    }));

    return this.addImages({
      draftUrl,
      images,
      globalOptions: { alpha: 1.0 }
    });
  }

  // 便捷方法:创建图片蒙太奇
  async createMontage(draftUrl, imageUrls, totalDuration = 10000000) {
    const imageDuration = totalDuration / imageUrls.length;
    const overlapDuration = imageDuration * 0.1; // 10%重叠

    const images = imageUrls.map((url, index) => ({
      image_url: url,
      width: 1024,
      height: 1024,
      start: Math.max(0, index * imageDuration - overlapDuration),
      end: Math.min(totalDuration, (index + 1) * imageDuration),
      in_animation: "缩放进入",
      out_animation: "缩放退出",
      loop_animation: "呼吸",
      in_animation_duration: 300000,
      out_animation_duration: 300000,
      loop_animation_duration: 2000000
    }));

    return this.addImages({
      draftUrl,
      images,
      globalOptions: { 
        alpha: 0.8,
        scaleX: 1.1,
        scaleY: 1.1
      }
    });
  }
}

// 使用示例
const imageManager = new ImageManager();

// 创建幻灯片
await imageManager.createSlideshow(
  draftUrl,
  [
    "https://example.com/slide1.jpg",
    "https://example.com/slide2.jpg", 
    "https://example.com/slide3.jpg"
  ],
  5000000 // 每张图片显示5秒
);

// 创建蒙太奇
await imageManager.createMontage(
  draftUrl,
  [
    "https://example.com/montage1.jpg",
    "https://example.com/montage2.jpg",
    "https://example.com/montage3.jpg"
  ],
  15000000 // 总时长15秒
);

Python 示例 (可选)

import requests
import json

class ImageProcessor:
    def __init__(self, base_url="https://jy-api.fyshark.com"):
        self.base_url = base_url

    def add_images(self, draft_url, images, **options):
        data = {
            "draft_url": draft_url,
            "image_infos": json.dumps(images),
            **options
        }
        
        response = requests.post(
            f'{self.base_url}/api/drafts/add_images',
            headers={'Content-Type': 'application/json'},
            json=data
        )
        return response.json()

# 使用示例
processor = ImageProcessor()

images = [
    {
        "image_url": "https://example.com/image1.jpg",
        "width": 1024,
        "height": 1024,
        "start": 0,
        "end": 2000000,
        "in_animation": "淡入"
    }
]

result = processor.add_images(
    draft_url="YOUR_DRAFT_URL",
    images=images,
    alpha=0.8,
    scale_x=1.2
)

print(f"结果: {result}")

错误码说明

错误码 错误信息 说明 解决方案
400 draft_url是必填项 缺少草稿URL参数 提供有效的草稿URL
400 image_infos是必填项 缺少图片信息参数 提供图片信息数组
400 image_infos格式错误 JSON解析失败 检查JSON格式是否正确
400 图片信息验证失败 图片数据不符合要求 检查图片URL和尺寸信息
400 透明度参数无效 alpha不在0-1范围内 使用0-1之间的数值
400 时间范围无效 start >= end 确保start < end
404 草稿不存在 指定的草稿URL无效 检查草稿URL是否正确
404 图片文件不存在 图片URL无法访问 检查图片URL有效性
500 图片处理失败 内部处理错误 联系技术支持
500 动画创建失败 动画效果处理错误 检查动画参数设置

注意事项

  1. image_infos参数格式: 必须是JSON字符串格式,不是直接的数组对象
  2. 时间单位: 所有时间参数(start, end, duration等)都使用微秒为单位
  3. 图片尺寸: width和height必须与实际图片尺寸匹配,以确保正确显示
  4. 透明度范围: alpha参数范围为0-1,超出范围会被重置为1.0
  5. 转场时长限制: transition_duration必须在100000-2500000微秒之间
  6. 动画兼容性: 不同的动画类型可能有特定的参数要求
  7. 性能考虑: 大量图片或复杂动画可能影响渲染性能

工作流程

  1. 验证必填参数(draft_url, image_infos)
  2. 解析image_infos JSON字符串
  3. 验证图片信息格式和透明度参数
  4. 获取并解密草稿内容
  5. 创建新的视频轨道(用于图片)
  6. 遍历图片信息数组,逐个处理:
    • 创建图片素材(使用MATERIAL_TYPE.PHOTO)
    • 添加图片片段到轨道
    • 设置透明度、缩放和位置
    • 处理动画效果(入场、出场、循环)
    • 添加转场效果(如果指定)
  7. 加密并保存更新后的草稿
  8. 返回轨道ID和图片ID列表

技术特性

图片处理能力

动画系统

转场效果

最佳实践

图片规格建议

const imageGuidelines = {
  formats: ['jpg', 'jpeg', 'png', 'gif'],
  maxSize: '10MB',
  resolutions: {
    '16:9': { width: 1920, height: 1080 },
    '9:16': { width: 1080, height: 1920 },
    '1:1': { width: 1080, height: 1080 }
  },
  qualityTips: [
    '使用高质量图片以确保清晰度',
    '保持图片比例与画布匹配',
    '避免过大的文件影响处理速度'
  ]
};

动画效果建议

const animationBestPractices = {
  timing: {
    inAnimation: '300000-800000', // 0.3-0.8秒
    outAnimation: '300000-800000', // 0.3-0.8秒
    loopAnimation: '1000000-3000000', // 1-3秒
    transition: '500000-1500000' // 0.5-1.5秒
  },
  combinations: [
    { in: '淡入', out: '淡出', transition: '淡入淡出' },
    { in: '飞入', out: '飞出', transition: '推拉门' },
    { in: '缩放进入', out: '缩放退出', transition: '缩放' }
  ]
};

性能优化

const optimizationTips = {
  batchSize: '建议每次处理10-20张图片',
  imageSize: '单张图片建议不超过5MB',
  animationComplexity: '避免同时使用过多复杂动画',
  transitionUsage: '适度使用转场效果,避免过度',
  
  // 预处理图片
  preprocessImages: async (imageUrls) => {
    return imageUrls.map(url => ({
      url,
      // 可以在这里添加图片预检查逻辑
      valid: true
    }));
  }
};

错误处理策略

const addImagesWithFallback = async (config) => {
  try {
    return await addImages(config.images, config.draftUrl, config.options);
  } catch (error) {
    // 如果动画失败,重试不包含动画的版本
    if (error.message.includes('动画')) {
      const simpleImages = config.images.map(img => ({
        image_url: img.image_url,
        width: img.width,
        height: img.height,
        start: img.start,
        end: img.end
        // 移除动画相关属性
      }));
      
      return addImages(simpleImages, config.draftUrl, config.options);
    }
    throw error;
  }
};

高级用法

图片序列动画

const createImageSequence = (baseUrl, count, startTime, frameDuration) => {
  return Array.from({ length: count }, (_, i) => ({
    image_url: `${baseUrl}/frame_${i.toString().padStart(3, '0')}.jpg`,
    width: 1920,
    height: 1080,
    start: startTime + i * frameDuration,
    end: startTime + (i + 1) * frameDuration,
    transition: i < count - 1 ? '淡入淡出' : null,
    transition_duration: frameDuration * 0.1
  }));
};

// 创建60帧的图片序列动画
const sequence = createImageSequence(
  'https://example.com/sequence',
  60,
  0,
  33333 // 30fps
);

响应式图片布局

const createResponsiveLayout = (images, canvasWidth, canvasHeight) => {
  return images.map((img, index) => {
    const cols = Math.ceil(Math.sqrt(images.length));
    const rows = Math.ceil(images.length / cols);
    
    const cellWidth = canvasWidth / cols;
    const cellHeight = canvasHeight / rows;
    
    const col = index % cols;
    const row = Math.floor(index / cols);
    
    return {
      ...img,
      width: cellWidth * 0.9, // 留边距
      height: cellHeight * 0.9,
      start: index * 1000000, // 错开显示
      end: (index + 1) * 1000000 + 2000000 // 重叠显示
    };
  });
};

相关接口

更新日志


📖 文档版本: v1.0.0
🔄 最后更新: 2025-08-01
👤 维护者: Developer