# Vision Analysis

> Analyze ad creatives using server-side vision AI for structured extraction

Canonical URL: https://fa7e86e3d553:3005/tools/vision-analysis

> **MCP v3 routing:** The operation names on this page are retained as action-contract references. Do not call them as top-level tools. Pass the former name to `lexsis_discover`, then call the returned router and action with the documented parameters inside `args`.

Tools for analyzing ad creatives using server-side vision AI. Use these when you cannot view images yourself (text-only models) or need structured extraction from visual content.

---

## analyze_ad_creative

Call server-side vision AI to analyze ad images, carousels, or videos. Returns structured JSON with headline, claims, colors, tone, and audience signals.

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `image_urls` | string[] | No | Up to 5 image URLs (for carousel ads) |
| `image_base64` | string[] | No | Base64-encoded images (alternative to URLs) |
| `video_url` | string | No | Video URL — will extract frames before analysis |
| `ad_format` | `"image"` \| `"video"` \| `"carousel"` | Yes | Ad format type |

### Returns

`AdAnalysis` object:
```typescript
{
  headline?: string               // Main ad headline text if visible
  subheadline?: string           // Secondary headline if visible
  key_claims: string[]           // Product claims/benefits shown
  visual_style?: string          // "dark luxury" | "clean minimal" | "editorial cream" | etc.
  dominant_colors: string[]      // Hex codes like ["#FF3366", "#1A1A1A"]
  color_palette_name?: string    // "dark_premium" | "clean_white" | "editorial_cream" | etc.
  tone?: string                  // "premium" | "playful" | "clinical" | "editorial" | etc.
  product_shown?: string         // Product name/type if identifiable
  cta_text?: string              // Call-to-action text if visible
  industry_guess?: string        // "skincare" | "food_beverage" | "fashion" | etc.
  persona_signals: string[]      // Audience phrases like "working moms", "fitness enthusiasts"
  confidence?: number            // Analysis confidence score (0-1)
}
```

### Example

```json
{
  "name": "analyze_ad_creative",
  "arguments": {
    "ad_format": "carousel",
    "image_urls": [
      "https://example.com/ad1.jpg",
      "https://example.com/ad2.jpg"
    ]
  }
}
```

**Response:**
```json
{
  "headline": "Your Skin, But Better",
  "subheadline": "Clinically-tested hyaluronic serum",
  "key_claims": [
    "Clinically-tested",
    "72-hour hydration",
    "Visible results in 2 weeks"
  ],
  "visual_style": "clean minimal",
  "dominant_colors": ["#FFFFFF", "#E8D5C4", "#1A1A1A"],
  "color_palette_name": "clean_white",
  "tone": "clinical",
  "product_shown": "Hyaluronic acid serum bottle",
  "cta_text": "Shop Now",
  "industry_guess": "skincare",
  "persona_signals": ["skincare enthusiasts", "minimal beauty", "clinical results"],
  "confidence": 0.92
}
```

### When to Use

- **You're a text-only model** and cannot view images yourself
- **You need structured extraction** from visual content for downstream page generation
- **Processing video ads** — pair with `extract_video_frames` first, or pass `video_url` directly
- **Analyzing carousels** — pass multiple `image_urls` to capture all slides

Feed the `AdAnalysis` result into `match_persona_to_ad` to get copy adaptations.

---

## extract_video_frames

Extract key frames from a video ad URL as base64 JPEGs. Returns start, middle, and end frames (or custom count). Feed results into `analyze_ad_creative`.

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `video_url` | string | Yes | Video URL to extract frames from |
| `frame_count` | number (1–10) | No | Number of frames to extract (default: 3) |

### Returns

```typescript
{
  frames: string[]       // Array of base64-encoded JPEG frames
  frame_count: number    // Actual number of frames extracted
}
```

### Example

```json
{
  "name": "extract_video_frames",
  "arguments": {
    "video_url": "https://example.com/ad-video.mp4",
    "frame_count": 3
  }
}
```

**Response:**
```json
{
  "frames": [
    "/9j/4AAQSkZJRgABAQAAAQABAAD...",
    "iVBORw0KGgoAAAANSUhEUgAABAA...",
    "R0lGODlhAQABAIAAAAAAAP///yH5..."
  ],
  "frame_count": 3
}
```

### When to Use

- **You have a video ad URL** and need static frames for analysis
- Call this first, then pass the base64 frames to `analyze_ad_creative`:

```typescript
// Step 1: Extract frames
const { frames } = await extract_video_frames({ video_url: "...", frame_count: 3 });

// Step 2: Analyze frames
const analysis = await analyze_ad_creative({ 
  ad_format: "video", 
  image_base64: frames 
});
```

---

## get_ad_creatives

Retrieve previously stored ad campaign metadata. Use this to access saved ad analyses without re-analyzing.

### Parameters

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `group_id` | string | No | Ad group UUID to filter by |
| `creative_ids` | string[] (max 20) | No | List of specific creative UUIDs to retrieve |

### Returns

```typescript
{
  group?: AdGroupResult      // Ad group metadata if group_id provided
  creatives: AdCreative[]    // Array of stored ad creatives with analysis
}
```

Each `AdCreative` contains:
- `id` — creative UUID
- `analysis` — the `AdAnalysis` object from prior `analyze_ad_creative` call
- `metadata` — campaign name, platform, dates

### Example

```json
{
  "name": "get_ad_creatives",
  "arguments": {
    "group_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}
```

### When to Use

- **Retrieve stored ad metadata** without re-analyzing
- **Batch-process campaigns** by fetching all creatives in a group
- Check existing analysis before calling `analyze_ad_creative` to avoid duplicate work
