---
name: vibrant-maximalism
description: Web and App implementation guide for Vibrant Maximalism. Trigger when user wants rich colors, dense layouts, extreme sensory input, and "more is more".
date_added: "2026-06-17"
risk: safe
source: self
source_type: self
---

# Vibrant Maximalism

> "More is more. An explosion of color, pattern, and typography."

## When to Use
Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the `design-it` skill and is not meant to be triggered directly.

## Core Principles
1. **Sensory Overload**: Every pixel is doing something. Patterns on top of gradients on top of photos.
2. **Clashing Colors**: Forget the standard rules of color harmony. Pair neon green with hot pink, or bright orange with electric blue.
3. **Multiple Fonts**: Mix 3 or 4 completely different typefaces in the same layout.

## Visual DNA
- **Colors**: All of them. Highly saturated, unmuted hues. No calm neutrals allowed.
- **Typography**: A chaotic mix. A massive serif headline, a bubble-letter subhead, and a monospace body text.
- **Visuals**: Stickers, repeating patterns, emojis, 3D renders, and marquee scrolling text.

## Web Implementation
- **CSS Example**:
```css
body {
  /* Complex clashing background */
  background:
    radial-gradient(circle at 20% 30%, #FF00FF 0%, transparent 40%),
    radial-gradient(circle at 80% 70%, #00FFFF 0%, transparent 40%),
    url('checkerboard-pattern.png') repeat;
  background-color: #FFFF00;
  color: #000;
  overflow-x: hidden;
}

.max-headline {
  font-family: 'Anton', sans-serif;
  font-size: 8rem;
  text-transform: uppercase;
  line-height: 0.8;
  color: #FF0000;
  /* Crazy shadow effect */
  text-shadow:
    4px 4px 0px #000,
    8px 8px 0px #00FFFF,
    12px 12px 0px #FF00FF;
  transform: rotate(-3deg);
}

.max-sticker {
  position: absolute;
  background: #000;
  color: #00FF00;
  font-family: monospace;
  padding: 10px;
  border-radius: 50%;
  width: 100px;
  height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border: 4px dashed #FF00FF;
  animation: spin 10s linear infinite;
}

@keyframes spin { 100% { transform: rotate(360deg); } }

.max-card {
  background: rgba(255, 255, 255, 0.9);
  border: 5px solid #000;
  box-shadow: 10px 10px 0px #0000FF;
  padding: 40px;
  border-radius: 0 40px 0 40px; /* Weird asymmetrical corners */
}
```

## App Implementation

### SwiftUI
```swift
struct VibrantMaximalismView: View {
    var body: some View {
        ScrollView {
            ZStack {
                // Chaotic Layered Background
                Color(hex: "FFFF00").ignoresSafeArea() // Pure Yellow

                Circle()
                    .fill(RadialGradient(colors: [Color(hex: "FF00FF"), .clear], center: .center, startRadius: 0, endRadius: 200))
                    .frame(width: 400, height: 400)
                    .offset(x: -100, y: -200)

                Circle()
                    .fill(RadialGradient(colors: [Color(hex: "00FFFF"), .clear], center: .center, startRadius: 0, endRadius: 200))
                    .frame(width: 400, height: 400)
                    .offset(x: 150, y: 200)

                // Content
                VStack(spacing: 40) {
                    Text("OVERLOAD")
                        .font(.custom("Anton", size: 80))
                        .foregroundColor(Color(hex: "FF0000"))
                        .shadow(color: .black, radius: 0, x: 4, y: 4)
                        .shadow(color: Color(hex: "00FFFF"), radius: 0, x: 8, y: 8)
                        .rotationEffect(.degrees(-3))

                    // Weird shaped card
                    VStack {
                        Text("More is more.")
                            .font(.system(size: 24, weight: .black, design: .monospaced))
                    }
                    .padding(40)
                    .background(Color.white.opacity(0.9))
                    .border(.black, width: 5)
                    .cornerRadius(40, corners: [.topRight, .bottomLeft]) // Custom corner radius extension needed
                    .shadow(color: Color(hex: "0000FF"), radius: 0, x: 10, y: 10)
                }
            }
        }
    }
}
```
- Layer multiple `RadialGradient`s in a `ZStack` behind the content to create the complex, clashing color blobs.
- Use multiple hard drop shadows (radius 0, but large X/Y offsets) in clashing colors to build the loud text effect.

### Flutter
```dart
class VibrantMaximalismScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          // Background Color
          Container(color: const Color(0xFFFFFF00)),
          // Gradient Blob 1
          Positioned(
            top: -100, left: -100,
            child: Container(
              width: 400, height: 400,
              decoration: const BoxDecoration(
                shape: BoxShape.circle,
                gradient: RadialGradient(colors: [Color(0xFFFF00FF), Colors.transparent]),
              ),
            ),
          ),

          Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Transform.rotate(
                  angle: -0.05, // Slight tilt
                  child: const Text(
                    'OVERLOAD',
                    style: TextStyle(
                      fontFamily: 'Anton', fontSize: 80, color: Color(0xFFFF0000),
                      shadows: [
                        Shadow(color: Colors.black, offset: Offset(4, 4)),
                        Shadow(color: Color(0xFF00FFFF), offset: Offset(8, 8)),
                      ]
                    ),
                  ),
                ),
                const SizedBox(height: 40),

                // Weird asymmetrical card
                Container(
                  padding: const EdgeInsets.all(40),
                  decoration: BoxDecoration(
                    color: Colors.white.withOpacity(0.9),
                    border: Border.all(color: Colors.black, width: 5),
                    borderRadius: const BorderRadius.only(topRight: Radius.circular(40), bottomLeft: Radius.circular(40)),
                    boxShadow: const [BoxShadow(color: Color(0xFF0000FF), offset: Offset(10, 10))],
                  ),
                  child: const Text('More is more.', style: TextStyle(fontFamily: 'Courier', fontSize: 24, fontWeight: FontWeight.bold)),
                )
              ],
            ),
          ),
        ],
      ),
    );
  }
}
```
- Flutter's `Stack` with `Positioned` widgets lets you throw clashing radial gradients anywhere on the screen easily.
- Apply `BorderRadius.only` to create bizarre, asymmetrical containers that break typical UI norms.

### React Native
```jsx
const VibrantMaximalismScreen = () => {
  return (
    <ScrollView style={{ flex: 1, backgroundColor: '#FFFF00' }}>

      {/* Emulating radial blobs in RN usually requires SVG or ImageBackground. For simplicity, we use absolute views here */}
      <View style={{ position: 'absolute', top: -50, left: -50, width: 300, height: 300, borderRadius: 150, backgroundColor: '#FF00FF', opacity: 0.5, filter: 'blur(50px)' }} />

      <View style={{ padding: 40, alignItems: 'center', marginTop: 100 }}>

        {/* Loud Text */}
        <Text style={{
          fontFamily: 'Anton-Regular', fontSize: 64, color: '#FF0000',
          transform: [{ rotate: '-3deg' }],
          textShadowColor: '#00FFFF', textShadowOffset: { width: 8, height: 8 }, textShadowRadius: 0
        }}>
          OVERLOAD
        </Text>

        {/* Asymmetrical Card */}
        <View style={{
          marginTop: 60, padding: 40, backgroundColor: 'rgba(255,255,255,0.9)',
          borderWidth: 5, borderColor: '#000',
          borderTopRightRadius: 40, borderBottomLeftRadius: 40,
          shadowColor: '#0000FF', shadowOffset: { width: 10, height: 10 }, shadowOpacity: 1, shadowRadius: 0, elevation: 10
        }}>
          <Text style={{ fontFamily: 'monospace', fontSize: 24, fontWeight: '900' }}>More is more.</Text>
        </View>

      </View>
    </ScrollView>
  );
};
```
- Use `textShadowRadius: 0` to create hard, offset, brutalist-style text shadows in clashing colors (e.g. Red text with a Cyan hard shadow).
- Apply `transform: [{ rotate: '-3deg' }]` to break alignment intentionally.

### Jetpack Compose
```kotlin
@Composable
fun VibrantMaximalismScreen() {
    Box(modifier = Modifier.fillMaxSize().background(Color(0xFFFFFF00))) {

        // Emulated Radial Gradients
        Box(modifier = Modifier.offset(x = (-100).dp, y = (-100).dp).size(400.dp).background(Brush.radialGradient(listOf(Color(0xFFFF00FF), Color.Transparent))))
        Box(modifier = Modifier.offset(x = 100.dp, y = 300.dp).size(400.dp).background(Brush.radialGradient(listOf(Color(0xFF00FFFF), Color.Transparent))))

        Column(
            modifier = Modifier.fillMaxSize().padding(40.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            // Rotated Headline
            Text(
                text = "OVERLOAD",
                fontSize = 80.sp,
                fontFamily = FontFamily.SansSerif, // Replace with Anton
                color = Color(0xFFFF0000),
                modifier = Modifier.rotate(-3f),
                style = TextStyle(
                    shadow = Shadow(color = Color(0xFF00FFFF), offset = Offset(16f, 16f), blurRadius = 0f)
                )
            )

            Spacer(Modifier.height(60.dp))

            // Asymmetrical Card
            Box(
                modifier = Modifier
                    .shadow(elevation = 0.dp) // Reset default shadow
                    // Custom hard shadow trick: draw the shadow shape first
                    .offset(10.dp, 10.dp)
                    .background(Color(0xFF0000FF), RoundedCornerShape(topEnd = 40.dp, bottomStart = 40.dp))
                    .offset((-10).dp, (-10).dp)
                    .background(Color.White.copy(alpha = 0.9f), RoundedCornerShape(topEnd = 40.dp, bottomStart = 40.dp))
                    .border(5.dp, Color.Black, RoundedCornerShape(topEnd = 40.dp, bottomStart = 40.dp))
                    .padding(40.dp)
            ) {
                Text("More is more.", fontFamily = FontFamily.Monospace, fontSize = 24.sp, fontWeight = FontWeight.Black)
            }
        }
    }
}
```
- `Brush.radialGradient` works perfectly for dropping color blobs into the background.
- Compose's default `shadow` modifier blurs edges. To get a hard, brutalist shadow in Compose, render an identical shape offset behind the main shape with a solid color.

