> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Marketing Video Library Analysis

> Score your entire Vimeo video catalog by emotional impact, message clarity, and behavioral effectiveness using Mavera Video Analysis

### Scenario

Your Vimeo account holds hundreds of marketing videos spanning campaigns, product demos, testimonials, and event recordings — but you have no systematic way to know which are your strongest creative assets. This job pulls your entire video library via `GET /me/videos`, uploads each to Mavera Assets, and runs Video Analysis scoring every video on emotional impact, message clarity, and behavioral effectiveness. The result is a ranked catalog that tells you which videos to promote, which to retire, and which patterns your best-performing creative shares.

### Architecture

```mermaid theme={"dark"}
flowchart LR
    A["Vimeo GET /me/videos"] --> B["Mavera POST /assets"] --> C["POST /video-analysis"] --> D["POST /mave/chat (catalog ranking)"] --> E[Scored creative catalog]
```

### Code

<CodeGroup>
  ```python Python theme={"dark"}
  import os, requests, time

  VM = os.environ["VIMEO_ACCESS_TOKEN"]
  MV = os.environ["MAVERA_API_KEY"]
  VM_BASE = "https://api.vimeo.com"
  MV_BASE = "https://app.mavera.io/api/v1"
  VM_H = {"Authorization": f"Bearer {VM}", "Accept": "application/vnd.vimeo.*+json;version=3.4"}
  MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

  # 1. Fetch entire video library (paginated, 100 per page)
  all_videos = []
  page = 1
  while True:
      resp = requests.get(f"{VM_BASE}/me/videos", headers=VM_H, params={
          "per_page": 100, "page": page,
          "fields": "uri,name,link,duration,stats,created_time,pictures.sizes",
          "sort": "date", "direction": "desc",
      })
      if resp.status_code == 429:
          retry = int(resp.headers.get("Retry-After", 60))
          print(f"Rate limited — waiting {retry}s")
          time.sleep(retry)
          continue
      resp.raise_for_status()
      data = resp.json()

      for v in data.get("data", []):
          vid_id = v["uri"].split("/")[-1]
          all_videos.append({
              "id": vid_id, "name": v["name"], "link": v["link"],
              "duration": v.get("duration", 0),
              "plays": v.get("stats", {}).get("plays", 0),
              "created": v.get("created_time", "")[:10],
          })

      if not data.get("paging", {}).get("next"):
          break
      page += 1
      time.sleep(0.6)

  print(f"Library size: {len(all_videos)} videos")

  # 2. Analyze each video via Mavera (sample top 20 by plays)
  scored = []
  for video in sorted(all_videos, key=lambda v: -v["plays"])[:20]:
      upload = requests.post(f"{MV_BASE}/assets", headers=MV_H, json={
          "url": video["link"], "name": video["name"][:80], "type": "video",
      }).json()

      analysis = requests.post(f"{MV_BASE}/video-analysis", headers=MV_H, json={
          "asset_id": upload["id"],
          "analysis_types": [
              "message_clarity", "emotional_impact", "behavioral_effectiveness",
              "hook_score", "pacing", "cognitive_load",
          ],
          "metadata": {"vimeo_id": video["id"], "plays": video["plays"]},
      }).json()

      for _ in range(30):
          time.sleep(3)
          status = requests.get(
              f"{MV_BASE}/video-analysis/{analysis['id']}", headers=MV_H
          ).json()
          if status.get("status") == "completed":
              break

      r = status.get("results", {})
      scored.append({
          **video,
          "clarity": r.get("message_clarity", {}).get("score", 0),
          "emotion": r.get("emotional_impact", {}).get("score", 0),
          "behavior": r.get("behavioral_effectiveness", {}).get("score", 0),
          "hook": r.get("hook_score", {}).get("score", 0),
      })
      time.sleep(1)

  # 3. Catalog ranking via Mave
  scores_block = "\n".join(
      f"- \"{s['name'][:50]}\" — plays: {s['plays']:,}, clarity: {s['clarity']}/100, "
      f"emotion: {s['emotion']}/100, behavior: {s['behavior']}/100, hook: {s['hook']}/100"
      for s in scored
  )

  ranking = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
      "message": f"""Rank this marketing video library by creative quality.

  SCORED CATALOG ({len(scored)} videos):
  {scores_block}

  Produce:
  1. **Tier 1 — Promote** (top creative assets): which videos and why
  2. **Tier 2 — Optimize** (strong but fixable): what to improve
  3. **Tier 3 — Retire** (underperforming creative): replace with what
  4. **Patterns**: What do Tier 1 videos share that Tier 3 lacks?
  5. **Recommendations**: 3 specific creative briefs for new videos based on the winning patterns""",
  }).json()

  print("MARKETING VIDEO LIBRARY ANALYSIS")
  print("=" * 60)
  for s in sorted(scored, key=lambda x: -x["emotion"]):
      print(f"  {s['name'][:40]:<42} Plays:{s['plays']:>8,}  "
            f"Clarity:{s['clarity']:>3}  Emotion:{s['emotion']:>3}  "
            f"Hook:{s['hook']:>3}")
  print("\n" + ranking.get("content", "")[:2000])
  ```

  ```javascript JavaScript theme={"dark"}
  const VM = process.env.VIMEO_ACCESS_TOKEN;
  const MV = process.env.MAVERA_API_KEY;
  const VM_BASE = "https://api.vimeo.com";
  const MV_BASE = "https://app.mavera.io/api/v1";
  const VM_H = { Authorization: `Bearer ${VM}`, Accept: "application/vnd.vimeo.*+json;version=3.4" };
  const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };

  // 1. Fetch entire library (paginated)
  const allVideos = [];
  let page = 1;
  while (true) {
    const resp = await fetch(
      `${VM_BASE}/me/videos?per_page=100&page=${page}&fields=uri,name,link,duration,stats,created_time&sort=date&direction=desc`,
      { headers: VM_H }
    );
    if (resp.status === 429) {
      const retry = parseInt(resp.headers.get("Retry-After") || "60", 10);
      console.log(`Rate limited — waiting ${retry}s`);
      await new Promise(r => setTimeout(r, retry * 1000));
      continue;
    }
    const data = await resp.json();

    for (const v of data.data || []) {
      allVideos.push({
        id: v.uri.split("/").pop(), name: v.name, link: v.link,
        duration: v.duration || 0,
        plays: v.stats?.plays || 0,
        created: (v.created_time || "").slice(0, 10),
      });
    }
    if (!data.paging?.next) break;
    page++;
    await new Promise(r => setTimeout(r, 600));
  }

  console.log(`Library size: ${allVideos.length} videos`);

  // 2. Analyze top 20 by plays
  const scored = [];
  for (const video of allVideos.sort((a, b) => b.plays - a.plays).slice(0, 20)) {
    const upload = await fetch(`${MV_BASE}/assets`, {
      method: "POST", headers: MV_H,
      body: JSON.stringify({ url: video.link, name: video.name.slice(0, 80), type: "video" }),
    }).then(r => r.json());

    const analysis = await fetch(`${MV_BASE}/video-analysis`, {
      method: "POST", headers: MV_H,
      body: JSON.stringify({
        asset_id: upload.id,
        analysis_types: [
          "message_clarity", "emotional_impact", "behavioral_effectiveness",
          "hook_score", "pacing", "cognitive_load",
        ],
        metadata: { vimeo_id: video.id, plays: video.plays },
      }),
    }).then(r => r.json());

    let status;
    for (let i = 0; i < 30; i++) {
      await new Promise(r => setTimeout(r, 3000));
      status = await fetch(
        `${MV_BASE}/video-analysis/${analysis.id}`, { headers: MV_H }
      ).then(r => r.json());
      if (status.status === "completed") break;
    }

    const r = status.results || {};
    scored.push({
      ...video,
      clarity: r.message_clarity?.score || 0,
      emotion: r.emotional_impact?.score || 0,
      behavior: r.behavioral_effectiveness?.score || 0,
      hook: r.hook_score?.score || 0,
    });
    await new Promise(r => setTimeout(r, 1000));
  }

  // 3. Catalog ranking via Mave
  const scoresBlock = scored.map(s =>
    `- "${s.name.slice(0, 50)}" — plays: ${s.plays.toLocaleString()}, clarity: ${s.clarity}/100, ` +
    `emotion: ${s.emotion}/100, behavior: ${s.behavior}/100, hook: ${s.hook}/100`
  ).join("\n");

  const ranking = await fetch(`${MV_BASE}/mave/chat`, {
    method: "POST", headers: MV_H,
    body: JSON.stringify({
      message: `Rank this marketing video library by creative quality.\n\nCATALOG (${scored.length} videos):\n${scoresBlock}\n\nProduce:\n1. Tier 1 — Promote (top assets and why)\n2. Tier 2 — Optimize (strong but fixable)\n3. Tier 3 — Retire (replace with what)\n4. Patterns (what Tier 1 shares that Tier 3 lacks)\n5. 3 creative briefs for new videos based on winning patterns`,
    }),
  }).then(r => r.json());

  console.log("MARKETING VIDEO LIBRARY ANALYSIS");
  console.log("=".repeat(60));
  scored.sort((a, b) => b.emotion - a.emotion).forEach(s =>
    console.log(`  ${s.name.slice(0, 40).padEnd(42)} Plays:${String(s.plays.toLocaleString()).padStart(8)}  ` +
      `Clarity:${String(s.clarity).padStart(3)}  Emotion:${String(s.emotion).padStart(3)}  ` +
      `Hook:${String(s.hook).padStart(3)}`)
  );
  console.log("\n" + (ranking.content || "").slice(0, 2000));
  ```
