YouTube Videos automatisch transkribieren und zusammenfassen lassen? Mit der Supadata API geht das ganz einfach – und der Free Plan reicht für den täglichen Bedarf.

Die bessere Alternative zu manuellem Transkribieren

Supadata bietet direkten Zugriff auf YouTube-Transkripte mit KI-gestützter Zusammenfassung – deutlich effizienter als Selbsttranskription oder teure Dienste.

Warum Supadata?

  • Kostenlos starten – 100 Credits/Monat im Free Plan
  • Nur bei Erfolg zahlen – Kein Transkript (404) = 0 Credits verbraucht
  • Deutsche Sprache – Optimiert fĂźr deutschsprachige Videos
  • Intelligentes Caching – 30-Tage-Cache verhindert Duplikate
  • Integriert mit YouTube-Tracker – Automatisch fĂźr neue Videos

Features

  • ✅ Direkter API-Zugriff auf YouTube-Transkripte
  • ✅ Automatische KI-Zusammenfassung via lokales Qwen-Modell
  • ✅ Credit-Schutz – nur bei Erfolg verbraucht
  • ✅ Monatliches Tracking mit automatischem Reset
  • ✅ Nahtlose OpenClaw-Integration

Installation

1. Account erstellen

  1. Besuche dash.supadata.ai
  2. Registriere dich fĂźr einen Free Account
  3. Kopiere deinen API Key (beginnt mit sd_)

2. API Key konfigurieren

FĂźge in deine .env Datei ein:

SUPERDATA_API_KEY=sd_dein_api_key_hier

3. Skill installieren

Erstelle folgende Dateien:

SKILL.md → skills/supadata-youtube-transcript/SKILL.md

---
name: supadata-youtube-transcript
description: Supadata API Integration fĂźr YouTube-Transkripte. Verwendet api.supadata.ai um Transkripte zu holen und KI-Zusammenfassungen zu erstellen. Free Plan: 100 Credits/Monat. Credits nur bei Erfolg verbraucht (404 = kostenlos).
---

# Supadata YouTube Transkript Skill

Integration der Supadata API fĂźr YouTube-Transkripte.

## Überblick

Holt YouTube-Transkripte via Supadata API und erstellt KI-Zusammenfassungen. 
Optimiert fĂźr Free Plan (100 Credits/Monat).

**API:** https://api.supadata.ai/v1

## Schnellstart

python3 scripts/supadata_transcript.py VIDEO_ID "Titel"

## Credit-Management

- **100 Credits/Monat** im Free Plan
- **1 Credit** = 1 Video mit Transkript
- **0 Credits** = Kein Transkript verfĂźgbar (404)
- Automatischer Reset bei Monatswechsel

## Installation

1. Account erstellen bei https://dash.supadata.ai/
2. API Key in .env eintragen: SUPERDATA_API_KEY=sd_xxx
3. Skill nach skills/supadata-youtube-transcript/ kopieren

## Links

- Dashboard: https://dash.supadata.ai/
- API: https://api.supadata.ai/v1

supadata_transcript.py → skills/supadata-youtube-transcript/scripts/supadata_transcript.py

