Files
Alexandre 6c0c96c65d
Release / release (push) Failing after 6s
CI: workflow Gitea Actions de livraison par tag
- build + push image dans le registry Gitea sur tag vX.Y.Z
- création d'une release Gitea avec le compose de prod en asset
- doc CI/CD dans le README

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 03:01:36 +02:00

8.5 KiB
Raw Permalink Blame History

🎬 MKV → AVI

Petite application web (Docker) pour parcourir un dossier média, télécharger un fichier d'origine ou le convertir en AVI Xvid lisible par les vieux lecteurs DivX/DVD.

La conversion reprend le pipeline qui a fait ses preuves :

  • vidéo Xvid (mpeg4 -vtag xvid, qualité qscale 4) ;
  • audio MP3 stéréo (downmix 5.1 → 2.0) ;
  • sélection auto de la piste française en évitant l'audiodescription ;
  • tone-mapping HDR → SDR propre via zscale (les sources 4K HDR10/DV/HLG sont détectées automatiquement) ;
  • redimensionnement au choix (720 px « max compatibilité », 1280 px, ou original).

Le décodage est logiciel : dans un conteneur, l'accélération matérielle (VideoToolbox sur Mac, QSV/NVENC) n'est pas disponible. Comptez plusieurs minutes à quelques dizaines de minutes par film selon le CPU.

Démarrage rapide

# Dossier contenant vos films (monté en lecture seule)
export MEDIA_DIR=/chemin/vers/mes/films
# Où écrire les AVI convertis (optionnel, défaut ./output)
export OUTPUT_DIR=$PWD/output

docker compose up -d --build

Puis ouvrir http://localhost:8080.

  • Rechercher un fichier dans le champ de recherche.
  • ⬇ Télécharger : récupère le fichier d'origine.
  • 🎬 Convertir en AVI : choisir définition + piste audio → suivre la progression → ⬇ Télécharger l'AVI une fois terminé.

Les fichiers convertis restent aussi dans le dossier OUTPUT_DIR.

Authentification Keycloak (OIDC)

L'app peut exiger une connexion Keycloak (flow Authorization Code, session par cookie). Elle est désactivée tant que OIDC_ISSUER est vide — pratique en dev local. Une fois configurée, tout utilisateur authentifié du realm a accès ; login/logout et nom de l'utilisateur sont gérés dans l'app.

