Metadata-Version: 2.4
Name: shorts-trends
Version: 5.0.0
Summary: YouTube Shorts trend analyzer with local dashboard
Requires-Python: >=3.11
Requires-Dist: claude-agent-sdk>=0.1.72
Requires-Dist: pandas>=2.0
Requires-Dist: platformdirs<5,>=4.5
Requires-Dist: psutil>=7.0
Requires-Dist: python-dotenv>=1.0
Requires-Dist: requests>=2.32
Provides-Extra: captions
Provides-Extra: dashboard
Requires-Dist: fastapi>=0.115; extra == 'dashboard'
Requires-Dist: jinja2>=3.1; extra == 'dashboard'
Requires-Dist: python-multipart>=0.0.7; extra == 'dashboard'
Requires-Dist: uvicorn>=0.30; extra == 'dashboard'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: httpx>=0.28; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: pyyaml>=6.0; extra == 'dev'
Requires-Dist: scipy>=1.13; extra == 'dev'
Provides-Extra: visuals
Requires-Dist: pillow<13,>=11; extra == 'visuals'
Provides-Extra: voice
Requires-Dist: bark==0.1.5; extra == 'voice'
Requires-Dist: scipy>=1.13; extra == 'voice'
Requires-Dist: torch<3,>=2.10; extra == 'voice'
Requires-Dist: transformers<6,>=4.46; extra == 'voice'
Description-Content-Type: text/markdown

# YouTube Shorts Trend Analyzer

Local Python pipeline that ingests YouTube Shorts data, identifies early viral candidates,
scores them with AI-driven content evaluation, and surfaces repeatable viral formats.

## Quickstart

```bash
python -m venv .venv
.venv\Scripts\activate         # Windows
pip install -r requirements.txt
python main.py --input data/sample_videos.csv
```

Default scorer is `MockScorer` (no API key needed) so the pipeline runs out of the box.

## AI Features (Claude Code)

The `--script`, `--ideas`, and `SCORER=claude` features authenticate via a **signed-in Claude Code CLI session**.

### Prerequisites

1. Install the Claude Code CLI:
   ```bash
   npm install -g @anthropic-ai/claude-code
   ```
2. Sign in with your Claude Max plan:
   ```bash
   claude login
   ```
   Complete the OAuth flow in the browser using the account that holds your Max plan subscription.

3. Verify your sign-in:
   ```bash
   claude /status
   ```

### Running AI features

```bash
python main.py --input data/sample_videos.csv --script   # generates 3 production-ready scripts
python main.py --input data/sample_videos.csv --ideas    # generates 2-3 video ideas
```

All AI usage is billed against your Claude Max plan. No additional API key is required.

> **Note:** API-key fallback (`ANTHROPIC_API_KEY`-based auth) is **NOT supported** in this version.
> Future versions may revisit this if there is demand.

The `YOUTUBE_API_KEY` environment variable is only needed for `--query` and `--channel` (live YouTube fetching), not for AI features.

## Async usage (FastAPI)

All three generators expose native async methods (`ascore`, `agenerate`) usable directly from async hosts without `RuntimeError`:

```python
from fastapi import FastAPI
from ai_analysis.claude_scorer import ClaudeScorer
from output.ideas import IdeaGenerator

app = FastAPI()
scorer = ClaudeScorer()
idea_gen = IdeaGenerator()

@app.post("/analyze")
async def analyze(videos: list[dict]):
    # Convert request payload into Video objects (omitted)
    scored = await scorer.ascore(video_list)
    ideas = await idea_gen.agenerate(
        archetypes=detected_archetypes,
        top_videos=scored,
    )
    return {"scores": scored, "ideas": ideas}
```

The sync entry methods (`score_batch`, `generate`) are preserved as thin wrappers and remain safe to call from any host — including async ones — via internal sync-from-async dispatch.

## Pipeline

```
CSV input
   │
   ▼
data_collection      → list[Video]
   │
   ▼
feature_extraction   → metrics: views/hour, age_hours
   │
   ▼
ai_analysis          → hook_strength, curiosity_gap, viral_potential (0-10 each)
   │
   ▼
scoring              → composite 0-100
   │
   ▼
output               → ranked table + pattern report
```

## Modules

| Module | Purpose |
|---|---|
| `config/`            | Weights, thresholds, model settings |
| `data_collection/`   | CSV loader (v1), YouTube API client (v2) |
| `feature_extraction/`| Numeric metrics (views/hour, age) |
| `ai_analysis/`       | Pluggable LLM scorers (Mock / Claude) |
| `scoring/`           | Combine metrics + AI scores into composite |
| `output/`            | Rank, print, extract patterns |

## Production Pipeline (v5.0)

The v5.0 production pipeline turns a generated script into an upload-ready
YouTube Shorts bundle:

```
shorts-trends produce --from-script <script.json> [--variant N] [--length 15s|30s|60s] [--out <dir>]
```

The bundle directory `<out>/<run_id>/` contains:

- `<run_id>.mp4` — final 1080×1920 stitched short
- `metadata.json` — title (≤95 chars), description (first line contains
  `#Shorts`), tags (within YouTube's 500-char budget), `category_id: 22`,
  `privacy_status: "private"`, `thumbnail_kind: "auto"`
- `<run_id>_thumbnail.png` — auto-extracted midpoint frame
- `credits.json` — Pexels attribution list
- `<run_id>.srt` — sidecar captions (YouTube CC parity)
- `upload_instructions.txt` — step-by-step manual upload guide

### Manual upload boundary

**v5.0 produces an upload-ready bundle. Manual upload via
[studio.youtube.com](https://studio.youtube.com/upload) is the supported
path. Programmatic upload (`--upload` flag, OAuth flow, credentials cache)
is on the v5.1 roadmap (UPLOAD-V51-01).**

Following each `shorts-trends produce` run, open `upload_instructions.txt`
in the bundle directory for the exact YouTube Studio steps. The
`metadata.json` fields are designed to be copy-pasted directly into the
YouTube Studio upload form.

## Roadmap

- **v1** (this scaffold): CSV → mock scoring → ranked output
- **v2**: Plug in Claude (`claude-agent-sdk`) — auth delegates to a signed-in Claude Code CLI session.
- **v3**: YouTube Data API v3 collector replacing CSV
- **v4**: Scheduling (cron / Windows Task Scheduler) + persistence (SQLite)
