Skill: franklinyung/video-content-watcher (version 1.0.0)

--- name: video-content-watcher description: Extract core content and generate structured analysis reports from YouTube, Bilibili, or local video files. Triggers when user asks to summarize, analyze, extract key points from a video, or assess video value. Supports Chinese/English video content analysis with MiniMax LLM. --- # Video Content Watcher Extract audio → transcribe → analyze → generate structured Markdown report. ## Quick Start ```bash cd /home/ykl/.openclaw/workspace-code-dev/video-reader export MINIMAX_API_KEY="your-key" export WHISPER_MODE="local" # or "api" python3 << 'EOF' import sys; sys.path.insert(0, 'src') from video_reader_mcp import VideoReaderMCP mcp = VideoReaderMCP() result = mcp.process_url('VIDEO_URL') print(result['report']) EOF ``` Or use the CLI script: ```bash python3 /home/ykl/.openclaw/workspace/skills/video-content-watcher/scripts/video_reader.py "VIDEO_URL" ``` ## Workflow 1. **Audio extraction**: Uses `yt-dlp` for online videos / `ffmpeg` for local files 2. **Transcription**: Whisper (local `openai-whisper` or API mode) 3. **Analysis**: MiniMax LLM analyzes transcript → structured report ## Configuration (env vars) | Variable | Required | Default | Description | |----------|----------|---------|-------------| | `MINIMAX_API_KEY` | Yes | — | MiniMax API key | | `WHISPER_MODE` | No | `api` | `api` or `local` | | `WHISPER_API_KEY` | If mode=api | — | OpenAI API key for Whisper | | `LLM_BASE_URL` | No | `https://api.minimaxi.com/v1` | MiniMax endpoint | | `LLM_MODEL` | No | `MiniMax-M2.7` | Model name | ## Supported Sources - **YouTube**: `https://www.youtube.com/watch?v=xxx` - **Bilibili**: `https://www.bilibili.com/video/BVxxx` - **Local files**: `/path/to/video.mp4` ## Output Returns a Markdown report with: - Basic info (source, transcript length) - Core content summary - Key takeaways - Main viewpoints - Pros / cons - Target audience ## Scripts - `scripts/video_reader.py` — CLI entry point - `scripts/analyze_text.py` — Analyze raw text directly (skip video processing)

path: scripts/analyze_text.py
content: #!/usr/bin/env python3
"""Analyze raw text directly - skip video/audio processing"""

import sys
from pathlib import Path

# MCP project location
SKILL_ROOT = Path(__file__).resolve().parents[4]  # /home/ykl/.openclaw/
MCP_PATH = SKILL_ROOT / "workspace-code-dev" / "video-reader"
sys.path.insert(0, str(MCP_PATH / "src"))

from video_reader_mcp import VideoReaderMCP


def main():
    if len(sys.argv) < 2:
        print("Usage: python analyze_text.py '<text to analyze>'")
        sys.exit(1)

    text = sys.argv[1]
    mcp = VideoReaderMCP()
    result = mcp.analyze_text(text)
    print(result.get("report", result.get("analysis", "No output")))


if __name__ == "__main__":
    main()


path: scripts/video_reader.py
content: #!/usr/bin/env python3
"""Video Reader CLI - Extract and analyze video content"""

import sys
import os
from pathlib import Path

# MCP project location
# scripts/video_reader.py → parents[4] = /home/ykl/.openclaw/
SKILL_ROOT = Path(__file__).resolve().parents[4]  # /home/ykl/.openclaw/
MCP_PATH = SKILL_ROOT / "workspace-code-dev" / "video-reader"
sys.path.insert(0, str(MCP_PATH / "src"))  # add video-reader/src so video_reader_mcp can be found

from video_reader_mcp import VideoReaderMCP


def main():
    if len(sys.argv) < 2:
        print("Usage: python video_reader.py <video_url_or_file_path>")
        sys.exit(1)

    source = sys.argv[1]
    is_url = source.startswith(("http://", "https://"))

    mcp = VideoReaderMCP()

    if is_url:
        result = mcp.process_url(source)
    else:
        result = mcp.process_file(source)

    print(result["report"])


if __name__ == "__main__":
    main()


path: references/api_details.md
content: # Video Reader - Technical Reference

## Project Structure

```
video-reader/               # MCP project
├── src/
│   ├── __init__.py         # Main entry, VideoReaderMCP class
│   ├── config.py           # Config management (dotenv loading)
│   ├── extractor/
│   │   └── audio_extractor.py  # yt-dlp / ffmpeg audio extraction
│   ├── transcription/
│   │   └── whisper_client.py   # Whisper API or local transcription
│   ├── analyzer/
│   │   └── llm_analyzer.py     # MiniMax / OpenAI LLM analysis
│   └── output/
│       └── report_generator.py # Markdown report generation
├── .env                     # Env vars (gitignored, no real keys)
├── .env.example             # Template for collaborators
├── requirements.txt
└── temp/                    # Audio extraction temp files
```

## API Details

### MiniMax LLM (used for analysis)

- **Endpoint**: `https://api.minimaxi.com/v1` (or custom `LLM_BASE_URL`)
- **Model**: `MiniMax-M2.7` (default), `MiniMax-Text-01` also supported
- **Auth**: Bearer token via `MINIMAX_API_KEY`

### Whisper Transcription

- **Local mode** (default): uses `openai-whisper` package, downloads model (~139MB base)
- **API mode**: uses OpenAI Whisper API, requires `WHISPER_API_KEY`

## Config Priority

1. Constructor arguments (if provided)
2. Environment variables
3. `.env` file (non-sensitive defaults only)
4. Hardcoded defaults in `config.py`

## VideoReaderMCP Methods

```python
# Full pipeline: extract → transcribe → analyze → report
mcp.process_url(video_url)           # Online video
mcp.process_file("/path/to/file.mp4") # Local file

# Partial pipelines
mcp.transcribe_only(source, is_url=True)  # Transcription only
mcp.analyze_text(text)                    # Analyze raw text

# Result dict keys
result = mcp.process_url(url)
result["source_url"]           # Original URL
result["audio_path"]           # Temp audio file path
result["transcription"]        # Raw transcript text
result["transcription_length"] # Character count
result["analysis"]             # LLM raw output (dict)
result["report"]               # Formatted Markdown report
```

## Error Handling

- `WHISPER_API_KEY is required when WHISPER_MODE=api` → set env var or pass to constructor
- `MINIMAX_API_KEY is required` → set env var
- `ffmpeg not found` → install ffmpeg system package
- `No module named 'video_reader_mcp'` → ensure `src/` is in `PYTHONPATH`


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)