Files
freepik/freepik_cli/commands/analyze.py
T
valknar f24d138ab4 feat: initial Freepik AI CLI
Sophisticated Python CLI for generating and manipulating images and
video via the Freepik API, built with typer + rich.

Commands:
- generate-image: text-to-image with 8 models (flux-2-pro, mystic, seedream, etc.)
- generate-video: image-to-video with 7 models (kling, minimax, runway, etc.)
- generate-icon: text-to-icon in solid/outline/color/flat/sticker styles
- upscale-image: 3 modes (precision-v2, precision, creative) + 2x/4x scale
- upscale-video: standard/turbo modes
- expand-image: outpainting with per-side pixel offsets
- relight: AI-controlled relighting (Premium)
- style-transfer: artistic style application (Premium)
- describe-image: reverse-engineer an image into a prompt
- config set/get/show/reset: configuration management

Features: Rich Live polling panel, exponential backoff, --wait/--no-wait,
auto-timestamped output filenames, streaming download with progress bar,
FREEPIK_API_KEY env var support, venv-based setup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:56:45 +02:00

98 lines
3.1 KiB
Python

"""describe-image command."""
from __future__ import annotations
from pathlib import Path
from typing import Annotated, Optional
import typer
from freepik_cli.api.client import FreepikAPIError, FreepikClient
from freepik_cli.api.images import ImageAPI
from freepik_cli.utils.config import FreepikConfig
from freepik_cli.utils.console import console, print_describe_result, print_error, print_no_wait
from freepik_cli.utils.files import image_to_base64
from freepik_cli.utils.polling import FreepikTaskError, FreepikTimeoutError, PollConfig, poll_task
def _get_api_key(api_key: Optional[str], config: FreepikConfig) -> str:
key = api_key or config.api_key
if not key:
print_error("No API key found.", hint="Set [cyan]FREEPIK_API_KEY[/cyan] or pass [cyan]--api-key[/cyan].")
raise typer.Exit(1)
return key
def describe_image(
image: Annotated[
Path,
typer.Argument(
help="Image to analyze and describe",
exists=True, file_okay=True, dir_okay=False,
),
],
output: Annotated[
Optional[Path],
typer.Option("--output", "-o", help="Save the generated prompt to a text file"),
] = None,
wait: Annotated[
bool,
typer.Option("--wait/--no-wait"),
] = True,
api_key: Annotated[
Optional[str],
typer.Option("--api-key", envvar="FREEPIK_API_KEY"),
] = None,
) -> None:
"""
[bold]Describe an image[/bold] and generate a text prompt for it.
Reverse-engineers the image into an AI-ready prompt you can use with
[cyan]generate-image[/cyan].
[dim]Examples:[/dim]
freepik describe-image photo.jpg
freepik describe-image scene.png --output prompt.txt
"""
config = FreepikConfig.load()
key = _get_api_key(api_key, config)
image_b64 = image_to_base64(image)
with FreepikClient(key, base_url=config.base_url) as client:
api = ImageAPI(client)
with console.status("[info]Submitting image analysis…[/info]"):
try:
task_id = api.describe_submit(image_b64)
except FreepikAPIError as exc:
print_error(str(exc))
raise typer.Exit(1)
if not wait:
print_no_wait(task_id, "describe-image", "image-to-prompt")
return
poll_config = PollConfig(task_type="describe", max_wait=config.poll_timeout)
try:
result = poll_task(
check_fn=lambda tid: api.describe_status(tid),
task_id=task_id,
config=poll_config,
console=console,
)
except (FreepikTaskError, FreepikTimeoutError) as exc:
print_error(str(exc))
raise typer.Exit(1)
prompt_text = api.get_prompt_text(result)
if not prompt_text:
print_error("Analysis completed but no prompt text found.")
raise typer.Exit(1)
saved_path: Optional[Path] = None
if output:
output.write_text(prompt_text, encoding="utf-8")
saved_path = output
print_describe_result(task_id, prompt_text, saved_path)