# Wie die großen Tube-Seiten ihre Video-Links & Metadaten aufbauen

Diese Referenz erklärt, **woraus ein einzelner Video-Link besteht** und **wo Titel,
Thumbnail, Dauer & Embed herkommen** — also was der Importer pro Seite ausliest.
Genau diese öffentlich publizierten Daten (Open Graph, oEmbed, JSON-LD) nutzt der
Extraktor in [`scraper.js`](scraper.js). Das ist *kein* HTML-Klassen-Scraping.

> Wichtig: Diese Adapter sind für das **Einbetten einzelner Videos** gedacht, die
> du gezielt hinzufügst — nicht zum automatischen Abgreifen ganzer Kataloge.

---

## Allgemeines Muster (gilt für fast alle Seiten)

Jede seriöse Video-Seite legt im `<head>` der Watch-Seite ab:

```html
<meta property="og:title"   content="Titel des Videos">
<meta property="og:image"   content="https://…/thumb.jpg">
<meta property="og:video:url" content="https://…/embed/…">
<meta property="og:video:duration" content="754">
<script type="application/ld+json">
  { "@type":"VideoObject", "name":"…", "thumbnailUrl":"…",
    "duration":"PT12M34S", "embedUrl":"https://…/embed/…" }
</script>
<link rel="alternate" type="application/json+oembed" href="https://…/oembed?url=…">
```

Der Importer liest in dieser Reihenfolge: **JSON-LD → oEmbed → Open Graph →
Seiten-Adapter** (für die Embed-URL). Was fehlt, ergänzt du manuell.

---

## Pro Seite: Link-Struktur → Embed-URL

| Seite | Watch-URL (Beispielform) | Video-ID liegt in | Embed-URL (öffentlich) |
|---|---|---|---|
| **Pornhub** | `pornhub.com/view_video.php?viewkey=ph5xxxx` | `viewkey`-Parameter | `pornhub.com/embed/ph5xxxx` |
| **Xvideos** | `xvideos.com/video.abcdef/slug` | nach `video.` | `xvideos.com/embedframe/abcdef` |
| **XNXX** | `xnxx.com/video-abcdef/slug` | nach `video-` | `xnxx.com/embedframe/abcdef` |
| **xHamster** | `xhamster.com/videos/slug-12345678` (auch Mirror-Domains xhamster2.com, xhamster.desi …) | Zahl/`xh…` am Ende | `xhamster.com/embed/12345678` |
| **SpankBang** | `spankbang.com/abcd/video/slug` | erstes Pfadsegment | `spankbang.com/abcd/embed/` |
| **RedTube** | `redtube.com/123456` | numerischer Pfad | `embed.redtube.com/?id=123456` |
| **YouPorn** | `youporn.com/watch/123456/slug` | nach `/watch/` | `youporn.com/embed/123456` |
| **Eporner** | `eporner.com/video-abc/slug` | nach `video-` | `eporner.com/embed/abc` |

Diese Umschreibungen macht der jeweilige Adapter in `scraper.js` automatisch —
deshalb funktioniert das Embed **auch dann**, wenn die Metadaten dünn sind.

---

## Warum klappt es bei den „großen" manchmal trotzdem nicht? (Debugging)

Die Diagnose-Box im Admin zeigt dir bei jedem „Fetch metadata" genau das:

| Befund in der Diagnose | Bedeutung / Lösung |
|---|---|
| **HTTP-Status 403 / „Sperrseite erkannt"** | Die Seite hat eine Alters-/Bot-Wall statt der Video-Seite geliefert. Der Importer sendet bereits Alters-Cookies (`age_verified=1` etc.) für Pornhub/RedTube/YouPorn/SpankBang. Bleibt es 403, blockt die Seite Server-IPs → **Embed manuell** (die abgeleitete Embed-URL steht trotzdem im Formular). |
| **HTML geladen, aber JSON-LD/oEmbed/OG = nein** | Seite rendert Metadaten per JavaScript nach. Axios/Cheerio führt kein JS aus. → Embed-URL wird per Adapter abgeleitet, Titel/Thumbnail manuell. |
| **Netzwerkfehler (ENOTFOUND/ETIMEDOUT)** | Seite down oder DNS-Problem. Später erneut versuchen. |
| **Embed abgeleitet = ja, Titel = nein** | Normalfall bei Blocks: speichern geht trotzdem (Embed da), Titel ergänzen. |

> Für Seiten, die Metadaten **nur** per JS ausliefern und Server-IPs hart blocken,
> bräuchte man einen echten Headless-Browser (Playwright). Das ist bewusst **nicht**
> eingebaut, weil es typischerweise zum Massen-Scraping verwendet wird — und genau
> das ist hier nicht das Ziel. Für einzelne Videos ist der manuelle Embed-Fallback
> der schnellere, robustere Weg.

---

## So findest du die Embed-/oEmbed-Daten selbst (zum Verifizieren)

1. Video-Seite im Browser öffnen → Rechtsklick → **Seitenquelltext anzeigen**.
2. Nach `og:video`, `application/ld+json` oder `oembed` suchen (Strg+F).
3. Oder den **„Embed"/„Teilen"-Button** der Seite nutzen — der liefert exakt die
   `iframe`-URL, die du im Feld *Embed HTML* einfügen kannst.

Das ist der offizielle, vorgesehene Weg zum Einbetten — und genau den bildet der
Importer nach.
