Files
ohm_streaming/README.md
T

12 KiB

⛩ Ohm Stream Downloader

Application web auto-hébergée (homelab) : centre de contrôle unique pour découvrir, regarder et télécharger des animes et séries VOSTFR/VF.

⚖️ Avertissement légal

Ohm Stream Downloader est un outil technique d'automatisation : il ne fournit, n'héberge ni ne distribue aucun contenu. Il automatise uniquement l'accès à des flux déjà publiquement accessibles sur des sites tiers, dont l'auteur n'est pas responsable et qu'il n'exploite pas.

L'utilisation de ce logiciel relève de la seule responsabilité de l'utilisateur, tenu de respecter la législation de son pays — notamment le droit d'auteur (en France : art. L.122-4 du Code de la propriété intellectuelle). Le téléchargement ou la diffusion d'œuvres protégées sans autorisation est interdit par la loi.

Projet publié à des fins éducatives et de recherche. L'auteur décline toute responsabilité en cas d'usage illégal et n'encourage en aucune façon le piratage.

Disclaimer (EN): this project is a technical automation tool. It does not provide, host or distribute any content — it merely automates access to streams already publicly available on third-party websites that the author neither controls nor operates. Users are solely responsible for complying with their local laws, including copyright. The author assumes no liability for illegal use and does not endorse piracy.

Déploiement (Docker) — recommandé

Le déploiement officiel passe par Docker Compose : l'image (ffmpeg inclus) est hébergée publiquement sur GHCR (ghcr.io/aulyriusohm/ohm-streaming) — aucun compte requis.

Installation guidée (recommandée)

git clone https://git.lanro.eu/Roman/ohm_streaming.git && cd ohm_streaming
./scripts/install.sh

Le script vérifie Docker, demande la destination des épisodes (dossier dédié recommandé — voir « Bibliothèque Plex/Sonarr » ci-dessous), le port, génère les secrets, branche le montage et démarre. Non interactif aussi : ./scripts/install.sh --dir /srv/animes --port 8777.

À la main

# 1. Récupérer le projet
git clone https://git.lanro.eu/Roman/ohm_streaming.git && cd ohm_streaming

# 2. Configuration locale
cp .env.example .env
#    → OHM_SECRET_KEY (openssl rand -hex 32) et WATCHTOWER_TOKEN (openssl rand -hex 24) obligatoires

# 3. Démarrage
docker compose up -d

Puis ouvrir http://localhost:8777 — le premier compte créé est administrateur. Les données (data/, downloads/) sont montées en volumes : elles survivent aux mises à jour.

Variante Podman

Même déploiement via docker-compose.podman.yml (socket Podman pour Watchtower, au lieu du socket Docker) :

# 0. Socket Podman (une seule fois) — rootless :
systemctl --user enable --now podman.socket
sudo loginctl enable-linger $USER      # persister après déconnexion
export PODMAN_SOCKET=/run/user/$(id -u)/podman/podman.sock
#    rootful : sudo systemctl enable --now podman.socket  (aucun export nécessaire)

# 1. Récupérer le projet
git clone https://git.lanro.eu/Roman/ohm_streaming.git && cd ohm_streaming

# 2. Configuration locale (identique à Docker)
cp .env.example .env   # → OHM_SECRET_KEY et WATCHTOWER_TOKEN obligatoires

# 3. Démarrage
podman compose -f docker-compose.podman.yml up -d
#    (« podman compose » délègue à docker-compose ; sinon : podman-compose)

La mise à jour depuis la page Admin (bouton Watchtower) fonctionne à l'identique ; à la main : podman compose -f docker-compose.podman.yml pull && podman compose -f docker-compose.podman.yml up -d.

Bibliothèque Plex / Sonarr existante