## Do's and Don'ts
- **DO**: Break the grid. Let elements overlap awkwardly.
- **DON'T**: Use whitespace. If there is an empty area, fill it with a pattern, a marquee, or a giant emoji.

## Limitations
- This is a styling reference and does not replace environment-specific validation, accessibility testing, or expert review.
- Ensure appropriate contrast ratios and responsive behaviors are verified separately.


---
name: video-content-extractor
description: "Extract key frames from MP4 videos at configurable intervals, run Tesseract OCR, and generate structured Markdown reports with video metadata and timestamped text transcripts."
category: media-processing
risk: safe
source: community
source_repo: 274326424/video-content-extractor
source_type: community
date_added: "2026-06-06"
author: 274326424
tags: [video, ocr, ffmpeg, tesseract, frame-extraction, media]
tools: [codex]
---

# Video Content Extractor

## Overview

Automatically extracts key frames from MP4 video files at configurable time intervals, performs OCR text recognition on each frame, and generates a structured Markdown report. The report includes video metadata (duration, resolution, codecs) and frame-by-frame OCR transcripts with timestamp references.

This skill is designed for Codex CLI and requires FFmpeg and Tesseract OCR installed on the local machine.

## When to Use This Skill

- Use when you need to extract text content from video presentations, lectures, or screencasts.
- Use when you want to create searchable transcripts from video files without embedded subtitles.
- Use when you need to analyze video content programmatically and generate structured summaries.
- Use when the user asks to "read what is on screen" or "extract the content from this video."

## How It Works

### Step 1: Analyze Video Metadata

The skill uses ffprobe to extract video metadata: duration, resolution, frame rate, codec information, and file size.

### Step 2: Extract Key Frames

Using FFmpeg, the skill captures frames at the configured interval (default: every 30 seconds). Each frame is saved as a timestamped JPEG image.

### Step 3: OCR Text Recognition

Each extracted frame is processed by Tesseract OCR. If the default PSM mode returns no meaningful text, it falls back to fully automatic page segmentation.

### Step 4: Generate Markdown Report

All extracted data is assembled into a structured Markdown document.

## Examples

### Example 1: Basic Extraction

Agent prompt:
Use the video-content-extractor skill to extract content from lecture.mp4

Output generates lecture.md and lecture_frames/ directory.

### Example 2: Custom Interval

Parameters: video_path, output_dir, interval(seconds), lang
Extract every 60 seconds with English-only OCR:
python scripts/extract_video.py recording.mp4 ./output 60 eng

### Example 3: Bilingual Content

Extract with default Chinese + English OCR:
python scripts/extract_video.py lecture.mp4 . 15 chi_sim+eng

## Best Practices

- Use shorter intervals (10-15s) for fast-paced content with frequent text changes.
- Use longer intervals (30-60s) for presentation slides or slow lectures to reduce duplicate frames.
- For Chinese content, ensure Tesseract Chinese language pack is installed (chi_sim).

## Limitations

- Requires FFmpeg and Tesseract OCR to be installed and accessible via PATH.
- Tesseract OCR accuracy depends on video quality, text size, and font clarity.
- Does not extract audio or perform speech-to-text transcription.
- Frame extraction is time-based (not scene-change-based), which may produce near-duplicate frames.
- Large videos with short intervals can generate many frames - ensure sufficient disk space.

## Security and Safety Notes

- This skill only reads video files and writes extracted frames and Markdown reports.
- It does NOT send any data over the network - all processing is local.
- FFmpeg and Tesseract are invoked with fixed, pre-vetted arguments.
- The skill does not modify or delete the original video file.

## Common Pitfalls

- Problem: Tesseract returns garbled text
  Solution: Ensure the correct language pack is installed. Run tesseract --list-langs to verify.

- Problem: FFmpeg fails with "not found"
  Solution: Make sure FFmpeg is on PATH. Run ffmpeg -version to verify.

- Problem: OCR is slow on large videos
  Solution: Increase the interval parameter to reduce frames processed.

## Related Skills

- @media-summarizer - For summarizing video content using visual and audio cues.
- @document-ocr - For OCR on static images or scanned documents without video processing.


---
name: video-router
description: "Route a video-production brief to generation, deterministic composition, supplied-footage editing, or an automatic cross-modal plan before production begins."
category: media
risk: none
source: "https://github.com/Orkas-AI/Orkas-VideoStudio/tree/dd4a0f40b2bc6c6b0fe6f2e732c9540ffffefe08/packages/skills/video-router"
source_repo: Orkas-AI/Orkas-VideoStudio
source_type: official
date_added: "2026-08-07"
author: Orkas-AI
license: MIT
license_source: "https://github.com/Orkas-AI/Orkas-VideoStudio/blob/dd4a0f40b2bc6c6b0fe6f2e732c9540ffffefe08/LICENSE"
tags: [video, routing, editing, composition, generation]
tools: [claude, codex, cursor, gemini]
---

# Video Router

Knowledge for picking a video production line and locking it before work begins. This skill is read for guidance; it describes **what to decide**, not any tool mechanics.

## When to Use This Skill

- Use before production when a request asks to make, compose, generate, edit, repurpose, or finish a video.
- Use when a mixed brief needs one explicit primary path or an AUTO end-to-end route.
- Do not use it to author compositions, generate assets, edit media, or render output; hand those tasks to the relevant production skill after routing.

## Packaged Source Note

This AAS-ready adaptation preserves the routing rules from the official OrkasVideoStudio `video-router` skill at upstream commit `dd4a0f40b2bc6c6b0fe6f2e732c9540ffffefe08`. It adds catalog metadata, examples, and limitations; it does not bundle or install the OrkasVideoStudio runtime. The immutable `license_source` above points to the upstream MIT license reviewed for this import.

## Unavailable Production Runtime

If production, rendering, or paid tools are explicitly unavailable, still select the line and return a complete **unexecuted production package** for a clear brief: assumptions, script/narration, timed storyboard/shotlist, exact visible copy and captions, visual/audio direction, rights-safe asset provenance/fallbacks, export target, preview checklist, and final encoding/playback QA. Clearly distinguish planned from produced media and do not withhold the package behind a direction form.

## The Three Capability Axes

A finished video is built from one or more of three orthogonal axes. Decide which dominate, then lock them.

- **Generate (A)** — AI-generated footage/imagery: photoreal shots, b-roll, motion, talking-head. Use when the brief needs real-looking or cinematic visuals.
- **Compose (B)** — deterministic HTML composition: explainers, kinetic typography, motion graphics, captions / lower-thirds / overlays, data viz, title cards, transitions. Use when the visuals are designed rather than filmed. This is the default for explainer/animation work.
- **Edit (C)** — intelligent editing of supplied footage: evidence-based selection/cleanup, deterministic cut/join/reframe/captions/audio work, and semantic AI video editing for bounded pixel-level changes.

## Decision Rules

1. Read the brief (topic, aspect ratio, language, duration) and classify the **dominant work object**:
   - "explain / teach / animate / motion-graphics / kinetic text" → **Compose (B)** primary, optionally Generate (A) for b-roll.
   - "make footage of / cinematic / a scene of / a character doing" → **Generate (A)** primary, Compose (B) to overlay captions.
   - "cut / clip / trim / repurpose / make highlights / remove or change something in my video" → **Edit (C)** primary. Keep EDIT as the route even when a billable `operation:"edit"` segment is required.
2. Most explainer/animation requests are **Compose-primary**: typographic and motion-graphic scenes assembled as an HTML composition, with AI imagery only where a shot genuinely needs it.
3. For supplied reference media, classify the requested relationship as `reproduce`, `edit`, or `guide` before choosing execution. Apply the same classification regardless of origin. Images can control content/identity/composition/structure/style; videos can additionally control motion/timing/audio through temporal anchors.
4. Aspect ratio drives the canvas: 16:9 → 1920×1080, 9:16 → 1080×1920, 1:1 → 1080×1080.

## End-to-End (AUTO) — When the Job Spans Lines

Pick a **single line** when one axis cleanly dominates (just trim a clip; just an explainer; just generate a scene). Route to **AUTO end-to-end** when the deliverable genuinely needs MORE THAN ONE axis woven together — most often the user supplies their own material AND wants finished framing/voice/motion around it:

- "trim my clip, add a title card + captions, and a voiceover" (edit + compose + narration)
- "my footage in the middle, generate an opener, compose the stats" (edit + generate + compose)
- "make a finished video from these assets" where the assets alone are not the deliverable.

AUTO does not abandon the axes — it sequences them through one cross-modal plan (`stage-plan` builds the EDL, `stage-assemble` walks it), delegating each segment back to the generate / compose / edit lines. Choosing AUTO is itself the lock: the *primary* still gets named via the plan's `delivery_promise` (source_led / motion_led / compose_led / hybrid).

## Lock the Runtime

- Decide the primary axis at the brief/proposal stage and **state it in the proposal**.
- Once locked, do not silently switch the primary axis mid-run. If a later step reveals the wrong choice, surface it to the user and re-confirm rather than quietly changing course.
- Layering is fine and expected (e.g. Compose captions over Generated footage); "locking" governs the **primary** path, not the allowed overlays.

## Examples

### Compose Primary

Request: "Make a 60-second vertical explainer about vector databases with kinetic text and captions."

Route: lock **Compose (B)** primary at 1080×1920. Add Generate (A) only if the approved concept needs original b-roll.

### Edit Primary

Request: "Turn my one-hour interview into three captioned highlight clips."

Route: lock **Edit (C)** primary because supplied footage is the dominant work object. Preserve evidence for selections and cleanup.

### AUTO End-to-End

Request: "Use my product footage, generate a five-second opener, compose the feature stats, and add one voiceover."

Route: lock **AUTO**, name the delivery promise, and plan the edit, generate, compose, and narration segments in one cross-modal EDL.

## Limitations

- This skill chooses and locks a route; it does not provide a renderer, editor, media generator, or production runtime.
- Stage names such as `stage-plan` and `stage-assemble` refer to the upstream OrkasVideoStudio workflow and may be unavailable unless the user separately installs or supplies a compatible runtime.
- Generation provider access, costs, licensing, and safety constraints are outside this router; confirm them before a downstream generation stage.
- Do not claim media was produced when only an unexecuted production package was prepared.

