Skip to main content
Glama
README.md
# ME4-YouTube

> **🧠 Standards:** Dieses Projekt folgt den ME4-Service-Bus-Standards v1.0.  
> πŸ“– **Verbindlich:** [HUB-Thought im openBrain](http://localhost:9100/thought/a2d183a3-e6f8-48ab-9ba1-d7a9eae2399e) β€” die Single source of truth.  
> ⚠️ **Abweichungen** MÜSSEN in einem PR begründet werden.

[![ME4-Standard](https://img.shields.io/badge/ME4-Standard-v1.0-blue)](D:/Entwicklung/ME4-SERVICE-BUS-PILOT.md)
[![openBrain](https://img.shields.io/badge/openBrain-HUB-green)](http://localhost:9100/thought/a2d183a3-e6f8-48ab-9ba1-d7a9eae2399e)
[![SOA-konform](https://img.shields.io/badge/SOA-konform-ja-brightgreen)](D:/Entwicklung/ME4-SERVICE-BUS-PILOT.md)


> **Service-ID:** `ME4-YOUTUBE`  
> **Version:** 1.2.001
> **Schnittstellen:** MCP (stdio + ZMQ REQ/REP) + HTTP/REST + Framie-UI

YouTube Content Extraction Service fΓΌr die ME4-Suite:
- **Download** β€” Video- und Audio-Download via `yt-dlp`
- **Beschreibung** β€” VollstΓ€ndige Metadaten inkl. Description
- **Transkript** β€” Manuell oder Auto-Generated, Multi-Language
- **Kommentare** β€” Top-Kommentare via `yt-dlp`
- **Loadbalancer-MCP** β€” Parallele Worker-Instanzen mit Health-Monitoring
- **Framie-UI** β€” Embedded Live-Status-Display

---

## Schnellstart

```bash
# Voraussetzungen: Python 3.11+, ffmpeg (optional, fΓΌr Audio-Konvertierung)

# Klonen / Installieren
cd D:\Entwicklung\ME4-YouTube
python -m venv .venv
.venv\Scripts\activate           # Windows
# source .venv/bin/activate      # macOS/Linux
pip install -r requirements.txt

# Konfiguration (Beispiel kopieren, anpassen)
copy .env.example .env           # Windows
# cp .env.example .env           # macOS/Linux

# Starten
python main.py

# ODER (ΓΆffnet Framie-UI nicht automatisch)
python main.py --no-browser
```

Beim Start ΓΆffnet sich automatisch die **Framie-UI** im Browser unter
[http://localhost:8770/ui/index.html](http://localhost:8770/ui/index.html).

---

## Schnittstellen

| Schnittstelle | Port | Zweck |
|---|---|---|
| **HTTP / REST** | `8770` | Browser, Menschen, externe Tools |
| **ZMQ Main** | `5570` | MCP-Service-Endpoint |
| **ZMQ Loadbalancer** | `5571` | MCP-Loadbalancer (parallele Worker) |
| **Worker-Pool** | `8771+` | N parallele Worker-Instanzen (default: 2) |

### MCP-Tools (ZMQ + stdio)

| Tool | Beschreibung | Auth |
|---|---|---|
| `ping` | Service-Health | public |
| `get_manifest` | UI-Manifest fΓΌr Cockpit | public |
| `health` | Detaillierter Status inkl. Worker-Pool | public |
| `get_status_snapshot` | Live-Job-Status | public |
| `get_metadata` | YouTube Metadaten + Description | πŸ”‘ |
| `get_transcript` | YouTube Transkript | πŸ”‘ |
| `get_comments` | YouTube Top-Kommentare | πŸ”‘ |
| `download` | Video/Audio herunterladen | πŸ”‘ |
| `process` | Komplette Pipeline (alle 4 Features) | πŸ”‘ |
| `trigger_sm_produce` | SM-Producer anstoßen | πŸ”‘ |
| `shutdown` | Geordneter Shutdown | πŸ”‘ |

### HTTP-Endpunkte

| Pfad | Methode | Beschreibung |
|---|---|---|
| `/` | GET | Service-Info |
| `/docs` | GET | OpenAPI/Swagger UI |
| `/api/health` | GET | Health (public) |
| `/api/manifest` | GET | UI-Manifest (public) |
| `/api/status` | GET | Live-Job-Status (public) |
| `/api/framie/stream` | GET | SSE-Stream fΓΌr Framie-UI (public) |
| `/api/process` | POST | Komplette Verarbeitung (πŸ”‘) |
| `/api/metadata` | POST | Nur Metadaten (πŸ”‘) |
| `/api/transcript` | POST | Nur Transkript (πŸ”‘) |
| `/api/comments` | POST | Nur Kommentare (πŸ”‘) |
| `/api/download` | POST | Video-Download (πŸ”‘) |
| `/api/sm-produce` | POST | SM-Producer triggern (πŸ”‘) |
| `/ui/index.html` | GET | Framie Live-Status-Display |

πŸ”‘ = `X-API-Key` Header erforderlich (oder Dev-Mode wenn `API_KEY=""`)

---

## Beispiele

### HTTP (curl)

```bash
# Metadaten + Beschreibung
curl -X POST http://localhost:8770/api/metadata \
  -H "X-API-Key: ob-youtube-key-2026" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://youtu.be/dQw4w9WgXcQ"}'

# Komplette Verarbeitung (alle Features)
curl -X POST http://localhost:8770/api/process \
  -H "X-API-Key: ob-youtube-key-2026" \
  -H "Content-Type: application/json" \
  -d '{
    "url":"https://youtu.be/dQw4w9WgXcQ",
    "download":false,
    "include_description":true,
    "include_transcript":true,
    "include_comments":true,
    "language":"de",
    "max_comments":100
  }'
```

### ZMQ (Python)

```python
import zmq, json

ctx = zmq.Context()
sock = ctx.socket(zmq.REQ)
sock.connect("tcp://127.0.0.1:5570")

sock.send_json({
    "jsonrpc": "2.0", "id": 1, "method": "tools/call",
    "params": {
        "name": "process",
        "arguments": {
            "url": "https://youtu.be/dQw4w9WgXcQ",
            "api_key": "ob-youtube-key-2026",
        }
    }
})
print(sock.recv_json())
```

### MCP stdio (Claude Code / Agenten)

```json
{
  "mcpServers": {
    "me4-youtube": {
      "command": "python",
      "args": ["D:/Entwicklung/ME4-YouTube/main.py", "--mcp-stdio"]
    }
  }
}
```

### Loadbalancer-MCP (parallele Verarbeitung)

Der Service bringt einen eingebauten Loadbalancer-MCP mit. Agenten
kΓΆnnen Jobs direkt an den Loadbalancer schicken, der sie auf freie
Worker verteilt:

```python
sock.connect("tcp://127.0.0.1:5571")
sock.send_json({
    "jsonrpc": "2.0", "id": 1, "method": "tools/call",
    "params": {
        "name": "process",
        "arguments": {
            "url": "https://youtu.be/dQw4w9WgXcQ",
            "api_key": "ob-youtube-key-2026",
        }
    }
})
```

Strategien: `round_robin`, `least_loaded`, `random` (default: `least_loaded`)

---

## SM-Producer Anbindung

Der Service kann direkt die SM-Producer-Pipeline (ME4-SMproducer-3) anstoßen:

```bash
curl -X POST http://localhost:8770/api/sm-produce \
  -H "X-API-Key: ob-youtube-key-2026" \
  -H "Content-Type: application/json" \
  -d '{
    "url":"https://youtu.be/dQw4w9WgXcQ",
    "transcript":"Volltext...",
    "language":"de",
    "workflow":"default"
  }'
```

Der Aufruf wird an `http://localhost:3001/api/sm-produce` weitergeleitet.
Konfiguration via `SM_PRODUCER_URL` und `SM_PRODUCER_API_KEY` in `.env`.

---

## Framie-UI

Beim Start des Services ΓΆffnet sich automatisch die Framie-UI im Browser:
- KPIs: aktive Jobs, erledigt, Fehler, Worker-Status
- Live-Stream ΓΌber Server-Sent Events
- Worker-Liste mit Idle/Busy/Down-Status
- Letzte 15 Jobs in Tabelle
- Event-Log

URL: `http://localhost:8770/ui/index.html`

---

## Tests

```bash
pip install pytest pytest-asyncio
pytest

# Mit Coverage
pip install pytest-cov
pytest --cov=app --cov-report=term-missing
```

---

## Konfiguration (.env)

Siehe [`.env.example`](.env.example) fΓΌr alle Optionen.

Wichtige Variablen:
- `API_KEY` β€” API-Key (leer = Dev-Mode)
- `WORKER_COUNT` β€” Anzahl paralleler Worker (default: 2)
- `LOADBALANCER_STRATEGY` β€” `round_robin` | `least_loaded` | `random`
- `SM_PRODUCER_URL` β€” SM-Producer-Pipeline-URL
- `DOWNLOAD_DIR` β€” Zielordner fΓΌr Downloads

---

## Schnittstellen-Standard

Konform zu [MCP_ZMQ_STANDARD.md](./MCP_ZMQ_STANDARD.md):
- ZMQ REQ/REP mit JSON-RPC 2.0
- API-Key Auth
- UI-Manifest
- Standard-Tools (`ping`, `get_manifest`, `health`, `shutdown`)

---

## Architektur

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ME4-YouTube (Service-ID: ME4-YOUTUBE)                    β”‚
β”‚                                                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
β”‚  β”‚  HTTP API      β”‚  β”‚  ZMQ Main       β”‚                β”‚
β”‚  β”‚  :8770         β”‚  β”‚  :5570          β”‚                β”‚
β”‚  β”‚  + Framie-UI   β”‚  β”‚  MCP REQ/REP    β”‚                β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
β”‚           β”‚                   β”‚                         β”‚
β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                         β”‚
β”‚                     β–Ό                                   β”‚
β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”‚
β”‚           β”‚  WorkerPool         β”‚                       β”‚
β”‚           β”‚  (Load-Balancer)    β”‚                       β”‚
β”‚           β”‚  ZMQ :5571          │◄──── Loadbalancer-MCP  β”‚
β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β”‚
β”‚                     β”‚                                   β”‚
β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”‚
β”‚         β–Ό           β–Ό           β–Ό                       β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”‚
β”‚    β”‚worker-01β”‚ β”‚worker-02β”‚ β”‚worker-03β”‚  (jeweils        β”‚
β”‚    β”‚  :8771  β”‚ β”‚  :8772  β”‚ β”‚  :8773  β”‚   Orchestrator)  β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
β”‚                                                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                        β”‚
β”‚  β”‚  SM-Producer   β”‚                                        β”‚
β”‚  β”‚  HTTP :3001    β”‚                                        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

Jeder Worker hat:
- eigenen HTTP-Server (fΓΌr eingehende Jobs vom Loadbalancer)
- einen `Orchestrator` (fΓΌhrt die Pipeline aus)
- Status-Updates landen im globalen `StatusTracker` β†’ Framie-Stream