DEV Community

Hommy
Hommy

Posted on

[JCAIGC]Submit video generation task

gen_video API Documentation

πŸ“‹ Table of Contents

πŸ”§ API Overview

API Name: gen_video

API Endpoint: POST /openapi/capcut-mate/v1/gen_video

Function Description: Submit video generation task. This interface adopts asynchronous processing mode, immediately returns task ID, and video generation proceeds in the background. Supports task queuing to ensure system stability.

More Documentation

πŸ“– For more detailed documentation and tutorials, please visit: https://docs.jcaigc.cn

Request Parameters

Request Body (application/json)

Parameter Type Required Default Description
draft_url string Yes - Draft URL, format like: https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258

Request Example

{
  "draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}
Enter fullscreen mode Exit fullscreen mode

Response Format

Success Response

{
  "message": "Video generation task has been submitted, please use draft_url to check progress"
}
Enter fullscreen mode Exit fullscreen mode

Response Field Description

Field Type Description
message string Response message

Error Response

400 Bad Request - Parameter Validation Failed

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request parameter validation failed",
    "details": "draft_url parameter cannot be empty"
  }
}
Enter fullscreen mode Exit fullscreen mode

404 Not Found - Draft Does Not Exist

{
  "error": {
    "code": "INVALID_DRAFT_URL",
    "message": "Invalid draft URL",
    "details": "Cannot parse draft ID or draft does not exist"
  }
}
Enter fullscreen mode Exit fullscreen mode

500 Internal Server Error - Task Submission Failed

{
  "error": {
    "code": "VIDEO_GENERATION_SUBMIT_FAILED",
    "message": "Video generation task submission failed",
    "details": "System internal error"
  }
}
Enter fullscreen mode Exit fullscreen mode

Usage Examples

cURL Example

1. Basic Video Generation

curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/gen_video \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
  }'
Enter fullscreen mode Exit fullscreen mode

2. Request with Timeout Setting

curl -X POST https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/gen_video \
  -H "Content-Type: application/json" \
  -d '{
    "draft_url": "YOUR_DRAFT_URL"
  }' \
  --max-time 300
Enter fullscreen mode Exit fullscreen mode

JavaScript Example

const generateVideo = async (draftUrl) => {
  const response = await fetch('/openapi/capcut-mate/v1/gen_video', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ draft_url: draftUrl })
  });
  return response.json();
};

// Basic usage
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";
const result = await generateVideo(draftUrl);

if (result.video_url) {
  console.log('Video generated successfully:', result.video_url);

  // Create download link
  const downloadLink = document.createElement('a');
  downloadLink.href = result.video_url;
  downloadLink.download = 'generated_video.mp4';
  downloadLink.click();
} else {
  console.error('Video generation failed:', result.message);
}
Enter fullscreen mode Exit fullscreen mode

Advanced JavaScript Example

class VideoGenerator {
  constructor(baseUrl = 'https://capcut-mate.jcaigc.cn') {
    this.baseUrl = baseUrl;
  }

  async generateVideo(draftUrl, options = {}) {
    const {
      timeout = 300000, // 5 minutes timeout
      onProgress = null
    } = options;

    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);