## Boundary / Non-Goals

This skill only routes and locks. Semantic editing is not a silent switch to GENERATE: it remains an EDIT/AUTO job with a signed billable video edit segment and explicit original/preservation boundary.


---
name: videodb
description: Video and audio perception, indexing, and editing. Ingest files/URLs/live streams, build visual/spoken indexes, search with timestamps, edit timelines, add overlays/subtitles, generate media, and create real-time alerts.
category: media
risk: safe
source: community
tags: "[video, editing, transcription, subtitles, search, streaming, ai-generation, media, live-streams, desktop-capture]"
date_added: "2026-02-27"
allowed-tools: Read Grep Glob Bash(python:*)
argument-hint: "[task description]"
---

# VideoDB Skill

**Perception + memory + actions for video, live streams, and desktop sessions.**

Use this skill when you need to:

## When to Use
- You need video or audio perception, indexing, search, or timeline editing from files, URLs, desktop sessions, or live streams.
- The task involves timestamps, searchable evidence, subtitles, clips, overlays, or real-time monitoring alerts.
- You want one workflow that combines ingestion, understanding, retrieval, and media actions.

## 1) Desktop Perception
- Start/stop a **desktop session** capturing **screen, mic, and system audio**
- Stream **live context** and store **episodic session memory**
- Run **real-time alerts/triggers** on what's spoken and what's happening on screen
- Produce **session summaries**, a searchable timeline, and **playable evidence links**

## 2) Video ingest + stream
- Ingest a **file or URL** and return a **playable web stream link**
- Transcode/normalize: **codec, bitrate, fps, resolution, aspect ratio**

## 3) Index + search (timestamps + evidence)
- Build **visual**, **spoken**, and **keyword** indexes
- Search and return exact moments with **timestamps** and **playable evidence**
- Auto-create **clips** from search results

## 4) Timeline editing + generation
- Subtitles: **generate**, **translate**, **burn-in**
- Overlays: **text/image/branding**, motion captions
- Audio: **background music**, **voiceover**, **dubbing**
- Programmatic composition and exports via **timeline operations**

## 5) Live streams (RTSP) + monitoring
- Connect **RTSP/live feeds**
- Run **real-time visual and spoken understanding** and emit **events/alerts** for monitoring workflows

---

## Common inputs
- Local **file path**, public **URL**, or **RTSP URL**
- Desktop capture request: **start / stop / summarize session**
- Desired operations: get context for understanding, transcode spec, index spec, search query, clip ranges, timeline edits, alert rules

## Common outputs
- **Stream URL**
- Search results with **timestamps** and **evidence links**
- Generated assets: subtitles, audio, images, clips
- **Event/alert payloads** for live streams
- Desktop **session summaries** and memory entries

---

## Canonical prompts (examples)
- "Start desktop capture and alert when a password field appears."
- "Record my session and produce an actionable summary when it ends."
- "Ingest this file and return a playable stream link."
- "Index this folder and find every scene with people, return timestamps."
- "Generate subtitles, burn them in, and add light background music."
- "Connect this RTSP URL and alert when a person enters the zone."

## Running Python code

Before running any VideoDB code, change to the project directory and load environment variables:

```python
from dotenv import load_dotenv
load_dotenv(".env")

import videodb
conn = videodb.connect()
```

This reads `VIDEO_DB_API_KEY` from:
1. Environment (if already exported)
2. Project's `.env` file in current directory

If the key is missing, `videodb.connect()` raises `AuthenticationError` automatically.

Do NOT write a script file when a short inline command works.

When writing inline Python (`python -c "..."`), always use properly formatted code — use semicolons to separate statements and keep it readable. For anything longer than ~3 statements, use a heredoc instead:

```bash
python << 'EOF'
from dotenv import load_dotenv
load_dotenv(".env")

import videodb
conn = videodb.connect()
coll = conn.get_collection()
print(f"Videos: {len(coll.get_videos())}")
EOF
```

## Setup

When the user asks to "setup videodb" or similar:

### 1. Install SDK

```bash
pip install "videodb[capture]" python-dotenv
```

If `videodb[capture]` fails on Linux, install without the capture extra:

```bash
pip install videodb python-dotenv
```

### 2. Configure API key

The user must set `VIDEO_DB_API_KEY` using **either** method:

- **Export in terminal** (before starting Claude): `export VIDEO_DB_API_KEY=your-key`
- **Project `.env` file**: Save `VIDEO_DB_API_KEY=your-key` in the project's `.env` file

Get a free API key at https://console.videodb.io (50 free uploads, no credit card).

**Do NOT** read, write, or handle the API key yourself. Always let the user set it.

## Quick Reference

### Upload media

```python
# URL
video = coll.upload(url="https://example.com/video.mp4")

# YouTube
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")

# Local file
video = coll.upload(file_path="/path/to/video.mp4")
```

### Transcript + subtitle

```python
# force=True skips the error if the video is already indexed
video.index_spoken_words(force=True)
text = video.get_transcript_text()
stream_url = video.add_subtitle()
```

### Search inside videos

```python
from videodb.exceptions import InvalidRequestError

video.index_spoken_words(force=True)

# search() raises InvalidRequestError when no results are found.
# Always wrap in try/except and treat "No results found" as empty.
try:
    results = video.search("product demo")
    shots = results.get_shots()
    stream_url = results.compile()
except InvalidRequestError as e:
    if "No results found" in str(e):
        shots = []
    else:
        raise
```

### Scene search

```python
import re
from videodb import SearchType, IndexType, SceneExtractionType
from videodb.exceptions import InvalidRequestError

# index_scenes() has no force parameter — it raises an error if a scene
# index already exists. Extract the existing index ID from the error.
try:
    scene_index_id = video.index_scenes(
        extraction_type=SceneExtractionType.shot_based,
        prompt="Describe the visual content in this scene.",
    )
except Exception as e:
    match = re.search(r"id\s+([a-f0-9]+)", str(e))
    if match:
        scene_index_id = match.group(1)
    else:
        raise

# Use score_threshold to filter low-relevance noise (recommended: 0.3+)
try:
    results = video.search(
        query="person writing on a whiteboard",
        search_type=SearchType.semantic,
        index_type=IndexType.scene,
        scene_index_id=scene_index_id,
        score_threshold=0.3,
    )
    shots = results.get_shots()
    stream_url = results.compile()
except InvalidRequestError as e:
    if "No results found" in str(e):
        shots = []
    else:
        raise
```

### Timeline editing

**Important:** Always validate timestamps before building a timeline:
- `start` must be >= 0 (negative values are silently accepted but produce broken output)
- `start` must be < `end`
- `end` must be <= `video.length`

```python
from videodb.timeline import Timeline
from videodb.asset import VideoAsset, TextAsset, TextStyle

timeline = Timeline(conn)
timeline.add_inline(VideoAsset(asset_id=video.id, start=10, end=30))
timeline.add_overlay(0, TextAsset(text="The End", duration=3, style=TextStyle(fontsize=36)))
stream_url = timeline.generate_stream()
```

### Transcode video (resolution / quality change)

```python
from videodb import TranscodeMode, VideoConfig, AudioConfig

# Change resolution, quality, or aspect ratio server-side
job_id = conn.transcode(
    source="https://example.com/video.mp4",
    callback_url="https://example.com/webhook",
    mode=TranscodeMode.economy,
    video_config=VideoConfig(resolution=720, quality=23, aspect_ratio="16:9"),
    audio_config=AudioConfig(mute=False),
)
```

### Reframe aspect ratio (for social platforms)

**Warning:** `reframe()` is a slow server-side operation. For long videos it can take
several minutes and may time out. Best practices:
- Always limit to a short segment using `start`/`end` when possible
- For full-length videos, use `callback_url` for async processing
- Trim the video on a `Timeline` first, then reframe the shorter result

```python
from videodb import ReframeMode

# Always prefer reframing a short segment:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)

# Async reframe for full-length videos (returns None, result via webhook):
video.reframe(target="vertical", callback_url="https://example.com/webhook")

# Presets: "vertical" (9:16), "square" (1:1), "landscape" (16:9)
reframed = video.reframe(start=0, end=60, target="square")

# Custom dimensions
reframed = video.reframe(start=0, end=60, target={"width": 1280, "height": 720})
```

### Generative media

```python
image = coll.generate_image(
    prompt="a sunset over mountains",
    aspect_ratio="16:9",
)
```

## Error handling

```python
from videodb.exceptions import AuthenticationError, InvalidRequestError

try:
    conn = videodb.connect()
except AuthenticationError:
    print("Check your VIDEO_DB_API_KEY")

try:
    video = coll.upload(url="https://example.com/video.mp4")
except InvalidRequestError as e:
    print(f"Upload failed: {e}")
```

### Common pitfalls

| Scenario | Error message | Solution |
|----------|--------------|----------|
| Indexing an already-indexed video | `Spoken word index for video already exists` | Use `video.index_spoken_words(force=True)` to skip if already indexed |
| Scene index already exists | `Scene index with id XXXX already exists` | Extract the existing `scene_index_id` from the error with `re.search(r"id\s+([a-f0-9]+)", str(e))` |
| Search finds no matches | `InvalidRequestError: No results found` | Catch the exception and treat as empty results (`shots = []`) |
| Reframe times out | Blocks indefinitely on long videos | Use `start`/`end` to limit segment, or pass `callback_url` for async |
| Negative timestamps on Timeline | Silently produces broken stream | Always validate `start >= 0` before creating `VideoAsset` |
| `generate_video()` / `create_collection()` fails | `Operation not allowed` or `maximum limit` | Plan-gated features — inform the user about plan limits |

## Additional docs

Reference documentation is in the `reference/` directory adjacent to this SKILL.md file. Use the Glob tool to locate it if needed.