#!/usr/bin/env python3
"""
Supadata API fĂźr YouTube-Transkripte + KI-Zusammenfassung
Free Plan: 100 Credits/Monat (nur bei Erfolg verbraucht)
"/"/"

import os
import json
import urllib.request
import urllib.error
import ssl
from pathlib import Path
from datetime import datetime, timedelta

# === CONFIG ===
CREDIT_FILE = Path("/home/node/.openclaw/workspace/memory/supadata_credits.json")
CACHE_FILE = Path("/home/node/.openclaw/workspace/memory/supadata_cache.json")
MAX_CREDITS = 100


class SupadataClient:
    """Client fĂźr Supadata YouTube API"""
    
    BASE_URL = "https://api.supadata.ai/v1"
    
    def __init__(self):
        self.api_key = self._load_api_key()
        self.ssl_ctx = ssl.create_default_context()
        self.ssl_ctx.check_hostname = False
        self.ssl_ctx.verify_mode = ssl.CERT_NONE
    
    def _load_api_key(self):
        env_paths = [Path('/home/node/.openclaw/workspace/.env'), Path('.env')]
        for env_path in env_paths:
            if env_path.exists():
                with open(env_path) as f:
                    for line in f:
                        if line.strip().startswith('SUPERDATA_API_KEY='):
                            return line.split('=', 1)[1].strip().strip('"'')
        return os.getenv('SUPERDATA_API_KEY')
    
    def get_transcript(self, video_id, lang="de"):
        """Holt Transkript fĂźr Video"""
        url = f"{self.BASE_URL}/youtube/transcript?videoId={video_id}\&language={lang}"
        
        req = urllib.request.Request(
            url,
            headers={'x-api-key': self.api_key, 'Accept': 'application/json'},
            method='GET'
        )
        
        try:
            with urllib.request.urlopen(req, timeout=30, context=self.ssl_ctx) as r:
                data = json.loads(r.read().decode())
                return {
                    "success": True,
                    "has_transcript": True,
                    "content": data.get("content", [])
                }
        except urllib.error.HTTPError as e:
            if e.code == 404:
                return {"success": False, "has_transcript": False, "error": "No transcript"}
            elif e.code == 402:
                return {"success": False, "has_transcript": False, "error": "Credits exhausted"}
            else:
                return {"success": False, "has_transcript": False, "error": f"HTTP {e.code}"}
    
    def get_text(self, video_id, lang="de"):
        """Holt zusammengefĂźgten Text"""
        result = self.get_transcript(video_id, lang)
        if not result["has_transcript"]:
            return ""
        segments = result.get("content", [])
        return " ".join([s.get("text", "") for s in segments])
    
    def summarize(self, text, title=""):
        """KI-Zusammenfassung via Qwen"""
        text = text[:4000] + "..." if len(text) > 4000 else text
        
        prompt = f"""Fasse das YouTube-Transkript kurz zusammen (2-3 Sätze, max 250 Zeichen).

Titel: {title or 'Video'}

{text}