    try {
      const response = await fetch(`${this.baseUrl}/openapi/capcut-mate/v1/gen_video`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ draft_url: draftUrl }),
        signal: controller.signal
      });

      clearTimeout(timeoutId);

      if (!response.ok) {
        throw new Error(`Video generation failed: ${response.statusText}`);
      }

      return response.json();
    } catch (error) {
      clearTimeout(timeoutId);
      if (error.name === 'AbortError') {
        throw new Error('Video generation timeout');
      }
      throw error;
    }
  }

  // Polling-based video generation (suitable for long processing)
  async generateVideoWithPolling(draftUrl, options = {}) {
    const {
      pollInterval = 5000, // 5 seconds polling interval
      maxAttempts = 60, // Maximum attempts (5 minutes)
      onProgress = null
    } = options;

    // Start generation request
    let attempt = 0;

    while (attempt < maxAttempts) {
      try {
        const result = await this.generateVideo(draftUrl, { timeout: 30000 });

        if (result.video_url) {
          if (onProgress) onProgress({ status: 'completed', result });
          return result;
        }

        if (onProgress) {
          onProgress({ 
            status: 'processing', 
            attempt: attempt + 1, 
            maxAttempts,
            message: result.message 
          });
        }

        // Wait for next poll
        await new Promise(resolve => setTimeout(resolve, pollInterval));
        attempt++;

      } catch (error) {
        if (error.message.includes('timeout')) {
          // Timeout doesn't count as failure, continue polling
          if (onProgress) {
            onProgress({ 
              status: 'processing', 
              attempt: attempt + 1, 
              maxAttempts,
              message: 'Processing...' 
            });
          }
          await new Promise(resolve => setTimeout(resolve, pollInterval));
          attempt++;
        } else {
          throw error;
        }
      }
    }

    throw new Error('Video generation timeout, please try again later');
  }

  // Batch video generation
  async generateBatchVideos(draftUrls, options = {}) {
    const {
      concurrent = 2, // Concurrent count
      onProgress = null
    } = options;

    const results = {};
    const entries = Object.entries(draftUrls);

    // Batch processing
    for (let i = 0; i < entries.length; i += concurrent) {
      const batch = entries.slice(i, i + concurrent);

      const batchPromises = batch.map(async ([name, url]) => {
        try {
          if (onProgress) {
            onProgress({ name, status: 'starting', url });
          }

          const result = await this.generateVideoWithPolling(url, {
            onProgress: (progress) => {
              if (onProgress) {
                onProgress({ name, ...progress, url });
              }
            }
          });

          results[name] = result;

          if (onProgress) {
            onProgress({ name, status: 'completed', result, url });
          }

        } catch (error) {
          console.error(`Video generation failed ${name}:`, error);
          results[name] = { error: error.message };

          if (onProgress) {
            onProgress({ name, status: 'failed', error: error.message, url });
          }
        }
      });

      await Promise.all(batchPromises);

      // Add delay between batches
      if (i + concurrent < entries.length) {
        await new Promise(resolve => setTimeout(resolve, 1000));
      }
    }

    return results;
  }

  // Download generated video
  async downloadVideo(videoUrl, filename = 'generated_video.mp4') {
    try {
      const response = await fetch(videoUrl);
      const blob = await response.blob();

      const downloadUrl = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = downloadUrl;
      link.download = filename;

      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);

      window.URL.revokeObjectURL(downloadUrl);

      return true;
    } catch (error) {
      console.error('Download video failed:', error);
      return false;
    }
  }
}

// Usage example
const videoGenerator = new VideoGenerator();

// Single video generation
const draftUrl = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258";

try {
  const result = await videoGenerator.generateVideoWithPolling(draftUrl, {
    onProgress: (progress) => {
      console.log(`Generation progress: ${progress.status}`, progress);

      if (progress.status === 'processing') {
        console.log(`Processing... (${progress.attempt}/${progress.maxAttempts})`);
      }
    }
  });

  console.log('Video generated successfully:', result.video_url);

  // Download video
  await videoGenerator.downloadVideo(result.video_url, 'my_video.mp4');

} catch (error) {
  console.error('Generation failed:', error);
}

// Batch generate videos
const multipleDrafts = {
  "video1": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
  "video2": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
  "video3": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
};

const batchResults = await videoGenerator.generateBatchVideos(multipleDrafts, {
  concurrent: 2,
  onProgress: (progress) => {
    console.log(`${progress.name}: ${progress.status}`);
  }
});

// Download all successful videos
for (const [name, result] of Object.entries(batchResults)) {
  if (result.video_url && !result.error) {
    await videoGenerator.downloadVideo(result.video_url, `${name}.mp4`);
  }
}
Enter fullscreen mode Exit fullscreen mode

Python Example

import requests
import time
import asyncio
import aiohttp
from typing import Dict, Optional, Callable

class VideoGenerator:
    def __init__(self, base_url: str = "https://api.assets.jcaigc.cn"):
        self.base_url = base_url

    def generate_video(self, draft_url: str, timeout: int = 300) -> Dict:
        """Generate video"""
        response = requests.post(
            f'{self.base_url}/openapi/capcut-mate/v1/gen_video',
            headers={'Content-Type': 'application/json'},
            json={"draft_url": draft_url},
            timeout=timeout
        )
        response.raise_for_status()
        return response.json()

    def generate_video_with_polling(self, draft_url: str, 
                                  poll_interval: int = 5, 
                                  max_attempts: int = 60,
                                  on_progress: Optional[Callable] = None) -> Dict:
        """Polling-based video generation"""
        attempt = 0

        while attempt < max_attempts:
            try:
                result = self.generate_video(draft_url, timeout=30)

                if result.get('video_url'):
                    if on_progress:
                        on_progress({'status': 'completed', 'result': result})
                    return result

                if on_progress:
                    on_progress({
                        'status': 'processing',
                        'attempt': attempt + 1,
                        'max_attempts': max_attempts,
                        'message': result.get('message', 'Processing...')
                    })

                time.sleep(poll_interval)
                attempt += 1

            except requests.exceptions.Timeout:
                if on_progress:
                    on_progress({
                        'status': 'processing',
                        'attempt': attempt + 1,
                        'max_attempts': max_attempts,
                        'message': 'Processing...'
                    })
                time.sleep(poll_interval)
                attempt += 1
            except Exception as e:
                raise e

        raise Exception('Video generation timeout, please try again later')

    def generate_batch_videos(self, draft_urls: Dict[str, str], 
                            concurrent: int = 2,
                            on_progress: Optional[Callable] = None) -> Dict:
        """Batch video generation"""
        results = {}
        entries = list(draft_urls.items())

        # Batch processing
        for i in range(0, len(entries), concurrent):
            batch = entries[i:i + concurrent]
            batch_results = {}

            for name, url in batch:
                try:
                    if on_progress:
                        on_progress({'name': name, 'status': 'starting', 'url': url})

                    def progress_callback(progress):
                        if on_progress:
                            on_progress({'name': name, **progress, 'url': url})

                    result = self.generate_video_with_polling(
                        url, 
                        on_progress=progress_callback
                    )

                    batch_results[name] = result

                    if on_progress:
                        on_progress({'name': name, 'status': 'completed', 'result': result, 'url': url})

                except Exception as e:
                    print(f"Video generation failed {name}: {e}")
                    batch_results[name] = {'error': str(e)}

                    if on_progress:
                        on_progress({'name': name, 'status': 'failed', 'error': str(e), 'url': url})

            results.update(batch_results)

            # Delay between batches
            if i + concurrent < len(entries):
                time.sleep(1)

        return results

    def download_video(self, video_url: str, filename: str = "generated_video.mp4") -> bool:
        """Download video"""
        try:
            response = requests.get(video_url, stream=True)
            response.raise_for_status()

            with open(filename, 'wb') as f:
                for chunk in response.iter_content(chunk_size=8192):
                    f.write(chunk)

            print(f"Video downloaded to: {filename}")
            return True

        except Exception as e:
            print(f"Download video failed: {e}")
            return False

