Files
ALwrity/backend/routers/video_studio/endpoints/create.py
ajaysi b134e9dc7e Added video studio router and endpoints. Added research router and endpoints. Added youtube router and endpoints. Added onboarding utils router and endpoints. Added onboarding utils service. Added onboarding utils models. Added onboarding utils routes. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils. Added onboarding utils utils.
2026-01-01 17:56:25 +05:30

305 lines
12 KiB
Python

"""
Create video endpoints: text-to-video and image-to-video generation.
"""
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, BackgroundTasks
from sqlalchemy.orm import Session
from typing import Optional, Dict, Any
import uuid
from ...database import get_db
from ...models.content_asset_models import AssetSource, AssetType
from ...services.video_studio import VideoStudioService
from ...services.asset_service import ContentAssetService
from ...utils.auth import get_current_user, require_authenticated_user
from ...utils.logger_utils import get_service_logger
from api.story_writer.task_manager import task_manager
from ..tasks.video_generation import execute_video_generation_task
logger = get_service_logger("video_studio.endpoints.create")
router = APIRouter()
@router.post("/generate")
async def generate_video(
background_tasks: BackgroundTasks,
prompt: str = Form(..., description="Text description for video generation"),
negative_prompt: Optional[str] = Form(None, description="What to avoid in the video"),
duration: int = Form(5, description="Video duration in seconds", ge=1, le=10),
resolution: str = Form("720p", description="Video resolution"),
aspect_ratio: str = Form("16:9", description="Video aspect ratio"),
motion_preset: str = Form("medium", description="Motion intensity"),
provider: str = Form("wavespeed", description="AI provider to use"),
model: str = Form("hunyuan-video-1.5", description="Specific AI model to use"),
current_user: Dict[str, Any] = Depends(get_current_user),
db: Session = Depends(get_db),
) -> Dict[str, Any]:
"""
Generate video from text description using AI models.
Supports multiple providers and models for optimal quality and cost.
"""
try:
user_id = require_authenticated_user(current_user)
# Initialize services
video_service = VideoStudioService()
asset_service = ContentAssetService(db)
logger.info(f"[VideoStudio] Text-to-video request: user={user_id}, model={model}, duration={duration}s")
# Generate video
result = await video_service.generate_text_to_video(
prompt=prompt,
negative_prompt=negative_prompt,
duration=duration,
resolution=resolution,
aspect_ratio=aspect_ratio,
motion_preset=motion_preset,
provider=provider,
model=model,
user_id=user_id,
)
if not result.get("success"):
raise HTTPException(
status_code=500,
detail=f"Video generation failed: {result.get('error', 'Unknown error')}"
)
# Store in asset library if successful
video_url = result.get("video_url")
if video_url:
asset_metadata = {
"prompt": prompt,
"negative_prompt": negative_prompt,
"duration": duration,
"resolution": resolution,
"aspect_ratio": aspect_ratio,
"motion_preset": motion_preset,
"provider": provider,
"model": model,
"generation_type": "text-to-video",
}
asset_service.create_asset(
user_id=user_id,
filename=f"video_{uuid.uuid4().hex[:8]}.mp4",
file_url=video_url,
asset_type=AssetType.VIDEO,
source_module=AssetSource.VIDEO_STUDIO,
asset_metadata=asset_metadata,
cost=result.get("cost", 0),
tags=["video_studio", "text-to-video", "ai-generated"]
)
logger.info(f"[VideoStudio] Video generated successfully: user={user_id}, url={video_url}")
return {
"success": True,
"video_url": video_url,
"cost": result.get("cost", 0),
"estimated_duration": result.get("estimated_duration", duration),
"model_used": model,
"provider": provider,
}
except HTTPException:
raise
except Exception as e:
logger.error(f"[VideoStudio] Text-to-video error: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Video generation failed: {str(e)}")
@router.post("/transform")
async def transform_to_video(
background_tasks: BackgroundTasks,
file: UploadFile = File(..., description="Image file to transform"),
prompt: Optional[str] = Form(None, description="Optional text prompt to guide transformation"),
duration: int = Form(5, description="Video duration in seconds", ge=1, le=10),
resolution: str = Form("720p", description="Video resolution"),
aspect_ratio: str = Form("16:9", description="Video aspect ratio"),
motion_preset: str = Form("medium", description="Motion intensity"),
provider: str = Form("wavespeed", description="AI provider to use"),
model: str = Form("alibaba/wan-2.5", description="Specific AI model to use"),
current_user: Dict[str, Any] = Depends(get_current_user),
db: Session = Depends(get_db),
) -> Dict[str, Any]:
"""
Transform image to video using AI models.
Supports various motion presets and durations for dynamic video creation.
"""
try:
user_id = require_authenticated_user(current_user)
# Validate file type
if not file.content_type.startswith('image/'):
raise HTTPException(status_code=400, detail="File must be an image")
# Initialize services
video_service = VideoStudioService()
asset_service = ContentAssetService(db)
logger.info(f"[VideoStudio] Image-to-video request: user={user_id}, model={model}, duration={duration}s")
# Read image file
image_data = await file.read()
# Generate video
result = await video_service.generate_image_to_video(
image_data=image_data,
prompt=prompt,
duration=duration,
resolution=resolution,
aspect_ratio=aspect_ratio,
motion_preset=motion_preset,
provider=provider,
model=model,
user_id=user_id,
)
if not result.get("success"):
raise HTTPException(
status_code=500,
detail=f"Video transformation failed: {result.get('error', 'Unknown error')}"
)
# Store in asset library if successful
video_url = result.get("video_url")
if video_url:
asset_metadata = {
"original_image": file.filename,
"prompt": prompt,
"duration": duration,
"resolution": resolution,
"aspect_ratio": aspect_ratio,
"motion_preset": motion_preset,
"provider": provider,
"model": model,
"generation_type": "image-to-video",
}
asset_service.create_asset(
user_id=user_id,
filename=f"video_{uuid.uuid4().hex[:8]}.mp4",
file_url=video_url,
asset_type=AssetType.VIDEO,
source_module=AssetSource.VIDEO_STUDIO,
asset_metadata=asset_metadata,
cost=result.get("cost", 0),
tags=["video_studio", "image-to-video", "ai-generated"]
)
logger.info(f"[VideoStudio] Video transformation successful: user={user_id}, url={video_url}")
return {
"success": True,
"video_url": video_url,
"cost": result.get("cost", 0),
"estimated_duration": result.get("estimated_duration", duration),
"model_used": model,
"provider": provider,
}
except HTTPException:
raise
except Exception as e:
logger.error(f"[VideoStudio] Image-to-video error: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Video transformation failed: {str(e)}")
@router.post("/generate-async")
async def generate_video_async(
background_tasks: BackgroundTasks,
prompt: Optional[str] = Form(None, description="Text description for video generation"),
image: Optional[UploadFile] = File(None, description="Image file for image-to-video"),
operation_type: str = Form("text-to-video", description="Operation type: text-to-video or image-to-video"),
negative_prompt: Optional[str] = Form(None, description="What to avoid in the video"),
duration: int = Form(5, description="Video duration in seconds", ge=1, le=10),
resolution: str = Form("720p", description="Video resolution"),
aspect_ratio: str = Form("16:9", description="Video aspect ratio"),
motion_preset: str = Form("medium", description="Motion intensity"),
provider: str = Form("wavespeed", description="AI provider to use"),
model: str = Form("alibaba/wan-2.5", description="Specific AI model to use"),
current_user: Dict[str, Any] = Depends(get_current_user),
) -> Dict[str, Any]:
"""
Generate video asynchronously with polling support.
Returns task_id for polling. Frontend can poll /api/video-studio/task/{task_id}/status
to get progress updates and final result.
"""
try:
user_id = require_authenticated_user(current_user)
# Validate operation type
if operation_type not in ["text-to-video", "image-to-video"]:
raise HTTPException(
status_code=400,
detail=f"Invalid operation_type: {operation_type}. Must be 'text-to-video' or 'image-to-video'"
)
# Validate inputs based on operation type
if operation_type == "text-to-video" and not prompt:
raise HTTPException(
status_code=400,
detail="prompt is required for text-to-video generation"
)
if operation_type == "image-to-video" and not image:
raise HTTPException(
status_code=400,
detail="image file is required for image-to-video generation"
)
# Read image data if provided
image_data = None
if image:
image_data = await image.read()
if len(image_data) == 0:
raise HTTPException(status_code=400, detail="Image file is empty")
# Create task
task_id = task_manager.create_task("video_generation")
# Prepare kwargs
kwargs = {
"duration": duration,
"resolution": resolution,
"model": model,
}
if negative_prompt:
kwargs["negative_prompt"] = negative_prompt
if aspect_ratio:
kwargs["aspect_ratio"] = aspect_ratio
if motion_preset:
kwargs["motion_preset"] = motion_preset
# Start background task
background_tasks.add_task(
execute_video_generation_task,
task_id=task_id,
operation_type=operation_type,
user_id=user_id,
prompt=prompt,
image_data=image_data,
provider=provider,
**kwargs
)
logger.info(f"[VideoStudio] Started async video generation: task_id={task_id}, operation={operation_type}, user={user_id}")
return {
"task_id": task_id,
"status": "pending",
"message": f"Video generation started. This may take several minutes. Poll /api/video-studio/task/{task_id}/status for updates."
}
except HTTPException:
raise
except Exception as e:
logger.error(f"[VideoStudio] Failed to start async video generation: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Failed to start video generation: {str(e)}")