Ohm peut déposer ses épisodes directement dans ton serveur de média :

  1. Crée un dossier dédié (recommandé : hors de la racine Sonarr, ex. /plex_videos/ohm) et monte-le à la place de ./downloads : - /plex_videos/ohm:/downloads — c'est ce que fait scripts/install.sh.
  2. Ajoute ce dossier à Plex comme dossier d'une bibliothèque (ou comme dossier supplémentaire de ta bibliothèque animes). Les épisodes arrivent rangés par animé : One Piece/One Piece - E1010 (VOSTFR).mp4 — le nom du dossier sert de série, le fichier d'épisode.
  3. Sonarr n'est pas touché : l'entrypoint du conteneur ne prend possession (chown) que d'un dossier de téléchargements vide ; une bibliothèque existante et ses droits restent intacts. Pour piloter Ohm depuis Sonarr ou Prowlarr, voir l'API Torznab plus bas.

Si tu pointes /downloads sur un dossier non vide, Ohm adopte les fichiers présents (ils apparaissent dans sa bibliothèque interne) et conserve les droits existants — assure-toi juste que l'uid 1000 du conteneur peut y écrire.

Mettre à jour

Depuis l'interface (déploiement Docker) : page Admin → Mise à jour — configurer une fois le dépôt Gitea + un jeton d'accès (droit lecture), puis « Vérifier » et « ⬆ Mettre à jour maintenant ». Watchtower tire la nouvelle image et recrée le conteneur : quelques secondes d'indisponibilité, les pages ouvertes se reconnectent et rechargent automatiquement.

En ligne de commande (toujours possible) :

docker compose pull && docker compose up -d

Publier une version (mainteneur)

./scripts/release.sh 0.2.0

Bump de version, commit + tag git, build de l'image et push vers git.lanro.eu/roman/ohm_streaming (tags 0.2.0 et latest).

Démarrage rapide (développement)

uv sync
# ffmpeg requis pour les flux HLS (binaire statique dans ~/.local/bin, ou apt install ffmpeg)
uv run uvicorn app.main:app --host 0.0.0.0 --port 8777

Serveur persistant en dev : préférer Docker (voir plus haut) ; sinon tmux new-session -d -s ohm 'uv run uvicorn app.main:app --host 0.0.0.0 --port 8777'.

Puis ouvrir http://localhost:8777 — le premier compte créé est administrateur.

Configuration

Variables d'environnement (préfixe OHM_, voir .env.example) :

Variable Défaut Rôle
OHM_SECRET_KEY change-me-in-production À changer — signature des tokens
OHM_DOWNLOAD_DIR ./downloads Dossier des fichiers téléchargés
OHM_DATABASE_PATH ./data/ohm.db Base SQLite
OHM_MAX_PARALLEL_DOWNLOADS 3 Téléchargements simultanés
OHM_WATCHTOWER_URL (vide) URL Watchtower pour la mise à jour (réglé par docker-compose)
OHM_WATCHTOWER_TOKEN (vide) Jeton partagé Watchtower (réglé par docker-compose)
OHM_VERSION (pyproject) Version affichée — cuite dans l'image Docker au build