</CodeGroup>

### Example Output

```text theme={"dark"}
MARKETING VIDEO LIBRARY ANALYSIS
============================================================
  Q1 Brand Campaign — Feel the Differen    Plays:  84,200  Clarity: 91  Emotion: 94  Hook: 87
  Customer Story — Acme Corp Transformat   Plays:  42,100  Clarity: 88  Emotion: 82  Hook: 76
  Product Demo — Enterprise Dashboard      Plays:  31,500  Clarity: 79  Emotion: 45  Hook: 62
  Webinar Replay — State of the Market     Plays:  18,300  Clarity: 72  Emotion: 38  Hook: 41
  Trade Show Booth Walkthrough             Plays:   9,400  Clarity: 54  Emotion: 29  Hook: 33

## Catalog Ranking

### Tier 1 — Promote
- "Q1 Brand Campaign" (composite: 91/100) — highest emotional impact in library.
  Opens with face close-up and music swell in first 2 seconds. Redistribute as
  paid social hero and homepage embed.
- "Customer Story — Acme Corp" (composite: 82/100) — strong narrative arc with
  clear problem→solution→result structure. Feature on case study landing pages.

### Tier 2 — Optimize
- "Product Demo" — clarity 79 but emotion 45. The demo is thorough but clinical.
  Re-cut with a customer voiceover narrating their workflow instead of feature
  bullet points. Hook score 62 suggests the first 5 seconds need a problem statement.

### Tier 3 — Retire
- "Trade Show Booth Walkthrough" — all scores below 55. This format doesn't
  translate to digital. Replace with a 60-second highlight reel from the booth
  with customer sound bites.

### Patterns
Tier 1 videos share: human faces in first frame, emotional audio within 2 seconds,
single-message focus (1 CTA per video). Tier 3 videos share: wide establishing shots,
multiple messages crammed in, no clear CTA.
```

