Skip to content

video_api

OpenAI/vLLM-Omni-compatible video generation routes.

Classes

Functions:

fastvideo.entrypoints.openai.video_api.create_video async

create_video(raw_request: Request) -> VideoResponse

Create an asynchronous video generation job.

Source code in fastvideo/entrypoints/openai/video_api.py
@router.post("", response_model=VideoResponse)
@router.post("/generations", response_model=VideoResponse, include_in_schema=False)
async def create_video(raw_request: Request) -> VideoResponse:
    """Create an asynchronous video generation job."""
    request = await _parse_video_request(raw_request)
    request_id = f"video_gen_{generate_request_id()}"
    generation_request = await _adapt_request(request_id, request)
    job = _make_video_job(request_id, request, generation_request)
    await VIDEO_STORE.upsert(request_id, job)
    task = asyncio.create_task(_run_generation(request_id, generation_request), name=f"video-job-{request_id}")
    _track_video_job(request_id, task)
    return VideoResponse(**job)

fastvideo.entrypoints.openai.video_api.create_video_sync async

create_video_sync(raw_request: Request) -> FileResponse

Generate synchronously and return raw MP4 bytes with vLLM headers.

Source code in fastvideo/entrypoints/openai/video_api.py
@router.post("/sync")
async def create_video_sync(raw_request: Request) -> FileResponse:
    """Generate synchronously and return raw MP4 bytes with vLLM headers."""
    request = await _parse_video_request(raw_request)
    request_id = f"video_sync-{generate_request_id()}"
    generation_request = await _adapt_request(request_id, request)
    started = time.perf_counter()
    try:
        result = await get_serving_engine().generate(generation_request)
    except Exception as error:
        logger.exception("Sync video generation failed for %s", request_id)
        raise HTTPException(status_code=500, detail=f"Video generation failed: {error}") from error
    if isinstance(result, list):
        if not result:
            raise HTTPException(status_code=500, detail="FastVideo returned no generation results")
        result = result[0]
    elapsed = time.perf_counter() - started
    video_path = _result_value(result, "video_path") or generation_request.output.output_path
    if not video_path or not os.path.exists(video_path):
        raise HTTPException(status_code=500, detail="FastVideo did not produce an MP4 file")
    return FileResponse(
        video_path,
        media_type="video/mp4",
        filename=os.path.basename(video_path),
        headers={
            "X-Request-Id": request_id,
            "X-Model": get_served_model_name(),
            "X-Inference-Time-S": f"{elapsed:.3f}",
            "X-Stage-Durations": json.dumps(_stage_durations(result), separators=(",", ":")),
            "X-Peak-Memory-MB": f"{float(_result_value(result, 'peak_memory_mb', 0.0) or 0.0):.3f}",
        },
        background=BackgroundTask(_remove_artifact, video_path),
    )

fastvideo.entrypoints.openai.video_api.shutdown_video_jobs async

shutdown_video_jobs() -> None

Cancel all transport tasks before the serving engine shuts down.

Source code in fastvideo/entrypoints/openai/video_api.py
async def shutdown_video_jobs() -> None:
    """Cancel all transport tasks before the serving engine shuts down."""
    tasks = list(_VIDEO_JOB_TASKS.values())
    _VIDEO_JOB_TASKS.clear()
    for task in tasks:
        task.cancel()
    for task in tasks:
        with suppress(asyncio.CancelledError):
            await task