#!/bin/bash # ============================================================================= # COMPRESSION ROAD-TRIP — STRATÉGIE HYBRIDE + ENCODAGE PARALLÈLE # Source : GoPro Hero 9, rushs en HEVC 1080p # # Sorties (noms de fichiers INCHANGÉS par rapport à l'ancien script) : # .mp4 1080p natif, HEVC/H.265, tag hvc1 # → gros fichier, là où les 40 % d'économie comptent # _mobile.mp4 720p, H.264, tag avc1, profil High # → fichier chargé par défaut, se lit sur TOUS # les navigateurs sans exception # # PARALLÉLISME # Deux niveaux, tous deux actifs par défaut : # 1. Les deux paliers d'un même rush sont indépendants → lancés ensemble. # 2. JOBS rushs traités simultanément (pool géré par xargs -P). # Le nombre de threads par encodeur est borné pour ne pas surcharger : # x265 sature vite (scaling sublinéaire au-delà de ~6-8 threads), donc # plusieurs encodages courts valent mieux qu'un seul très parallélisé. # # Variables d'environnement : # JOBS=N nombre de rushs en parallèle # (défaut : cœurs performance / 4, minimum 1) # THREADS=N threads par encodeur (défaut : cœurs / JOBS) # ENCODER=cpu (défaut) libx265 + libx264 — meilleure qualité/octet # ENCODER=vt VideoToolbox — ~10x plus rapide sur Apple Silicon # (⚠️ le parallélisme n'y sert à rien : le bloc média # de la puce est une ressource fixe → JOBS=1 forcé) # PRESET=medium preset CPU : ultrafast…placebo # CRF_HEVC=26 qualité du 1080p HEVC (échelle x265) # CRF_H264=25 qualité du 720p H.264 (échelle x264 — PAS la même !) # VTQ_HD=60 VTQ_SD=58 qualité VideoToolbox (1-100, plus haut = meilleur) # FPS_MAX=60 plafonne le framerate (un rush 30p reste en 30p, # un rush 120p/240p est ramené à 60) # FORCE=1 réencode même si le fichier de sortie existe # # Exemples : # ./compress.sh mon-voyage # JOBS=4 ./compress.sh mon-voyage # JOBS=1 ./compress.sh mon-voyage # séquentiel + barre de progression # ENCODER=vt ./compress.sh mon-voyage # ============================================================================= set -uo pipefail shopt -s nocaseglob nullglob # --- 0. MODE INTERNE --------------------------------------------------------- # Quand le script est rappelé par xargs pour traiter UN rush, il arrive ici. if [ "${1:-}" = "--encode-one" ]; then INTERNAL=1 BASE_DIR="${RT_BASE_DIR:-.}" TARGET="${2:?--encode-one attend un fichier}" else INTERNAL=0 BASE_DIR="${1:-.}" fi SOURCE_DIR="$BASE_DIR/rushs" DEST_DIR="$BASE_DIR/videos" # --- 1. CONFIGURATION -------------------------------------------------------- ENCODER="${ENCODER:-cpu}" PRESET="${PRESET:-medium}" CRF_HEVC="${CRF_HEVC:-26}" CRF_H264="${CRF_H264:-25}" VTQ_HD="${VTQ_HD:-60}" VTQ_SD="${VTQ_SD:-58}" FPS_MAX="${FPS_MAX:-60}" FORCE="${FORCE:-0}" # Détection des cœurs. Sur Apple Silicon on ne compte que les cœurs # PERFORMANCE : les cœurs d'efficience sont si lents qu'ils deviennent des # traînards dans un pool x265 et pénalisent l'encodage entier. detect_cores() { local c="" c=$(sysctl -n hw.perflevel0.logicalcpu 2>/dev/null); [ -n "$c" ] && { echo "$c"; return; } c=$(sysctl -n hw.logicalcpu 2>/dev/null); [ -n "$c" ] && { echo "$c"; return; } c=$(nproc 2>/dev/null); [ -n "$c" ] && { echo "$c"; return; } echo 4 } CORES="${CORES:-$(detect_cores)}" # En VideoToolbox, le parallélisme ne sert à rien (un seul moteur d'encodage # matériel sur les puces M de base) — sauf si l'utilisateur force JOBS. JOBS_EXPLICIT=0 [ -n "${JOBS+x}" ] && JOBS_EXPLICIT=1 if [ "$ENCODER" = "vt" ] && [ "$JOBS_EXPLICIT" = "0" ]; then JOBS=1 else JOBS="${JOBS:-$(( CORES / 4 ))}" fi [ "$JOBS" -lt 1 ] 2>/dev/null && JOBS=1 [ -z "$JOBS" ] && JOBS=1 THREADS="${THREADS:-$(( CORES / JOBS ))}" [ "$THREADS" -lt 2 ] 2>/dev/null && THREADS=2 # Le palier 720p H.264 est 3 à 5× plus rapide que le 1080p HEVC : on lui donne # moitié moins de threads. Il finit largement avant, et la fenêtre pendant # laquelle les deux paliers tournent ensemble ne surcharge pas la machine. THREADS_SD=$(( THREADS / 2 )) [ "$THREADS_SD" -lt 2 ] && THREADS_SD=2 # --- 2. FONCTION D'ENCODAGE -------------------------------------------------- # encode