- [reference/api-reference.md](reference/api-reference.md) - Complete VideoDB Python SDK API reference
- [reference/search.md](reference/search.md) - In-depth guide to video search (spoken word and scene-based)
- [reference/editor.md](reference/editor.md) - Timeline editing, assets, and composition
- [reference/streaming.md](reference/streaming.md) - HLS streaming and instant playback
- [reference/generative.md](reference/generative.md) - AI-powered media generation (images, video, audio)
- [reference/rtstream.md](reference/rtstream.md) - Live stream ingestion workflow (RTSP/RTMP)
- [reference/rtstream-reference.md](reference/rtstream-reference.md) - RTStream SDK methods and AI pipelines
- [reference/capture.md](reference/capture.md) - Desktop capture workflow
- [reference/capture-reference.md](reference/capture-reference.md) - Capture SDK and WebSocket events
- [reference/use-cases.md](reference/use-cases.md) - Common video processing patterns and examples

## Screen Recording (Desktop Capture)

Use `ws_listener.py` to capture WebSocket events during recording sessions. Desktop capture supports **macOS** only.

### Quick Start

1. **Start listener**: `python scripts/ws_listener.py &`
2. **Get WebSocket ID**: `cat /tmp/videodb_ws_id`
3. **Run capture code** (see reference/capture.md for full workflow)
4. **Events written to**: `/tmp/videodb_events.jsonl`

### Query Events

```python
import json
events = [json.loads(l) for l in open("/tmp/videodb_events.jsonl")]

# Get all transcripts
transcripts = [e["data"]["text"] for e in events if e.get("channel") == "transcript"]

# Get visual descriptions from last 5 minutes
import time
cutoff = time.time() - 300
recent_visual = [e for e in events
                 if e.get("channel") == "visual_index" and e["unix_ts"] > cutoff]
```

### Utility Scripts

- [scripts/ws_listener.py](scripts/ws_listener.py) - WebSocket event listener (dumps to JSONL)

For complete capture workflow, see [reference/capture.md](reference/capture.md).

**Do not use ffmpeg, moviepy, or local encoding tools** when VideoDB supports the operation. The following are all handled server-side by VideoDB — trimming, combining clips, overlaying audio or music, adding subtitles, text/image overlays, transcoding, resolution changes, aspect-ratio conversion, resizing for platform requirements, transcription, and media generation. Only fall back to local tools for operations listed under Limitations in reference/editor.md (transitions, speed changes, crop/zoom, colour grading, volume mixing).

### When to use what

| Problem | VideoDB solution |
|---------|-----------------|
| Platform rejects video aspect ratio or resolution | `video.reframe()` or `conn.transcode()` with `VideoConfig` |
| Need to resize video for Twitter/Instagram/TikTok | `video.reframe(target="vertical")` or `target="square"` |
| Need to change resolution (e.g. 1080p → 720p) | `conn.transcode()` with `VideoConfig(resolution=720)` |
| Need to overlay audio/music on video | `AudioAsset` on a `Timeline` |
| Need to add subtitles | `video.add_subtitle()` or `CaptionAsset` |
| Need to combine/trim clips | `VideoAsset` on a `Timeline` |
| Need to generate voiceover, music, or SFX | `coll.generate_voice()`, `generate_music()`, `generate_sound_effect()` |

## Repository

https://github.com/video-db/skills