Zusammenfassung:"""
        
        try:
            import subprocess
            result = subprocess.run(
                ['curl', '-s', 'http://localhost:11434/api/generate',
                 '-d', json.dumps({
                     "model": "qwen3.5:cloud",
                     "prompt": prompt,
                     "stream": False,
                     "options": {"temperature": 0.3, "num_predict": 150}
                 })],
                capture_output=True, text=True, timeout=30
            )
            if result.returncode == 0:
                response = json.loads(result.stdout)
                return response.get('response', '').strip()
        except Exception as e:
            print(f"LLM Error: {e}", file=__import__('sys').stderr)
        
        # Fallback
        sentences = text.split('. ')[:3]
        return '. '.join(sentences) + '.' if sentences else "Keine Zusammenfassung"


# === CREDIT & CACHE MANAGEMENT ===

def load_credits():
    if CREDIT_FILE.exists():
        try:
            with open(CREDIT_FILE) as f:
                state = json.load(f)
                if state.get("month") != datetime.now().strftime("%Y-%m"):
                    return {"month": datetime.now().strftime("%Y-%m"), "used": 0, "remaining": MAX_CREDITS}
                return state
        except:
            pass
    return {"month": datetime.now().strftime("%Y-%m"), "used": 0, "remaining": MAX_CREDITS}


def save_credits(state):
    CREDIT_FILE.parent.mkdir(parents=True, exist_ok=True)
    with open(CREDIT_FILE, "w") as f:
        json.dump(state, f, indent=2)


def load_cache():
    if CACHE_FILE.exists():
        try:
            with open(CACHE_FILE) as f:
                return json.load(f)
        except:
            pass
    return {}


def save_cache(cache):
    CACHE_FILE.parent.mkdir(parents=True, exist_ok=True)
    cutoff = (datetime.now() - timedelta(days=30)).isoformat()
    cache = {k: v for k, v in cache.items() if v.get("checked_at", "") > cutoff}
    with open(CACHE_FILE, "w") as f:
        json.dump(cache, f, indent=2)


# === MAIN FUNCTIONS ===

def get_summary(video_id, title="", lang="de"):
    """Holt Zusammenfassung mit Credit-Schutz"""
    
    credits = load_credits()
    if credits["remaining"] <= 0:
        print(f"⚠️  Credits aufgebraucht ({credits['used']}/{MAX_CREDITS})")
        return None
    
    cache = load_cache()
    if video_id in cache:
        cached = cache[video_id]
        if cached.get("has_transcript"):
            print(f"📦 Aus Cache")
            return {"summary": cached["summary"], "source": "cache"}
        return None
    
    client = SupadataClient()
    result = client.get_transcript(video_id, lang)
    
    entry = {"checked_at": datetime.now().isoformat(), "has_transcript": result["has_transcript"]}
    
    if result["has_transcript"]:
        text = client.get_text(video_id, lang)
        summary = client.summarize(text, title)
        
        credits["used"] += 1
        credits["remaining"] -= 1
        
        entry.update({"summary": summary, "source": "supadata"})
        cache[video_id] = entry
        save_cache(cache)
        save_credits(credits)
        
        print(f"✅ Credit {credits['used']}/{MAX_CREDITS}")
        return {"summary": summary, "source": "supadata"}
    else:
        cache[video_id] = entry
        save_cache(cache)
        print(f"ℹ️  Kein Transkript: {result.get('error', 'Unknown')}")
        return None


def process_videos(videos, max_videos=3):
    """Verarbeitet Video-Liste"""
    if not videos:
        return videos
    
    credits = load_credits()
    print(f"
💰 Credits: {credits['used']}/{MAX_CREDITS}")
    
    if credits["remaining"] <= 0:
        print("⚠️  Keine Credits - überspringe")
        return videos
    
    processed = []
    fetched = 0
    
    for video in videos[:max_videos]:
        vid = video.get("id")
        title = video.get("title", "")
        
        if not vid:
            processed.append(video)
            continue
        
        print(f"
📝 {title[:50]}...")
        result = get_summary(vid, title)
        
        if result:
            video["transcript_summary"] = result["summary"]
            video["transcript_source"] = result["source"]
            fetched += 1
        else:
            video["transcript_summary"] = None
            video["transcript_source"] = None
        
        processed.append(video)
    
    processed.extend(videos[max_videos:])
    print(f"
✅ {fetched} Transkripte")
    return processed


def credit_status():
    credits = load_credits()
    print(f"Supadata Credits ({credits['month']}):")
    print(f"  Verwendet: {credits['used']}/{MAX_CREDITS}")
    print(f"  Verbleibend: {credits['remaining']}")


# === CLI ===

if __name__ == "__main__":
    import sys
    
    if len(sys.argv) < 2:
        print("Usage: python3 supadata_transcript.py  [title]")
        print("       python3 supadata_transcript.py --status")
        sys.exit(1)
    
    if sys.argv[1] == "--status":
        credit_status()
        sys.exit(0)
    
    vid = sys.argv[1]
    title = sys.argv[2] if len(sys.argv) > 2 else ""
    
    print(f"Testing: {vid}")
    result = get_summary(vid, title)
    
    if result:
        print(f"
✅ {result['source']}")
        print(f"   {result['summary']}")
    else:
        print("
❌ Kein Transkript")

Nutzung

Einmaliges Video testen

python3 scripts/supadata_transcript.py VIDEO_ID "Video Titel"

Credit-Status prĂźfen

python3 scripts/supadata_transcript.py --status

Im YouTube-Tracker

Der Skill ist automatisch integriert. Bei jedem Check werden max. 3 neue Videos verarbeitet. Wenn keine Credits verfĂźgbar, wird Ăźbersprungen.

Preise

Plan Credits/Monat Preis
Free 100 Kostenlos
Pro 1.000  5$/Monat

Links

  • 🌐 Website: https://supadata.ai
  • 📊 Dashboard: https://dash.supadata.ai/
  • 💻 API: https://api.supadata.ai/v1

Skill-Location: ~/.openclaw/workspace/skills/supadata-youtube-transcript/