Fonctionnalités

  • Recherche unifiée sur plusieurs sources (Vostfree, French-Manga, VoirAnime pour les animes ; French-Stream pour les séries et films VF/VOSTFR) — chaque source est un module interchangeable activable/désactivable à chaud (page Admin), dont l'URL est modifiable à la volée (utile si un site change de domaine).
  • Extraction en 2 niveaux : page d'épisode → lecteurs embarqués → URL directe (Sibnet, SendVid, VidMoly, Uqload, Vidzy, Luluvdo ; VoirAnime résout via son endpoint « prepare » : MP4 direct ou HLS relayé par le proxy du site).
  • Préférence de contenus par compte : sélecteur topbar ⛨ Animés / 📺 Séries / ✨ Les deux — la recherche et les nouveautés filtrent par type de média, et les sources hors périmètre ne sont même pas interrogées.
  • Proxy vidéo intégré (/api/proxy) : contourne les protections (tokens liés à l'IP, Referer/UA obligatoires), réécrit les playlists HLS.
  • Téléchargements : file parallèle, pause/reprise (HTTP Range), retry, anti-doublons, progression en temps réel (SSE), persistance au redémarrage.
  • Bibliothèque locale : streaming avec range requests, reprise de lecture, navigation épisode suivant/précédent.
  • Comptes : JWT court + refresh token (rotation), rôles admin/utilisateur, administration des comptes.
  • Découverte (/discover) : 🎭 exploration par genre (animés via Kitsu, séries/films via French-Stream — état dans l'URL, partageable), 🆕 nouveautés en rails séparés (animés triés par date de sortie via Kitsu ; séries & films de French-Stream), 🔥 incontournables animés (top popularité Kitsu) et ✨ recommandations par genres déduites des téléchargements et favoris, titres déjà possédés exclus (cache mémoire). Sans Sonarr, les genres des séries/films téléchargés sont lus sur leur fiche source ; sans aucun historique, une carte d'amorçage invite à télécharger un premier titre.

Intégration Sonarr / Prowlarr (*arr)

OhmStreaming expose une API Torznab (indexeur) et une API compatible qBittorrent (client de téléchargement) : Sonarr peut lui déléguer toute la chaîne — recherche, téléchargement, puis import et renommage automatiques dans la bibliothèque Sonarr.

1. OhmStreaming comme indexeur

Dans Admin → Intégrations Sonarr / Prowlarr, copier :

Champ Valeur
URL http://<hote-ohm>:8777/torznab/api
Clé API générée automatiquement (bouton Régénérer pour la changer)
  • Prowlarr : Indexers → Add Indexer → Generic Torznab → coller URL + clé, puis synchroniser vers Sonarr.
  • Sonarr (direct) : Settings → Indexers → Add → Torznab → coller URL + clé. Catégories : TV (5000) / Anime (5070).

Endpoints : t=caps, t=tvsearch (q, season, ep), t=search — auth par ?apikey= ou en-tête X-Api-Key.

2. OhmStreaming comme client de téléchargement (recommandé)

Dans Sonarr : Settings → Download Clients → Add → qBittorrent :

Champ Valeur
Host http://<hote-ohm>:8777
Username ohm
Password la clé API Torznab (Admin → Intégrations)

Le flux complet devient : Sonarr grab → Ohm télécharge (progression visible dans la file Sonarr) → Sonarr importe, renomme et range l'épisode dans sa bibliothèque selon ses propres règles → le « torrent » est retiré de la file Ohm (fichier inclu si « Remove Completed » est coché).

Chemin d'accès : Ohm annonce les fichiers sous /downloads/<Animé>/… (chemin conteneur). Si Sonarr tourne dans Docker sans ce montage, ajouter un Remote Path Mapping : hôte = <hote-ohm>, distant = /downloads, local = le dossier hôte monté (ex. /plex_videos/ohm).

Variante minimale sans import : client « Torrent Blackhole » — Sonarr pose le .torrent de service et l'épisode reste dans la bibliothèque OhmStreaming seulement (pas d'import/renommage Sonarr).

2. « Pour toi » personnalisé par Sonarr

Toujours dans Admin → Intégrations, renseigner l'URL Sonarr (http://sonarr:8989) et sa clé API (Settings → General → API Key), puis « Enregistrer » et « Tester ». Les genres des séries téléchargées/grabées sur Sonarr alimentent la section ✨ Pour toi (et ce qui y est possédé n'est pas re-recommandé). Sonarr absent ou KO → dégradation gracieuse, rien ne casse.

Architecture

app/
├── main.py              # FastAPI + lifespan (DB, download manager)
├── config.py            # pydantic-settings (OHM_*)
├── db.py                # SQLite (aiosqlite) — source de vérité unique
├── routers/             # auth, search, discover, downloads, library, admin, torznab, pages
├── scrapers/
│   ├── base.py          # contrats SourceScraper/HosterExtractor + registres
│   ├── configs/         # sélecteurs YAML externalisés (réparer sans coder)
│   ├── sources/         # vostfree, french_manga, voiranime, french_stream
├── services/            # downloads, kitsu, discover, sonarr, torznab, settings
└── templates/ + static/ # UI htmx + Alpine.js, thème sombre

Ajouter une source : créer app/scrapers/sources/ma_source.py qui implémente SourceScraper, la décorer @register_source — c'est tout (registre auto-découvert).

Tests

uv run pytest        # 132 tests
uv run ruff check .  # lint