gen_video API Documentation
π Table of Contents
- π§ API Overview
- π― Function Description
- π₯ Request Parameters
- π€ Response Format
- π» Usage Examples
- β Error Code Description
- β οΈ Notes
- π Workflow
- β‘οΈ Next Steps
- π Related Interfaces
π§ 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"
}
Response Format
Success Response
{
"message": "Video generation task has been submitted, please use draft_url to check progress"
}
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"
}
}
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"
}
}
500 Internal Server Error - Task Submission Failed
{
"error": {
"code": "VIDEO_GENERATION_SUBMIT_FAILED",
"message": "Video generation task submission failed",
"details": "System internal error"
}
}
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"
}'
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
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);
}
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`);
}
}
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')
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
- Processing Time: Video generation is a time-consuming operation, may take several minutes to tens of minutes
- File Size: Draft complexity and material quantity will affect processing time
- Network Stability: Ensure material URLs can be stably accessed
- Timeout Setting: It is recommended to set longer timeout times or use polling mechanism
- Concurrency Limit: Avoid generating large numbers of videos simultaneously
- Storage Space: Generated video files may be large, pay attention to storage space
- URL Validity: Generated video_url may have time limitations
Workflow
- Validate draft_url parameter
- Parse draft configuration file
- Download all required material files
- Arrange and process materials by timeline
- Apply visual effects and transitions
- Mix audio tracks
- Render final video
- Encode and upload video file
- Return video URL
Best Practices
- Polling Check: For long processing, use polling mechanism
- Error Retry: Implement automatic retry mechanism
- Progress Feedback: Show processing progress to users
- Batch Processing: Reasonably control concurrent quantity
- Resource Cleanup: Clean up temporary files in time
- 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)