### Error Handling

<AccordionGroup>
  <Accordion title="Rate limit (429) handling">Vimeo returns a `Retry-After` header in seconds. The code respects this value. Free accounts hit \~100 req/min; Pro/Business accounts get \~600 req/10 min. Add exponential backoff for large libraries.</Accordion>
  <Accordion title="Video file access scope">The `video_files` scope is required to access download URLs for some endpoints. Without it, use the `link` field (public Vimeo URL) for Mavera asset uploads instead.</Accordion>
  <Accordion title="Large library pagination">Libraries with 500+ videos require multiple pages. Each page costs one API call. The code paginates automatically but add a 600ms delay between pages to stay within rate limits.</Accordion>
</AccordionGroup>

***

## What's Next

<CardGroup cols={2}>
  <Card title="Vimeo Integration" icon="circle-play" href="/integrations/vimeo">
    Back to Vimeo integration overview
  </Card>

  <Card title="Pre-Publish Creative Testing" icon="flask-vial" href="/integrations/vimeo/pre-publish-testing">
    Gate publishing with quality thresholds
  </Card>

  <Card title="Video Analysis API" icon="chart-bar" href="/api-reference/video-analysis">
    Full reference for POST /api/v1/video-analysis
  </Card>

  <Card title="Mave Agent" icon="brain" href="/api-reference/mave">
    Full reference for POST /api/v1/mave/chat
  </Card>
</CardGroup>