1. Créer le client dans Keycloak

  • Clients → Create client : type OpenID Connect, Client ID mkv2avi.
  • Client authentication : On (client confidentiel) → un secret est généré (onglet Credentials).
  • Valid redirect URIs : https://mkv2avi.mondomaine.fr/auth/callback
  • Valid post logout redirect URIs : https://mkv2avi.mondomaine.fr/
  • Web origins : + (ou l'URL exacte).

2. Renseigner les variables

cp .env.example .env
# puis éditer .env :
#   OIDC_ISSUER=https://keycloak.mondomaine.fr/realms/mon-realm
#   OIDC_CLIENT_ID=mkv2avi
#   OIDC_CLIENT_SECRET=...(onglet Credentials)
#   SESSION_SECRET=$(openssl rand -hex 32)
#   SESSION_HTTPS_ONLY=true      # si servi en HTTPS via Nginx Proxy Manager
docker compose up -d --build

Derrière Nginx Proxy Manager (TLS) : uvicorn tourne avec --proxy-headers, donc l'URL de callback est déduite en https. En cas de souci, forcez-la avec OIDC_REDIRECT_URI. Activez SESSION_HTTPS_ONLY=true pour des cookies Secure.

Stack tout-en-un (Keycloak inclus)

Pour tester/déployer Keycloak + PostgreSQL + l'app d'un coup, un compose dédié avec un realm pré-importé (client mkv2avi + utilisateur de test) est fourni :

# 1. Rendre Keycloak résolvable sous le même nom côté navigateur ET côté conteneur
echo "127.0.0.1  keycloak.local" | sudo tee -a /etc/hosts

# 2. (optionnel) dossier de films à convertir
export MEDIA_DIR=/Volumes/data/films

# 3. Démarrer le stack
docker compose -f docker-compose.keycloak.yml up -d --build
Service URL Identifiants
App MKV → AVI http://localhost:8090 alex / alex
Console Keycloak http://localhost:8080 admin / admin

Le realm mkv2avi (keycloak/realm-mkv2avi.json) contient déjà le client confidentiel (secret : mkv2avi-secret-change-me) et un utilisateur. Change les secrets/mots de passe avant tout usage réel (variables OIDC_CLIENT_SECRET, SESSION_SECRET, KC_ADMIN_PASSWORD, KC_DB_PASSWORD, et le secret dans le realm JSON).

Pourquoi keycloak.local ? L'URL de Keycloak (l'issuer) doit être identique depuis le navigateur et depuis le conteneur de l'app. L'alias réseau Docker keycloak.local + la ligne /etc/hosts garantissent cette cohérence. En production derrière Nginx Proxy Manager, on remplace tout ça par le vrai domaine (KC_HOSTNAME + OIDC_ISSUER = https://auth.mondomaine.fr/realms/mkv2avi).

Production derrière Nginx Proxy Manager

Fichier docker-compose.prod.yml : Keycloak en mode production (start), TLS terminé par NPM. Domaines : app = https://mkv2avi.maisongrondin.fr, Keycloak = https://auth.mkv2avi.maisongrondin.fr.

1. Secrets

cp .env.prod.example .env.prod
# générer : openssl rand -hex 32   (pour OIDC_CLIENT_SECRET et SESSION_SECRET)
# OIDC_CLIENT_SECRET doit être identique au "secret" du client dans
#   keycloak/realm-mkv2avi.json (ou régénéré ensuite dans la console Keycloak).

2. Démarrage

docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --build

Les services publient sur l'hôte : Keycloak :8080, app :8090.

3. Deux Proxy Hosts dans NPM

Domaine Forward vers Options
auth.mkv2avi.maisongrondin.fr http <IP_HOTE> 8080 SSL (Let's Encrypt) · Force SSL · Websockets
mkv2avi.maisongrondin.fr http <IP_HOTE> 8090 SSL · Force SSL · Websockets

Pour l'app, ajoute cette Advanced / Custom Nginx Configuration (téléchargements de gros fichiers sans coupure — même logique que ton fix Nextcloud) :

proxy_buffering off;
proxy_request_buffering off;
client_max_body_size 0;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;

4. Points de vigilance

  • DNS interne : le conteneur mkv2avi doit résoudre auth.mkv2avi.maisongrondin.fr (il valide les tokens via cette URL). Si ton réseau ne fait pas de hairpin NAT, décommente le bloc extra_hosts du compose en pointant vers l'IP de NPM/hôte.
  • Keycloak sert en HTTP interne (KC_HTTP_ENABLED=true) et fait confiance aux en-têtes X-Forwarded-* de NPM (KC_PROXY_HEADERS=xforwarded) ; l'issuer reste figé sur l'URL publique (KC_HOSTNAME).
  • Change tous les mots de passe/secrets par défaut avant exposition.

Déploiement sur TrueNAS SCALE

Utilisable comme Custom App (Docker) : montez le dataset des films sur /media (en lecture seule) et un dataset de sortie sur /output, exposez le port 8000.

CI/CD (Gitea Actions)

Workflow .gitea/workflows/release.ymllivraison par tag :

git tag v0.1.0
git push origin v0.1.0

À chaque tag vX.Y.Z, la pipeline :

  1. build l'image Docker ;
  2. la pousse dans le registry Giteagit.maisongrondin.fr/alexandre/mkv2avi:X.Y.Z (+ :latest) ;
  3. crée une release Gitea avec docker-compose.prod.yml et .env.prod.example en pièces jointes.

L'authentification au registry utilise le token automatique du runner (secrets.GITEA_TOKEN), aucun secret à configurer. Pour cibler un autre registry (Distribution), changez REGISTRY/IMAGE en tête du workflow et ajoutez un docker login avec vos identifiants en secrets.

Prérequis : Actions activées sur le dépôt, un Act Runner avec accès Docker et le label ubuntu-latest. Le déploiement se fait ensuite manuellement (voir Production ci-dessus) : docker compose --env-file .env.prod -f docker-compose.prod.yml up -d.

Variables d'environnement

Variable Défaut Rôle
MEDIA_DIR /media Dossier parcouru (monté en lecture seule)
OUTPUT_DIR /output Dossier des AVI convertis
MAX_WORKERS 1 Conversions simultanées (1 = en série)
MAX_RESULTS 400 Nb max de fichiers listés par recherche
OIDC_ISSUER (vide) URL du realm Keycloak (vide = auth off)
OIDC_CLIENT_ID (vide) Client ID Keycloak
OIDC_CLIENT_SECRET (vide) Secret du client confidentiel
OIDC_REDIRECT_URI (auto) Force l'URL de callback si besoin
SESSION_SECRET (à changer) Clé de signature des cookies de session
SESSION_HTTPS_ONLY false Cookies Secure (mettre true en HTTPS)

Développement local (sans Docker)

pip install -r requirements.txt
# ffmpeg avec le filtre zscale requis pour le HDR (sinon HDR non géré)
MEDIA_DIR=/chemin/films OUTPUT_DIR=./output \
  uvicorn main:app --app-dir app --reload --port 8000