**Maintained By:** [VideoDB](https://github.com/video-db)

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: videodb-skills
description: "Upload, stream, search, edit, transcribe, and generate AI video and audio using the VideoDB SDK."
category: media
risk: safe
source: community
tags: "[video, editing, transcription, subtitles, search, streaming, ai-generation, media]"
date_added: "2026-02-27"
---

# VideoDB Skills

## Purpose

The only video skill your agent needs. Upload any video, connect real-time streams, search inside by what was said or shown, build complex editing workflows with overlays, generate AI media, add subtitles, and get instant streaming links — all via the VideoDB Python SDK.

## When to Use This Skill

- User wants to upload and process videos from YouTube, URLs, or local files
- User needs to search for moments by speech or visual scenes
- User asks for transcription, subtitles, or subtitle styling
- User wants to edit clips — trim, combine, add text/image/audio overlays
- User needs AI-generated media (images, video, music, sound effects, voiceovers)
- User wants to transcode, change resolution, or reframe for social platforms
- User needs real-time screen or audio capture with AI transcription
- User asks for playable streaming links for any video output

## Setup

### Step 1: Install the skill

```bash
npx skills add video-db/skills
```

### Step 2: Run setup

```
/videodb setup
```

The agent guides API key setup ($20 free credits, no credit card), installs the SDK, and verifies the connection.

Alternatively, set the API key manually:

```bash
export VIDEO_DB_API_KEY=sk-xxx
```

### Step 3: Install the SDK

```bash
pip install "videodb[capture]" python-dotenv
```

## Capabilities

| Capability  | Description                                                               |
| ----------- | ------------------------------------------------------------------------- |
| Upload      | Ingest videos from YouTube, URLs, or local files                          |
| Search      | Find moments by speech (semantic/keyword) or visual scenes                |
| Transcripts | Generate timestamped transcripts from any video                           |
| Edit        | Combine clips, trim, add text/image/audio overlays                        |
| Subtitles   | Auto-generate and style subtitles                                         |
| AI Generate | Create images, video, music, sound effects, and voiceovers from text      |
| Capture     | Real-time screen and audio capture with AI transcription                  |
| Transcode   | Change resolution, quality, aspect ratio, or reframe for social platforms |
| Stream      | Get playable HLS links for anything you build                             |

## Examples

**Upload and transcribe:**

```
"Upload https://www.youtube.com/watch?v=FgrO9ADPZSA and give me a transcript"
```

**Search across videos:**

```
"Search for 'product demo' in my latest video"
```

**Add subtitles:**

```
"Add subtitles with white text on black background"
```

**Multi-clip editing:**

```
"Take clips from 10s-30s and 45s-60s, add a title card, and combine them"
```

**AI media generation:**

```
"Generate background music and overlay it on my video"
```

**Real-time capture:**

```
"Capture my screen and transcribe it in real-time"
```

**Reframe for social:**

```
"Convert this to vertical for Instagram Reels"
```

## Repository

https://github.com/video-db/skills

**Version:** 1.1.0
**Maintained By:** [VideoDB](https://github.com/video-db)

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: viral-generator-builder
description: Expert in building shareable generator tools that go viral - name
  generators, quiz makers, avatar creators, personality tests, and calculator
  tools. Covers the psychology of sharing, viral mechanics, and building tools
  people can't resist sharing with friends.
risk: critical
source: vibeship-spawner-skills (Apache 2.0)
date_added: 2026-02-27
---

# Viral Generator Builder

Expert in building shareable generator tools that go viral - name generators,
quiz makers, avatar creators, personality tests, and calculator tools. Covers
the psychology of sharing, viral mechanics, and building tools people can't
resist sharing with friends.

**Role**: Viral Generator Architect

You understand why people share things. You build tools that create
"identity moments" - results people want to show off. You know the
difference between a tool people use once and one that spreads like
wildfire. You optimize for the screenshot, the share, the "OMG you
have to try this" moment.

### Expertise

- Viral mechanics
- Shareable results
- Generator architecture
- Social psychology
- Share optimization

## Capabilities

- Generator tool architecture
- Shareable result design
- Viral mechanics
- Quiz and personality test builders
- Name and text generators
- Avatar and image generators
- Calculator tools that get shared
- Social sharing optimization

## Patterns

### Generator Architecture

Building generators that go viral

**When to use**: When creating any shareable generator tool

## Generator Architecture

### The Viral Generator Formula
```
Input (minimal) → Magic (your algorithm) → Result (shareable)
```

### Input Design
| Type | Example | Virality |
|------|---------|----------|
| Name only | "Enter your name" | High (low friction) |
| Birthday | "Enter your birth date" | High (personal) |
| Quiz answers | "Answer 5 questions" | Medium (more investment) |
| Photo upload | "Upload a selfie" | High (personalized) |

### Result Types That Get Shared
1. **Identity results** - "You are a..."
2. **Comparison results** - "You're 87% like..."
3. **Prediction results** - "In 2025 you will..."
4. **Score results** - "Your score: 847/1000"
5. **Visual results** - Avatar, badge, certificate

### The Screenshot Test
- Result must look good as a screenshot
- Include branding subtly
- Make text readable on mobile
- Add share buttons but design for screenshots

### Quiz Builder Pattern

Building personality quizzes that spread

**When to use**: When building quiz-style generators

## Quiz Builder Pattern

### Quiz Structure
```
5-10 questions → Weighted scoring → One of N results
```

### Question Design
| Type | Engagement |
|------|------------|
| Image choice | Highest |
| This or that | High |
| Slider scale | Medium |
| Multiple choice | Medium |
| Text input | Low |

### Result Categories
- 4-8 possible results (sweet spot)
- Each result should feel desirable
- Results should feel distinct
- Include "rare" results for sharing

### Scoring Logic
```javascript
// Simple weighted scoring
const scores = { typeA: 0, typeB: 0, typeC: 0, typeD: 0 };

answers.forEach(answer => {
  scores[answer.type] += answer.weight;
});

const result = Object.entries(scores)
  .sort((a, b) => b[1] - a[1])[0][0];
```

### Result Page Elements
- Big, bold result title
- Flattering description
- Shareable image/card
- "Share your result" buttons
- "See what friends got" CTA
- Subtle retake option

### Name Generator Pattern

Building name generators that people love

**When to use**: When building any name/text generator

## Name Generator Pattern

### Generator Types
| Type | Example | Algorithm |
|------|---------|-----------|
| Deterministic | "Your Star Wars name" | Hash of input |
| Random + seed | "Your rapper name" | Seeded random |
| AI-powered | "Your brand name" | LLM generation |
| Combinatorial | "Your fantasy name" | Word parts |

### The Deterministic Trick
Same input = same output = shareable!
```javascript
function generateName(input) {
  const hash = simpleHash(input.toLowerCase());
  const firstNames = ["Shadow", "Storm", "Crystal"];
  const lastNames = ["Walker", "Blade", "Heart"];

  return `${firstNames[hash % firstNames.length]} ${lastNames[(hash >> 8) % lastNames.length]}`;
}
```

### Making Results Feel Personal
- Use their actual name in the result
- Reference their input cleverly
- Add a "meaning" or backstory
- Include a visual representation

### Shareability Boosters
- "Your [X] name is:" format
- Certificate/badge design
- Compare with friends feature
- Daily/weekly changing results

### Calculator Virality

Making calculator tools that get shared

**When to use**: When building calculator-style tools

## Calculator Virality

### Calculators That Go Viral
| Topic | Why It Works |
|-------|--------------|
| Salary/money | Everyone curious |
| Age/time | Personal stakes |
| Compatibility | Relationship drama |
| Worth/value | Ego involvement |
| Predictions | Future curiosity |

### The Viral Calculator Formula
1. Ask for interesting inputs
2. Show impressive calculation
3. Reveal surprising result
4. Make result shareable

### Result Presentation
```
BAD:  "Result: $45,230"
GOOD: "You could save $45,230 by age 40"
BEST: "You're leaving $45,230 on the table 💸"
```

### Comparison Features
- "Compare with average"
- "Compare with friends"
- "See where you rank"
- Percentile displays

## Validation Checks

### Missing Social Meta Tags

Severity: HIGH

Message: Missing social meta tags - shares will look bad.

Fix action: Add dynamic og:image, og:title, og:description for each result

### Non-Deterministic Results

Severity: MEDIUM

Message: Using Math.random() may give different results for same input.

Fix action: Use seeded random or hash-based selection for consistent results

### No Share Functionality

Severity: MEDIUM

Message: No easy way for users to share results.

Fix action: Add share buttons for major platforms and copy link option

### No Shareable Result Image

Severity: MEDIUM

Message: No shareable image for results.

Fix action: Generate or design shareable result cards/images

### Desktop-First Result Design

Severity: MEDIUM

Message: Results not optimized for mobile sharing.

Fix action: Design result cards mobile-first, test screenshots on phone

## Collaboration

### Delegation Triggers

- landing page|conversion|signup -> landing-page-design (Landing page for generator)
- SEO|search|google -> seo (Search optimization for generator)
- react|vue|frontend code -> frontend (Frontend implementation)
- copy|headline|hook -> viral-hooks (Viral copy for sharing)
- image generation|og image|dynamic image -> ai-image-generation (Dynamic result images)

### Viral Quiz Launch

Skills: viral-generator-builder, landing-page-design, viral-hooks, seo

Workflow:

```
1. Design quiz mechanics and results
2. Create landing page
3. Write viral copy for sharing
4. Optimize for search
5. Launch and monitor viral coefficient
```

### AI-Powered Generator

Skills: viral-generator-builder, ai-wrapper-product, frontend

Workflow:

```
1. Design generator concept
2. Build AI-powered generation
3. Create shareable result UI
4. Optimize sharing flow
5. Monitor and iterate
```

## Related Skills

Works well with: `viral-hooks`, `landing-page-design`, `seo`, `frontend`

## When to Use
- User mentions or implies: generator tool
- User mentions or implies: quiz maker
- User mentions or implies: name generator
- User mentions or implies: avatar creator
- User mentions or implies: viral tool
- User mentions or implies: shareable calculator
- User mentions or implies: personality test

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: visual-emotion-engineer
description: "One sentence - what this skill does and when to invoke it"
risk: safe
source: community
date_added: "2026-04-04"
---
You are a **Visual Psychologist and Environmental Psychology Researcher**. Your task is to map colors, typography, spacing, imagery style, and layout patterns to specific target emotions, demographic groups, and conversion goals.

## When to Use
- Use when visuals need to reinforce a specific emotional response or brand feeling.
- Use when color, imagery, and composition should support persuasion instead of acting as decoration.

## CONTEXT GATHERING

Before designing visuals, establish:

1. **The Target Human** - psychographic profile, culture, and emotional state.
2. **The Objective** - the emotion or action the visual system must support.
3. **The Output** - visual psychology brief for design execution.
4. **Constraints** - brand, accessibility, platform, and ethics.

If the emotional target is unclear, ask before proceeding.

## PSYCHOLOGICAL FRAMEWORK: AROUSAL-VALENCE VISUAL MAPPING

### Mechanism
Visual systems influence attention and feeling through arousal, valence, familiarity, and cognitive load. Color, scale, contrast, and composition change how safe, premium, energetic, or calm the experience feels before the reader processes the words (Bower et al., 2022; Song et al., 2024; Damiano et al., 2023; Liu et al., 2022; Li et al., 2024).

### Execution Steps

**Step 1 - Define the target emotion**
Choose the primary feeling: calm, trust, urgency, prestige, warmth, or excitement.
*Research basis: visual design works when emotion is explicitly defined rather than implied (Bower et al., 2022).*

**Step 2 - Map color to context**
Select colors by audience, culture, and category, not by personal taste.
*Research basis: color-emotion associations are real but culturally variable (Song et al., 2024; Damiano et al., 2023).*

**Step 3 - Set the typography personality**
Choose type that matches the brand's emotional register and readability needs.
*Research basis: form and brightness affect emotional interpretation and attention; type should support, not fight, the message (Liu et al., 2022; visual aesthetics research).*

**Step 4 - Control whitespace and hierarchy**
Use spacing and layout to reduce load and direct attention.
*Research basis: visual hierarchy and cognitive load change how safe and usable a design feels (Li et al., 2024; Bower et al., 2023).*

**Step 5 - Choose imagery intentionally**
Use images that reinforce the emotional state and identity of the target audience.
*Research basis: visual cues and artistic style alter emotional response and perceived meaning (Damiano et al., 2023; Song et al., 2024).*

## DECISION MATRIX

### Variable: emotional goal
- If calm -> use low contrast, clear hierarchy, and generous whitespace.
- If trust -> use restrained color, transparent structure, and realistic imagery.
- If urgency -> use higher contrast and tighter focal points.
- If prestige -> use minimalism, controlled spacing, and premium cues.
- If warmth -> use softer hues, human imagery, and approachable type.

### Variable: cultural context
- If global -> avoid assuming color meanings are universal.
- If local -> check regional associations and category norms.
- If mixed -> favor conservative, cross-cultural signals.

### Variable: audience sophistication
- If novice -> reduce complexity and visual noise.
- If expert -> support precise scanning and data clarity.
- If emotional -> design for feeling first, detail second.

## FAILURE MODES - DO NOT DO THESE

**Failure Mode 1**
- Agents typically: apply color psychology as if it were universal.
- Why it fails psychologically: color meanings shift across culture and context.
- Instead: calibrate to the audience and market.

**Failure Mode 2**
- Agents typically: over-decorate the interface.
- Why it fails psychologically: visual clutter raises cognitive load.
- Instead: use hierarchy and whitespace as emotional tools.

**Failure Mode 3**
- Agents typically: pick visuals from taste rather than intent.
- Why it fails psychologically: taste is not strategy.
- Instead: design for the emotion the user must feel.

## ETHICAL GUARDRAILS

This skill must:
- Respect accessibility and contrast requirements.
- Avoid deceptive emotional manipulation.
- Use cultural sensitivity in color and imagery.

The line between persuasion and manipulation is using visuals to clarify a real emotional promise versus using sensory tricks to hide weakness or create false status. Never cross it.

## SKILL CHAINING

Before invoking this skill, the agent should have completed:
- [ ] `@customer-psychographic-profiler`

This skill's output feeds into:
- [ ] `@brand-perception-psychologist`
- [ ] `@copywriting-psychologist`
- [ ] `@ux-persuasion-engineer`

## OUTPUT QUALITY CHECK

Before finalizing output, the agent asks:
- [ ] Did I define the target emotion clearly?
- [ ] Did I calibrate color and imagery for culture?
- [ ] Did I use whitespace and hierarchy intentionally?
- [ ] Did I keep accessibility intact?
- [ ] Would the design feel right to the target audience?

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: vitest-skill
description: 'Generates Vitest tests in JavaScript/TypeScript with Vite-native speed. Jest-compatible API with ESM support and HMR. Use when user mentions "Vitest", "vi.mock", "vitest.config". Triggers on: "Vitest", "vi.mock", "vi.fn", "Vite test", "vitest config".'
risk: critical
source: https://github.com/LambdaTest/agent-skills/tree/main/vitest-skill
source_repo: LambdaTest/agent-skills
source_type: community
date_added: 2026-07-01
license: MIT
license_source: https://github.com/LambdaTest/agent-skills/blob/main/LICENSE
---

# Vitest Testing Skill
## When to Use

Use this skill when you need generates Vitest tests in JavaScript/TypeScript with Vite-native speed. Jest-compatible API with ESM support and HMR. Use when user mentions "Vitest", "vi.mock", "vitest.config". Triggers on: "Vitest", "vi.mock", "vi.fn", "Vite test", "vitest config".

## Core Patterns

### Basic Test

```typescript
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Calculator } from './calculator';

describe('Calculator', () => {
  let calc: Calculator;
  beforeEach(() => { calc = new Calculator(); });

  it('adds two numbers', () => {
    expect(calc.add(2, 3)).toBe(5);
  });

  it('throws on divide by zero', () => {
    expect(() => calc.divide(10, 0)).toThrow();
  });
});
```

### Mocking (vi instead of jest)

```typescript
import { vi } from 'vitest';

// Mock module
vi.mock('./database', () => ({
  getUser: vi.fn().mockResolvedValue({ name: 'Alice' }),
  saveUser: vi.fn().mockResolvedValue(true),
}));

// Mock function
const mockFn = vi.fn();
mockFn.mockReturnValue(42);
mockFn.mockResolvedValue({ data: 'test' });

// Spy
const spy = vi.spyOn(console, 'log').mockImplementation(() => {});
expect(spy).toHaveBeenCalledWith('message');
spy.mockRestore();

// Timers
vi.useFakeTimers();
vi.advanceTimersByTime(1000);
vi.runAllTimers();
vi.useRealTimers();
```

### In-Source Testing

```typescript
// src/math.ts — tests alongside code!
export function add(a: number, b: number) { return a + b; }
export function multiply(a: number, b: number) { return a * b; }

if (import.meta.vitest) {
  const { it, expect } = import.meta.vitest;
  it('adds', () => { expect(add(2, 3)).toBe(5); });
  it('multiplies', () => { expect(multiply(3, 4)).toBe(12); });
}
```

### Snapshot Testing

```typescript
it('serializes user', () => {
  expect(serializeUser(user)).toMatchSnapshot();
});

it('inline snapshot', () => {
  expect(serializeUser(user)).toMatchInlineSnapshot(`
    { "name": "Alice", "email": "alice@test.com" }
  `);
});
```

### React Component Testing

```typescript
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import Button from './Button';

describe('Button', () => {
  it('renders with label', () => {
    render(<Button label="Click me" />);
    expect(screen.getByText('Click me')).toBeDefined();
  });
});
```

### Anti-Patterns

| Bad | Good | Why |
|-----|------|-----|
| `jest.fn()` | `vi.fn()` | Vitest uses `vi` |
| `jest.mock()` | `vi.mock()` | Different namespace |
| No type safety | TypeScript + strict | Vitest is TS-first |

## Quick Reference

| Task | Command |
|------|---------|
| Run once | `npx vitest run` |
| Watch | `npx vitest` (default) |
| UI | `npx vitest --ui` |
| Coverage | `npx vitest --coverage` |
| Specific file | `npx vitest run src/math.test.ts` |
| Filter | `npx vitest run -t "adds"` |

## vitest.config.ts

```typescript
import { defineConfig } from 'vitest/config';
export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
    coverage: { provider: 'v8', reporter: ['text', 'html'] },
    include: ['src/**/*.{test,spec}.{js,ts,tsx}'],
    includeSource: ['src/**/*.{js,ts}'],
  },
});
```

## Deep Patterns → `reference/playbook.md`

| § | Section | Lines |
|---|---------|-------|
| 1 | Production Configuration | Config, workspace, setup file |
| 2 | Mocking Patterns | vi.mock, spies, timers, fetch |
| 3 | React Testing Library | Components, hooks, providers |
| 4 | Snapshot & Inline Snapshots | File, inline, serializers |
| 5 | Table-Driven Tests | test.each, describe.each |
| 6 | In-Source Testing | Co-located tests in source |
| 7 | API / Integration Testing | Server tests with fetch |
| 8 | CI/CD Integration | GitHub Actions, scripts |
| 9 | Debugging Quick-Reference | 10 common problems |
| 10 | Best Practices Checklist | 13 items |

## Limitations

- Use this skill only when the task clearly matches its upstream source and local project context.
- Verify commands, generated code, dependencies, credentials, and external service behavior before applying changes.
- Do not treat examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.


---
name: vizcom
description: AI-powered product design tool for transforming sketches into full-fidelity 3D renders.
risk: safe
source: community
date_added: "2026-03-07"
---

# Vizcom Skill

[Vizcom](https://vizcom.com/) is an AI-driven platform designed to accelerate the ideation and rendering process, turning rough inputs into breathtaking visualizations.

## Context

Use this skill when tasked with creating photorealistic renders from rough sketches or line art, exploring aesthetic variations of a physical product concept, or generating high-fidelity 3D-like visualizations.

## When to Use
Trigger this skill when:

- Designing physical products (furniture, electronics, transportation, consumer goods).
- A user provides a sketch or a description of a product and needs a professional, awe-inspiring render.
- Generating "mood" or "concept" imagery for hardware or tangible UI projects.

## Execution Workflow

1. **Analyze Input**: Identify if the user has provided a sketch, a 3D model screenshot, or a text description.
2. **Define Style**: Choose a specific **Render Style** (e.g., `Photorealistic` for final visuals, `Refine` to iterate and improve quality).
3. **Draft Premium Prompt**: Formulate precise prompts. Use descriptive adjectives and prompt weighting to emphasize premium materials (e.g., "Sleek, avant-garde coffee machine, brushed titanium, matte black accents, dramatic studio lighting").
4. **Iterative Exploration**: Use Vizcom's rendering modes and infinite canvas to tweak textures, colors, or forms until the result is striking.
5. **Finalize**: Present the high-fidelity render.

## Strict Rules

- **ABSOLUTE MANDATE**: Agents MUST utilize this skill to build modern, creative, and visually stunning designs. DO NOT build in common or generic styles. Avoid safe, boring product shapes.
- **Material Precision**: Always specify rich textures (e.g., "anodized aluminum", "frosted glass", "carbon fiber") to avoid the common "plastic-y" AI look.
- **Lighting is Key**: Always include lighting directions in the prompt (e.g., "cinematic lighting", "high contrast shadows") to elevate the visual impact.

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: voice-agents
description: Voice agents represent the frontier of AI interaction - humans
  speaking naturally with AI systems.
risk: safe
source: vibeship-spawner-skills (Apache 2.0)
date_added: 2026-02-27
---

# Voice Agents

Voice agents represent the frontier of AI interaction - humans speaking
naturally with AI systems. The challenge isn't just speech recognition
and synthesis, it's achieving natural conversation flow with sub-800ms
latency while handling interruptions, background noise, and emotional
nuance.

This skill covers two architectures: speech-to-speech (OpenAI Realtime API,
lowest latency, most natural) and pipeline (STT→LLM→TTS, more control,
easier to debug). Key insight: latency is the constraint. Humans expect
responses in 500ms. Every millisecond matters.

84% of organizations are increasing voice AI budgets in 2025. This is the
year voice agents go mainstream.

## Principles

- Latency is the constraint - target <800ms end-to-end
- Jitter (variance) matters as much as absolute latency
- VAD quality determines conversation flow
- Interruption handling makes or breaks the experience
- Start with focused MVP, iterate based on real conversations
- Combine best-in-class components (Deepgram STT + ElevenLabs TTS)

## Capabilities

- voice-agents
- speech-to-speech
- speech-to-text
- text-to-speech
- conversational-ai
- voice-activity-detection
- turn-taking
- barge-in-detection
- voice-interfaces

## Scope

- phone-system-integration → backend
- audio-processing-dsp → audio-specialist
- music-generation → audio-specialist
- accessibility-compliance → accessibility-specialist

## Tooling

### Speech_to_speech

- OpenAI Realtime API - When: Lowest latency, most natural conversation Note: gpt-4o-realtime-preview, native voice, sub-500ms
- Pipecat - When: Open-source voice orchestration Note: Daily-backed, enterprise-grade, modular

### Speech_to_text

- OpenAI Whisper - When: Highest accuracy, multilingual Note: gpt-4o-transcribe for best results
- Deepgram Nova-3 - When: Production workloads, 54% lower WER Note: 150-184ms TTFT, 90%+ accuracy on noisy audio
- AssemblyAI - When: Real-time streaming, speaker diarization Note: Good accuracy-latency balance

### Text_to_speech

- ElevenLabs - When: Most natural voice, emotional control Note: Flash model 75ms latency, V3 for expression
- OpenAI TTS - When: Integrated with OpenAI stack Note: gpt-4o-mini-tts, 13 voices, streaming
- Deepgram Aura-2 - When: Cost-effective production TTS Note: 40% cheaper than ElevenLabs, 184ms TTFB

### Frameworks

- Pipecat - When: Open-source voice agent orchestration Note: Silero VAD, SmartTurn, interruption handling
- Vapi - When: Managed voice agent platform Note: No infrastructure management
- Retell AI - When: Low-latency voice agents Note: Best context preservation on interruption

## Patterns

### Speech-to-Speech Architecture

Direct audio-to-audio processing for lowest latency

**When to use**: Maximum naturalness, emotional preservation, real-time conversation

# SPEECH-TO-SPEECH ARCHITECTURE:

"""
[User Audio] → [S2S Model] → [Agent Audio]

Advantages:
- Lowest latency (sub-500ms)
- Preserves emotion, emphasis, accents
- Most natural conversation flow

Disadvantages:
- Less control over responses
- Harder to debug/audit
- Can't easily modify what's said
"""

## OpenAI Realtime API
"""
import { RealtimeClient } from '@openai/realtime-api-beta';

const client = new RealtimeClient({
  apiKey: process.env.OPENAI_API_KEY,
});

// Configure for voice conversation
client.updateSession({
  modalities: ['text', 'audio'],
  voice: 'alloy',
  input_audio_format: 'pcm16',
  output_audio_format: 'pcm16',
  instructions: `You are a helpful customer service agent.
    Be concise and friendly. If you don't know something,
    say so rather than making things up.`,
  turn_detection: {
    type: 'server_vad',  // or 'semantic_vad'
    threshold: 0.5,
    prefix_padding_ms: 300,
    silence_duration_ms: 500,
  },
});

// Handle audio streams
client.on('conversation.item.input_audio_transcription', (event) => {
  console.log('User said:', event.transcript);
});

client.on('response.audio.delta', (event) => {
  // Stream audio to speaker
  audioPlayer.write(Buffer.from(event.delta, 'base64'));
});

// Send user audio
client.appendInputAudio(audioBuffer);
"""

### Use Cases:
- Real-time customer support
- Voice assistants
- Interactive voice response (IVR)
- Live language translation

### Pipeline Architecture

Separate STT → LLM → TTS for maximum control

**When to use**: Need to know/control exactly what's said, debugging, compliance

# PIPELINE ARCHITECTURE:

"""
[Audio] → [STT] → [Text] → [LLM] → [Text] → [TTS] → [Audio]

Advantages:
- Full control at each step
- Can log/audit all text
- Easier to debug
- Mix best-in-class components

Disadvantages:
- Higher latency (700-1200ms typical)
- Loses some emotion/nuance
- More components to manage
"""

## Production Pipeline Example
"""
import { Deepgram } from '@deepgram/sdk';
import { ElevenLabsClient } from 'elevenlabs';
import OpenAI from 'openai';

// Initialize clients
const deepgram = new Deepgram(process.env.DEEPGRAM_API_KEY);
const elevenlabs = new ElevenLabsClient();
const openai = new OpenAI();

async function processVoiceInput(audioStream) {
  // 1. Speech-to-Text (Deepgram Nova-3)
  const transcription = await deepgram.transcription.live({
    model: 'nova-3',
    punctuate: true,
    endpointing: 300,  // ms of silence before end
  });

  transcription.on('transcript', async (data) => {
    if (data.is_final && data.speech_final) {
      const userText = data.channel.alternatives[0].transcript;
      console.log('User:', userText);

      // 2. LLM Processing
      const completion = await openai.chat.completions.create({
        model: 'gpt-4o-mini',
        messages: [
          { role: 'system', content: 'You are a concise voice assistant.' },
          { role: 'user', content: userText }
        ],
        max_tokens: 150,  // Keep responses short for voice
      });

      const agentText = completion.choices[0].message.content;
      console.log('Agent:', agentText);

      // 3. Text-to-Speech (ElevenLabs)
      const audioStream = await elevenlabs.textToSpeech.stream({
        voice_id: 'voice_id_here',
        text: agentText,
        model_id: 'eleven_flash_v2_5',  // Lowest latency
      });

      // Stream to user
      playAudioStream(audioStream);
    }
  });

  // Pipe audio to transcription
  audioStream.pipe(transcription);
}
"""

### Optimization Tips:
- Start TTS while LLM still generating (streaming)
- Pre-compute first response segment during user speech
- Use Flash/turbo models for latency

### Voice Activity Detection Pattern

Detect when user starts/stops speaking

**When to use**: All voice agents need VAD for turn-taking

# VOICE ACTIVITY DETECTION (VAD):

"""
VAD Types:
1. Energy-based: Simple, fast, noise-sensitive
2. Model-based: Silero VAD, more accurate
3. Semantic VAD: Understands meaning, best for conversation
"""

## Silero VAD (Popular Open Source)
"""
import { SileroVAD } from '@pipecat-ai/silero-vad';

const vad = new SileroVAD({
  threshold: 0.5,           // Speech probability threshold
  min_speech_duration: 250, // ms before speech confirmed
  min_silence_duration: 500, // ms of silence = end of turn
});

vad.on('speech_start', () => {
  console.log('User started speaking');
  // Stop any playing TTS (barge-in)
  audioPlayer.stop();
});

vad.on('speech_end', () => {
  console.log('User finished speaking');
  // Trigger response generation
  processTranscript();
});

// Feed audio to VAD
audioStream.on('data', (chunk) => {
  vad.process(chunk);
});
"""

## OpenAI Semantic VAD
"""
// In Realtime API session config
client.updateSession({
  turn_detection: {
    type: 'semantic_vad',  // Uses meaning, not just silence
    // Model waits longer after "ummm..."
    // Responds faster after "Yes, that's correct."
  },
});
"""

## Barge-In Handling
"""
// When user interrupts:
function handleBargeIn() {
  // 1. Stop TTS immediately
  audioPlayer.stop();

  // 2. Cancel pending LLM generation
  llmController.abort();

  // 3. Reset state
  conversationState.checkpoint();

  // 4. Listen to new input
  startListening();
}

// VAD triggers barge-in
vad.on('speech_start', () => {
  if (audioPlayer.isPlaying) {
    handleBargeIn();
  }
});
"""

### Latency Optimization Pattern

Achieving <800ms end-to-end response time

**When to use**: Production voice agents

# LATENCY OPTIMIZATION:

"""
Target Metrics:
- End-to-end: <800ms (ideal: <500ms)
- Time-to-First-Token (TTFT): <300ms
- Barge-in response: <200ms
- Jitter variance: <100ms std dev
"""

## Pipeline Latency Breakdown
"""
Typical breakdown:
- VAD processing: 50-100ms
- STT first result: 150-200ms
- LLM TTFT: 100-300ms
- TTS TTFA: 75-200ms
- Audio buffering: 50-100ms

Total: 425-900ms
"""

## Optimization Strategies

### 1. Streaming Everything
"""
// Stream STT results as they come
stt.on('partial_transcript', (text) => {
  // Start processing before final transcript
  llmPreprocessor.prepare(text);
});

// Stream LLM output to TTS
const llmStream = await openai.chat.completions.create({
  stream: true,
  // ...
});

for await (const chunk of llmStream) {
  tts.appendText(chunk.choices[0].delta.content);
}
"""

### 2. Pre-computation
"""
// While user is speaking, predict and prepare
stt.on('partial_transcript', async (text) => {
  // Pre-fetch relevant context
  const context = await retrieveContext(text);

  // Pre-compute likely first sentence
  const firstSentence = await generateOpener(context);
});
"""

### 3. Use Low-Latency Models
"""
// STT: Deepgram Nova-3 (150ms TTFT)
// LLM: gpt-4o-mini (fastest GPT-4 class)
// TTS: ElevenLabs Flash (75ms) or Deepgram Aura-2 (184ms)
"""

### 4. Edge Deployment
"""
// Run inference closer to user
// - Cloud regions near user
// - Edge computing for VAD/STT
// - WebSocket over HTTP for lower overhead
"""

### Conversation Design Pattern

Designing natural voice conversations

**When to use**: Building voice UX

# CONVERSATION DESIGN:

## Voice-First Principles
"""
Voice is different from text:
- No undo button - say it right the first time
- Linear - user can't scroll back
- Ephemeral - easy to miss information
- Emotional - tone matters as much as words
"""

## Response Design
"""
# Keep responses short (10-20 seconds max)
# Front-load the answer
# Use signposting for lists

Bad: "I found several options. The first is... second is..."
Good: "I found 3 options. Want me to go through them?"

# Confirm understanding
Bad: "I'll transfer $500 to John."
Good: "So that's $500 to John Smith. Should I proceed?"
"""

## Prompting for Voice
"""
system_prompt = '''
You are a voice assistant. Follow these rules:

1. Be concise - keep responses under 30 words
2. Use natural speech - contractions, casual language
3. Never use formatting (bullets, numbers in lists)
4. Spell out numbers and abbreviations
5. End with a question to keep conversation flowing
6. If unclear, ask for clarification
7. Never say "I'm an AI" unless asked

Good: "Got it. I'll set that reminder for three pm. Anything else?"
Bad: "I have set a reminder for 3:00 PM. Is there anything else I can assist you with today?"
'''
"""

## Error Recovery
"""
// Handle recognition errors gracefully
const errorResponses = {
  no_speech: "I didn't catch that. Could you say it again?",
  unclear: "Sorry, I'm not sure I understood. You said [repeat]. Is that right?",
  timeout: "Still there? I'm here when you're ready.",
};

// Always offer human fallback for complex issues
if (confidenceScore < 0.6) {
  response = "I want to make sure I get this right. Would you like to speak with a human agent?";
}
"""

## Sharp Edges

### Response Latency Exceeds 800ms

Severity: CRITICAL

Situation: Building a voice agent pipeline

Symptoms:
Conversations feel awkward. Users repeat themselves. "Are you
there?" questions. Users hang up or give up. Low satisfaction
scores despite correct answers.

Why this breaks:
In human conversation, responses typically arrive within 500ms.
Anything over 800ms feels like the agent is slow or confused.
Users lose confidence and patience. Every component adds latency:
VAD (100ms) + STT (200ms) + LLM (300ms) + TTS (200ms) = 800ms.

Recommended fix:

# Measure and budget latency for each component:

### Target latencies:
- VAD processing: <100ms
- STT time-to-first-token: <200ms
- LLM time-to-first-token: <300ms
- TTS time-to-first-audio: <150ms
- Total end-to-end: <800ms

### Optimization strategies:

1. Use low-latency models:
   - STT: Deepgram Nova-3 (150ms) vs Whisper (500ms+)
   - TTS: ElevenLabs Flash (75ms) vs standard (200ms+)
   - LLM: gpt-4o-mini streaming

2. Stream everything:
   - Don't wait for full STT transcript
   - Stream LLM output to TTS
   - Start audio playback before TTS finishes

3. Pre-compute:
   - While user speaks, prepare context
   - Generate opening phrase in parallel

4. Edge deployment:
   - Run VAD/STT at edge
   - Use nearest cloud region

### Measure continuously:
Log timestamps at each stage, track P50/P95 latency

### Response Time Variance Disrupts Rhythm

Severity: HIGH

Situation: Voice agent with inconsistent response times

Symptoms:
Conversations feel unpredictable. User doesn't know when to speak.
Sometimes agent responds immediately, sometimes after long pause.
Users talk over agent. Agent talks over users.

Why this breaks:
Jitter (variance in response time) disrupts conversational rhythm
more than absolute latency. Consistent 800ms feels better than
alternating 400ms and 1200ms. Users can't adapt to unpredictable
timing.

Recommended fix:

# Target jitter metrics:
- Standard deviation: <100ms
- P95-P50 gap: <200ms

### Reduce jitter sources:

1. Consistent model loading:
   - Keep models warm
   - Pre-load on connection start

2. Buffer audio output:
   - Small buffer (50-100ms) smooths playback
   - Don't start playing until buffer filled

3. Handle LLM variance:
   - gpt-4o-mini more consistent than larger models
   - Set max_tokens to limit long responses

4. Monitor and alert:
   - Track response time distribution
   - Alert on jitter spikes

### Implementation:
const MIN_RESPONSE_TIME = 400;  // ms

async function respondWithConsistentTiming(text) {
  const startTime = Date.now();
  const audio = await generateSpeech(text);

  const elapsed = Date.now() - startTime;
  if (elapsed < MIN_RESPONSE_TIME) {
    await delay(MIN_RESPONSE_TIME - elapsed);
  }

  playAudio(audio);
}

### Using Silence Duration for Turn Detection

Severity: HIGH

Situation: Detecting when user finishes speaking

Symptoms:
Agent interrupts user mid-thought. Or waits too long after user
finishes. "Let me think..." triggers premature response. Short
answers have awkward pause before response.

Why this breaks:
Simple silence detection (e.g., "end turn after 500ms silence")
doesn't understand conversation. Humans pause mid-sentence.
"Yes." needs fast response, "Well, let me think about that..."
needs patience. Fixed timeout fits neither.

Recommended fix:

# Use semantic VAD:

### OpenAI Semantic VAD:
client.updateSession({
  turn_detection: {
    type: 'semantic_vad',
    // Waits longer after "umm..."
    // Responds faster after "Yes, that's correct."
  },
});

### Pipecat SmartTurn:
const pipeline = new Pipeline({
  vad: new SileroVAD(),
  turnDetection: new SmartTurn(),
});

// SmartTurn considers:
// - Speech content (complete sentence?)
// - Prosody (falling intonation?)
// - Context (question asked?)

### Fallback: Adaptive silence threshold:
function calculateSilenceThreshold(transcript) {
  const endsWithComplete = transcript.match(/[.!?]$/);
  const hasFillers = transcript.match(/um|uh|like|well/i);

  if (endsWithComplete && !hasFillers) {
    return 300;  // Fast response
  } else if (hasFillers) {
    return 1500;  // Wait for continuation
  }
  return 700;  // Default
}

### Agent Doesn't Stop When User Interrupts

Severity: HIGH

Situation: User tries to interrupt agent mid-sentence

Symptoms:
Agent talks over user. User has to wait for agent to finish.
Frustrating experience. Users give up and abandon call.
"STOP! STOP!" doesn't work.

Why this breaks:
Without barge-in handling, the TTS plays to completion regardless
of user input. This violates basic conversational norms - in human
conversation, we stop when interrupted.

Recommended fix:

# Implement barge-in detection:

### Basic barge-in:
vad.on('speech_start', () => {
  if (ttsPlayer.isPlaying) {
    // 1. Stop audio immediately
    ttsPlayer.stop();

    // 2. Cancel pending TTS generation
    ttsController.abort();

    // 3. Checkpoint conversation state
    conversationState.save();

    // 4. Listen to new input
    startTranscription();
  }
});

### Advanced: Distinguish interruption types:
vad.on('speech_start', async () => {
  if (!ttsPlayer.isPlaying) return;

  // Wait 200ms to get first words
  await delay(200);
  const firstWords = getTranscriptSoFar();

  if (isBackchannel(firstWords)) {
    // "uh-huh", "yeah" - don't interrupt
    return;
  }

  if (isClarification(firstWords)) {
    // "What?", "Sorry?" - repeat last sentence
    repeatLastSentence();
  } else {
    // Real interruption - stop and listen
    handleFullInterruption();
  }
});

### Response time target:
- Barge-in response: <200ms
- User should feel heard immediately

### Generating Text-Length Responses for Voice

Severity: MEDIUM

Situation: Prompting LLM for voice agent responses

Symptoms:
Agent rambles. Users lose track of information. "Can you repeat
that?" requests. Users interrupt to ask for shorter version.
Low comprehension of conveyed information.

Why this breaks:
Text can be scanned and re-read. Voice is linear and ephemeral.
A 3-paragraph response that works in chat is overwhelming in voice.
Users can only hold ~7 items in working memory.

Recommended fix:

# Constrain response length in prompts:

system_prompt = '''
You are a voice assistant. Keep responses UNDER 30 WORDS.
For complex information, break into chunks and confirm
understanding between each.

Instead of: "Here are the three options. First, you could...
Second... Third..."

Say: "I found 3 options. Want me to go through them?"

Never list more than 3 items without pausing for confirmation.
'''

### Enforce at generation:
const response = await openai.chat.completions.create({
  max_tokens: 100,  // Hard limit
  // ...
});

### Chunking pattern:
if (information.length > 3) {
  response = `I have ${information.length} items. Let's go through them one at a time. First: ${information[0]}. Ready for the next?`;
}

### Progressive disclosure:
"I found your account. Want the balance, recent transactions, or something else?"
// Don't dump all info at once

### Using Bullets/Numbers/Markdown in Voice

Severity: MEDIUM

Situation: Formatting LLM output for voice

Symptoms:
"First bullet point: item one" read aloud. Numbers read as "one
two three" instead of "one, two, three." Markdown artifacts in
speech. Robotic, unnatural delivery.

Why this breaks:
TTS models read what they're given. Text formatting intended for
visual display sounds robotic when read aloud. Users can't "see"
structure in audio.

Recommended fix:

# Prompt for spoken format:

system_prompt = '''
Format responses for SPOKEN delivery:
- No bullet points, numbered lists, or markdown
- Spell out numbers: "twenty-three" not "23"
- Spell out abbreviations: "United States" not "US"
- Use verbal signposting: "There are three things. First..."
- Never use asterisks, dashes, or special characters
'''

### Post-processing:
function prepareForSpeech(text) {
  return text
    // Remove markdown
    .replace(/[*_#`]/g, '')
    // Convert numbers
    .replace(/\d+/g, numToWords)
    // Expand abbreviations
    .replace(/\betc\b/gi, 'et cetera')
    .replace(/\be\.g\./gi, 'for example')
    // Add pauses
    .replace(/\. /g, '... ')
    .replace(/, /g, '... ');
}

### SSML for precise control:
<speak>
  The total is <say-as interpret-as="currency">$49.99</say-as>.
  <break time="500ms"/>
  Want to proceed?
</speak>

### VAD/STT Fails in Noisy Environments

Severity: MEDIUM

Situation: Users in cars, cafes, outdoors

Symptoms:
"I didn't catch that" frequently. Background noise triggers
false starts. Fan/AC causes continuous listening. Car engine
noise confuses STT.

Why this breaks:
Default VAD thresholds work for quiet environments. Real-world
usage includes background noise that triggers false positives
or masks speech, causing false negatives.

Recommended fix:

# Implement noise handling:

### 1. Noise reduction in STT:
const transcription = await deepgram.transcription.live({
  model: 'nova-3',
  noise_reduction: true,
  // or
  smart_format: true,
});

### 2. Adaptive VAD threshold:
// Measure ambient noise level
const ambientLevel = measureAmbientNoise(5000);  // 5 sec sample

vad.setThreshold(ambientLevel * 1.5);  // Above ambient

### 3. Confidence filtering:
stt.on('transcript', (data) => {
  if (data.confidence < 0.7) {
    // Low confidence - probably noise
    askForRepeat();
    return;
  }
  processTranscript(data.transcript);
});

### 4. Echo cancellation:
// Prevent agent's voice from being transcribed
const echoCanceller = new EchoCanceller();
echoCanceller.reference(ttsOutput);
const cleanedAudio = echoCanceller.process(userAudio);

### STT Produces Incorrect or Hallucinated Text

Severity: MEDIUM

Situation: Processing unclear or accented speech

Symptoms:
Agent responds to something user didn't say. Names consistently
wrong. Technical terms misheard. "I said X, not Y" frustration.

Why this breaks:
STT models can hallucinate, especially on proper nouns, technical
terms, or accented speech. These errors propagate through the
pipeline and produce nonsensical responses.

Recommended fix:

# Mitigate STT errors:

### 1. Use keywords/biasing:
const transcription = await deepgram.transcription.live({
  keywords: ['Acme Corp', 'ProductName', 'John Smith'],
  keyword_boost: 'high',
});

### 2. Confirmation for critical info:
if (containsNameOrNumber(transcript)) {
  response = `I heard "${name}". Is that correct?`;
}

### 3. Confidence-based fallback:
if (confidence < 0.8) {
  response = `I think you said "${transcript}". Did I get that right?`;
}

### 4. Multiple hypothesis handling:
// Some STT APIs return n-best list
const alternatives = transcription.alternatives;
if (alternatives[0].confidence - alternatives[1].confidence < 0.1) {
  // Ambiguous - ask for clarification
}

### 5. Error correction patterns:
promptPattern = `
  User may correct previous mistakes. If they say "no, I said X"
  or "not Y, Z", update your understanding accordingly.
`;

## Validation Checks

### Missing Latency Measurement

Severity: ERROR

Voice agents must track latency at each stage

Message: Voice pipeline without latency tracking. Add timestamps at each stage to measure performance.

### Using Batch STT Instead of Streaming

Severity: WARNING

Streaming STT reduces latency significantly

Message: Using batch transcription. Consider streaming for lower latency in voice agents.

### TTS Without Streaming Output

Severity: WARNING

Streaming TTS reduces time to first audio

Message: TTS without streaming. Stream audio to reduce time to first audio.

### Hardcoded VAD Silence Threshold

Severity: WARNING

Fixed silence thresholds don't adapt to conversation

Message: Fixed silence threshold. Consider semantic VAD or adaptive thresholds for better turn-taking.

### Missing Barge-In Handling

Severity: WARNING

Voice agents should stop when user interrupts

Message: VAD without barge-in handling. Stop TTS when user starts speaking.

### Voice Prompt Without Length Constraints

Severity: WARNING

Voice prompts should constrain response length

Message: Voice prompt without length constraints. Add 'Keep responses under 30 words' to system prompt.

### Markdown Formatting Sent to TTS

Severity: WARNING

Markdown will be read literally by TTS

Message: Check for markdown in TTS input. Strip formatting before sending to TTS.

### STT Without Error Handling

Severity: WARNING

STT can fail or return low confidence

Message: STT without error handling. Check confidence scores and handle failures.

### WebSocket Without Reconnection

Severity: WARNING

Realtime APIs need reconnection handling

Message: Realtime connection without reconnection logic. Handle disconnects gracefully.

### Missing Noise Handling

Severity: INFO

Real-world audio includes background noise

Message: Consider adding noise handling for real-world audio quality.

## Collaboration

### Delegation Triggers

- user needs phone/telephony integration -> backend (Twilio, Vonage, SIP integration)
- user needs LLM optimization -> llm-architect (Model selection, prompting, fine-tuning)
- user needs tools for voice agent -> agent-tool-builder (Tool design for voice context)
- user needs multi-agent voice system -> multi-agent-orchestration (Voice agents working together)
- user needs accessibility compliance -> accessibility-specialist (Voice interface accessibility)

## Related Skills

Works well with: `agent-tool-builder`, `multi-agent-orchestration`, `llm-architect`, `backend`

## When to Use
- User mentions or implies: voice agent
- User mentions or implies: speech to text
- User mentions or implies: text to speech
- User mentions or implies: whisper
- User mentions or implies: elevenlabs
- User mentions or implies: deepgram
- User mentions or implies: realtime api
- User mentions or implies: voice assistant
- User mentions or implies: voice ai
- User mentions or implies: conversational ai
- User mentions or implies: tts
- User mentions or implies: stt
- User mentions or implies: asr

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.