# Usage example
generator = VideoGenerator()

# Single video generation
draft_url = "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"

def on_progress(progress):
    print(f"Generation progress: {progress['status']}")
    if progress['status'] == 'processing':
        print(f"Processing... ({progress['attempt']}/{progress['max_attempts']})")

try:
    result = generator.generate_video_with_polling(
        draft_url, 
        on_progress=on_progress
    )

    print(f"Video generated successfully: {result['video_url']}")

    # Download video
    generator.download_video(result['video_url'], 'my_video.mp4')

except Exception as e:
    print(f"Generation failed: {e}")

# Batch generation
multiple_drafts = {
    "video1": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258",
    "video2": "https://capcut-mate.jcaigc.cn/openapi/capcut-mate/v1/get_draft?draft_id=2025092811473036584258"
}

def batch_progress(progress):
    print(f"{progress['name']}: {progress['status']}")

batch_results = generator.generate_batch_videos(
    multiple_drafts,
    concurrent=2,
    on_progress=batch_progress
)

# Download all successful videos
for name, result in batch_results.items():
    if 'video_url' in result and 'error' not in result:
        generator.download_video(result['video_url'], f'{name}.mp4')
Enter fullscreen mode Exit fullscreen mode

Error Code Description

Error Code Error Message Description Solution
400 draft_url is required Missing draft_url parameter Provide valid draft_url
400 draft_url format is invalid URL format is incorrect Check if URL format is correct
404 Draft does not exist Specified draft cannot be found Confirm if draft URL is correct and exists
400 Draft content is empty No exportable content in draft Ensure draft contains video, audio, or image materials
400 Material cannot be accessed Material files in draft cannot be downloaded Check if material URLs are valid
500 Video rendering failed Error occurred during video processing Check draft content or contact technical support
500 Audio processing failed Error occurred during audio mixing Check audio format or contact technical support
500 Encoding failed Final video encoding failed Contact technical support
503 Service busy Rendering server load is too high Retry later
504 Processing timeout Video generation timeout Simplify draft content or retry later

Notes

  1. Processing Time: Video generation is a time-consuming operation, may take several minutes to tens of minutes
  2. File Size: Draft complexity and material quantity will affect processing time
  3. Network Stability: Ensure material URLs can be stably accessed
  4. Timeout Setting: It is recommended to set longer timeout times or use polling mechanism
  5. Concurrency Limit: Avoid generating large numbers of videos simultaneously
  6. Storage Space: Generated video files may be large, pay attention to storage space
  7. URL Validity: Generated video_url may have time limitations

Workflow

  1. Validate draft_url parameter
  2. Parse draft configuration file
  3. Download all required material files
  4. Arrange and process materials by timeline
  5. Apply visual effects and transitions
  6. Mix audio tracks
  7. Render final video
  8. Encode and upload video file
  9. Return video URL

Best Practices

  1. Polling Check: For long processing, use polling mechanism
  2. Error Retry: Implement automatic retry mechanism
  3. Progress Feedback: Show processing progress to users
  4. Batch Processing: Reasonably control concurrent quantity
  5. Resource Cleanup: Clean up temporary files in time
  6. Quality Control: Verify completeness of draft content before generation

Related Interfaces


πŸ“š Project Resources

GitHub: https://github.com/Hommy-master/capcut-mate

Gitee: https://gitee.com/taohongmin-gitee/capcut-mate

Top comments (0)