video-shuoshan/backend/utils/seedance_client.py
zyc 566c3a476f
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m17s
add 存储桶
2026-03-13 15:38:08 +08:00

96 lines
2.7 KiB
Python

"""Volcano Engine Seedance (ARK) video generation API client."""
import requests
from django.conf import settings
MODEL_MAP = {
'seedance_2.0': 'doubao-seedance-2-0-260128',
'seedance_2.0_fast': 'doubao-seedance-2-0-fast-260128',
}
def _headers():
return {
'Content-Type': 'application/json',
'Authorization': f'Bearer {settings.ARK_API_KEY}',
}
def create_task(prompt, model, content_items, aspect_ratio, duration, generate_audio=True):
"""Create a video generation task.
Args:
prompt: Text prompt for video generation.
model: Model key ('seedance_2.0' or 'seedance_2.0_fast').
content_items: List of media content dicts (image_url, video_url, audio_url).
aspect_ratio: Video aspect ratio ('16:9', '9:16', etc.).
duration: Video duration in seconds.
generate_audio: Whether to generate audio with the video.
Returns:
dict: API response with task id and status.
"""
url = f'{settings.ARK_BASE_URL}/contents/generations/tasks'
content = []
if prompt:
content.append({'type': 'text', 'text': prompt})
content.extend(content_items)
payload = {
'model': MODEL_MAP.get(model, model),
'content': content,
'generate_audio': generate_audio,
'ratio': aspect_ratio,
'duration': duration,
'watermark': False,
}
resp = requests.post(url, json=payload, headers=_headers(), timeout=60)
resp.raise_for_status()
return resp.json()
def query_task(task_id):
"""Query a video generation task by its ARK task ID.
Returns:
dict: Task status, content (video URL on success), usage info.
"""
url = f'{settings.ARK_BASE_URL}/contents/generations/tasks/{task_id}'
resp = requests.get(url, headers=_headers(), timeout=30)
resp.raise_for_status()
return resp.json()
def extract_video_url(task_response):
"""Extract the video URL from a completed task response."""
content = task_response.get('content')
if not content:
return None
# content could be a list of items or a dict
if isinstance(content, list):
for item in content:
if item.get('type') == 'video_url':
return item.get('video_url', {}).get('url')
elif isinstance(content, dict):
if 'video_url' in content:
url = content['video_url']
return url.get('url') if isinstance(url, dict) else url
return None
def map_status(ark_status):
"""Map ARK task status to our DB status."""
mapping = {
'running': 'processing',
'submitted': 'queued',
'queued': 'queued',
'succeeded': 'completed',
'failed': 'failed',
}
return mapping.get(ark_status, 'processing')