What Is the Purpose of the Image Router in the FastAPI Backend?

The image router in the FastAPI backend provides a dedicated REST API endpoint for AI image generation, abstracting ComfyUI workflow execution behind a stable, versioned HTTP interface.

The image router (api/routers/image.py) in the AIDC-AI/Pixelle-Video repository serves as a critical API surface layer. It transforms internal media generation capabilities into an externally consumable service, enabling clients to generate AI images without managing the complexity of underlying ComfyUI workflows.

Image Router Architecture and Components

Understanding the purpose of the image router requires examining its constituent parts and how they interact with the broader FastAPI application.

Router Registration and Path Prefix

The router is instantiated with a clear namespace and documentation grouping:


# api/routers/image.py

router = APIRouter(prefix="/image", tags=["Basic Services"])

This registration in api/app.py through app.include_router(image_router, prefix=api_config.api_prefix) mounts all routes under /api/image, creating a predictable URL structure for API consumers.

Core Endpoint: POST /image/generate

The primary purpose of the image router is fulfilled by the POST /image/generate endpoint, which accepts structured requests and returns generated image URLs:

@router.post("/generate", response_model=ImageGenerateResponse)
async def generate_image(
    request: ImageGenerateRequest,
    pixelle_video: PixelleVideoDep
) -> ImageGenerateResponse:
    # Delegates to media service and validates output type

The endpoint leverages two Pydantic models defined in api/schemas/image.py:

  • ImageGenerateRequest: Validates prompt, width, height, and optional workflow parameters
  • ImageGenerateResponse: Serializes the response with success, message, and image_path fields

Dependency Injection and Service Layer Integration

A key architectural purpose of the image router is clean separation of concerns through FastAPI's dependency injection system.

PixelleVideoDep Singleton Pattern

The PixelleVideoDep dependency, defined in api/dependencies.py, injects a singleton PixelleVideoCore instance:


# api/dependencies.py

PixelleVideoDep = Annotated[PixelleVideoCore, Depends(get_pixelle_video_core)]

This pattern ensures that:

  • The router accesses shared state (ComfyUI connections, model caches) without global variables
  • Resource-intensive initialization occurs once per application lifecycle
  • Testing becomes straightforward through dependency overrides

Delegation to Media Service

The image router's purpose is orchestration, not execution. It delegates actual generation to pixelle_video/services/media.py:


# Internal call within the endpoint

result = await pixelle_video.media(
    prompt=request.prompt,
    width=request.width,
    height=request.height,
    workflow=request.workflow
)

The media.py service handles:

  • ComfyUI workflow selection and parameter substitution
  • Async queue management and result polling
  • Output file handling and URL generation

Backward Compatibility and Type Safety

An important purpose of the image router is maintaining API stability while the underlying system evolves.

Video Workflow Guard

The unified media service in pixelle_video/services/media.py can produce either images or videos depending on the workflow. The image router enforces type safety:


# Validation within the endpoint

if result.is_video:
    raise HTTPException(
        status_code=400,
        detail="Video workflow used. Please use /media/generate endpoint for video generation."
    )

This guard:

  • Prevents breaking changes for existing clients expecting image-only responses
  • Directs users to the appropriate /media/generate endpoint for video generation
  • Maintains clear error semantics with actionable resolution paths

Practical Usage Examples

cURL Request

curl -X POST "http://localhost:8000/api/image/generate" \
     -H "Content-Type: application/json" \
     -d '{
           "prompt": "A serene mountain landscape at sunset, photorealistic style",
           "width": 1024,
           "height": 1024
         }'

Response:

{
  "success": true,
  "message": "Success",
  "image_path": "http://.../generated/abcd1234.png"
}

Python Client with httpx

import httpx

payload = {
    "prompt": "A futuristic city skyline at night",
    "width": 1024,
    "height": 1024,
    "workflow": "image_flux.json"   # optional custom workflow

}

resp = httpx.post(
    "http://localhost:8000/api/image/generate",
    json=payload,
    timeout=120.0  # generation may take time

)
resp.raise_for_status()
data = resp.json()
print("Generated image URL:", data["image_path"])

Handling Workflow Mismatch Errors

When a video workflow is accidentally specified, the API returns a clear error:

import httpx

payload = {
    "prompt": "A dancing robot",
    "workflow": "video_wan2.json"  # This is a video workflow!

}

resp = httpx.post("http://localhost:8000/api/image/generate", json=payload)
print(resp.status_code)  # 400

print(resp.json())

# {"detail": "Video workflow used. Please use /media/generate endpoint for video generation."}

Summary

The image router in the FastAPI backend serves several interconnected purposes:

  • API Abstraction: Exposes ComfyUI image generation through a clean REST interface without exposing workflow complexity
  • Type Safety: Enforces image-only responses through runtime validation, maintaining contract stability
  • Dependency Management: Leverages FastAPI's injection system for singleton service access and testability
  • Backward Compatibility: Preserves existing /image endpoints while directing video use cases to the newer /media endpoint
  • Documentation Integration: Auto-generates OpenAPI specs through Pydantic models and router tags

These design decisions position the image router as a stable, maintainable API surface that shields clients from internal implementation changes while providing clear migration paths as the Pixelle-Video platform evolves.

Frequently Asked Questions

What is the endpoint URL for image generation in Pixelle-Video?

The image generation endpoint is POST /api/image/generate. The /api prefix is configurable through api_config.api_prefix, and the /image prefix comes from the APIRouter definition in api/routers/image.py. The full path combines these: {api_prefix}/image/generate.

How does the image router handle custom ComfyUI workflows?

The POST /image/generate endpoint accepts an optional workflow parameter in the ImageGenerateRequest schema. This string specifies which JSON workflow file to execute. However, the router validates that the executed workflow produces an image output. If a video workflow is detected, it returns a 400 error directing the client to /media/generate.

What is the difference between the image router and the media router?

The image router (api/routers/image.py) is a specialized endpoint that guarantees image output and maintains backward compatibility with existing clients. The media router (typically api/routers/media.py) is a newer, unified endpoint that handles both image and video generation through the same service layer. The image router delegates to pixelle_video.media() but adds type validation; the media router exposes the full flexibility of the underlying service.

Why does the image router use dependency injection for PixelleVideoCore?

Dependency injection through PixelleVideoDep in api/dependencies.py achieves three goals: resource efficiency by ensuring one PixelleVideoCore instance manages all ComfyUI connections; testability by allowing mock injection during unit tests; and separation of concerns by keeping router code focused on HTTP handling while the core manages workflow execution. This pattern follows FastAPI best practices for scalable service architecture.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →