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
- Besuche dash.supadata.ai
- Registriere dich fĂźr einen Free Account
- 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/