# Plan de Refonte Rust - DarkMedia-X Studio ## Contexte Le projet utilise actuellement un mix Python/Rust. L'objectif est de migrer le maximum de logique Python vers Rust pour la performance et la fiabilite. Le code compile et fonctionne sur la branche `main`. ## Etat Actuel ### Deja en Rust (Engine/src/) - `main.rs` - Point d'entree, decouverte des histoires, boucle principale - `scene.rs` - Extraction des scenes depuis les fichiers markdown - `config.rs` - Configuration depuis variables d'environnement - `generators/` - Wrappers Rust qui appellent Python via `Command::new("python")` - `wan2.rs`, `ssd.rs`, `open_sora.rs`, `ollama.rs`, `api_router.rs`, `moviepy.rs` - `renderer/` - Squelettes non-utilises (image_processor, vfx, depth, animation, postprocessing) - `progress_tracker.rs`, `optimization.rs`, `orchestrator.rs`, `ml_backend.rs` ### Encore en Python (a migrer) - `story_to_video.py` (47KB) - Orchestrateur principal video - `asset_generator.py` (24KB) - Generation d'assets - `renderers/moviepy_renderer.py` - Rendu video MoviePy - `audio_analyzer.py` - Analyse BPM avec librosa - `prompt_remixer.py` - Remix de prompts - `chroma_store.py` / `qdrant_store.py` - Stores vectoriels - `vfx/opencv_effects.py` - Effets visuels OpenCV - `optimizations/memory_manager.py` - Gestion memoire ### StudioHub (Rust - GUI) - `StudioHub/src/main.rs` (55KB) - Application egui complete, deja en Rust --- ## Etapes de Migration (par priorite) ### Phase 1: Rendu Video Natif Rust (Remplacer MoviePy) **Fichiers concernes:** `Engine/src/generators/moviepy.rs`, `Engine/renderers/moviepy_renderer.py` **Objectif:** Remplacer l'appel Python MoviePy par du Rust natif. **Implementation:** 1. Ajouter ces dependances dans `Engine/Cargo.toml`: ```toml ffmpeg-next = "7" # ou ffmpeg-cli-wrapper si ffmpeg-next pose probleme image = "0.25" ``` 2. Creer `Engine/src/video_assembler.rs`: ```rust // Assembler les images PNG en video MP4 via ffmpeg CLI // Input: dossier assets/images/ avec scene_1.png, scene_2.png, etc. // Output: output.mp4 dans le dossier de l'histoire // // Algorithme: // 1. Lister toutes les images scene_*.png triees par numero // 2. Pour chaque image, appliquer un effet Ken Burns (zoom lent) via ffmpeg // 3. Concatener les clips en une seule video // 4. Ajouter la musique si presente (fichier music.mp3 dans le dossier) // 5. Ajouter les sous-titres si texte overlay present // // Commande ffmpeg type pour chaque scene: // ffmpeg -loop 1 -i scene_1.png -vf "zoompan=z='min(zoom+0.001,1.5)':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=150:s=1080x1920" -t 5 -c:v libx264 clip_1.mp4 // // Concatenation: // ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4 // // Ajout musique: // ffmpeg -i output.mp4 -i music.mp3 -c:v copy -c:a aac -shortest final.mp4 ``` 3. Dans `main.rs`, remplacer `MoviePyRenderer` par `VideoAssembler` dans TOUS les modes (wan2, ssd, opensora, etc.) **Note importante:** L'approche la plus pragmatique est d'utiliser ffmpeg en CLI (deja installe sur la machine) plutot que des bindings Rust complexes. C'est ce que fait deja le code pour l'extraction de frames dans wan2.rs. --- ### Phase 2: Effets Visuels Natifs (Remplacer OpenCV Python) **Fichiers concernes:** `Engine/src/renderer/vfx.rs`, `Engine/src/renderer/image_processor.rs`, `Engine/vfx/opencv_effects.py` **Objectif:** Les squelettes Rust existent deja mais ne sont pas utilises. Les completer. **Implementation:** 1. Les fichiers `renderer/vfx.rs` et `renderer/image_processor.rs` ont deja du code fonctionnel (grain, blur, glitch, vignette, saturation). Il faut: - Les connecter dans le pipeline principal (main.rs) - Appliquer les effets sur chaque image AVANT l'assemblage video - Ajouter un parametre VFX dans la config (ex: `VFX_PROFILE=cinematic_dark`) 2. Dans `main.rs`, apres generation de chaque image: ```rust // Charger l'image let img = image::open(&img_file)?; // Appliquer les effets selon le profil let processed = renderer::vfx::apply_vfx(img, vfx_profile)?; // Sauvegarder processed.save(&img_file)?; ``` --- ### Phase 3: Analyse Audio Rust (Remplacer librosa) **Fichiers concernes:** `Engine/audio_analyzer.py`, nouveau `Engine/src/audio_analyzer.rs` **Objectif:** Extraire BPM et beats en Rust natif. **Implementation:** 1. Ajouter dans `Engine/Cargo.toml`: ```toml rodio = "0.19" symphonia = { version = "0.5", features = ["mp3", "wav", "ogg"] } rustfft = "6" ``` 2. Creer `Engine/src/audio_analyzer.rs`: ```rust // Analyse audio: BPM detection et beat timing // // Algorithme simplifie: // 1. Decoder le fichier audio (MP3/WAV) avec symphonia // 2. Convertir en mono, resampler a 22050 Hz // 3. Calculer onset strength (energie spectrale frame par frame) // - FFT sur des fenetres de 2048 samples, hop 512 // - Calculer la difference d'energie entre frames consecutives // 4. Autocorrelation pour detecter le BPM dominant // 5. Peak detection sur onset strength pour les positions de beats // // Struct de retour: pub struct AudioAnalysis { pub bpm: f32, pub beat_times: Vec, // en secondes pub intensity_curve: Vec, // normalise 0.0-1.0 pub duration: f32, // duree totale en secondes } ``` --- ### Phase 4: Store Vectoriel Qdrant Natif **Fichiers concernes:** `Engine/qdrant_store.py`, nouveau `Engine/src/qdrant_client.rs` **Objectif:** Appels Qdrant directement depuis Rust. **Implementation:** 1. Ajouter dans `Engine/Cargo.toml`: ```toml qdrant-client = "1" ``` 2. Creer `Engine/src/qdrant_client.rs`: ```rust // Client Qdrant pour le RAG // Variables d'env utilisees: // QDRANT_URL (deja dans .env racine) // QDRANT_API_KEY (deja dans .env racine) // QDRANT_COLLECTION_NAME (deja dans .env racine) // // Fonctions: // - search_similar(query_vector, limit) -> Vec // - upsert_story(story_id, vector, metadata) // - check_duplicate(vector, threshold) -> bool ``` --- ### Phase 5: Prompt Remixer Natif **Fichiers concernes:** `Engine/prompt_remixer.py`, nouveau `Engine/src/prompt_remixer.rs` **Objectif:** Remixer les prompts localement ou via API. **Note:** Comme l'utilisateur n'utilise plus d'API externes (sauf Qdrant), cette fonctionnalite devrait utiliser Ollama en local: ```rust // Appeler Ollama pour remixer un prompt avec un style musical // POST http://127.0.0.1:11434/api/generate // Body: { "model": "llama3", "prompt": "Remix this image prompt with musical energy: ..." } ``` --- ### Phase 6: Nettoyage et Unification 1. **Supprimer les fichiers Python redondants** une fois les equivalents Rust fonctionnels 2. **Unifier la configuration** - tout dans `config.rs`, plus de `.env` separes 3. **Supprimer les warnings** - `cargo fix --bin asset_generator` (97 warnings actuels) 4. **Connecter les modules renderer/** qui sont des squelettes inutilises (postprocessing.rs, animation.rs, depth.rs) --- ## Fichiers Cles a Modifier | Fichier | Action | |---------|--------| | `Engine/Cargo.toml` | Ajouter dependances (ffmpeg, symphonia, rustfft, qdrant-client) | | `Engine/src/main.rs` | Remplacer MoviePyRenderer par VideoAssembler, ajouter VFX pipeline | | `Engine/src/video_assembler.rs` | NOUVEAU - Assemblage video via ffmpeg CLI | | `Engine/src/audio_analyzer.rs` | NOUVEAU - Analyse BPM/beats | | `Engine/src/qdrant_client.rs` | NOUVEAU - Client Qdrant natif | | `Engine/src/prompt_remixer.rs` | NOUVEAU - Remix prompts via Ollama | | `Engine/src/renderer/vfx.rs` | Connecter dans le pipeline | | `Engine/src/renderer/image_processor.rs` | Connecter dans le pipeline | | `Engine/src/generators/moviepy.rs` | A SUPPRIMER apres Phase 1 | ## Architecture Cible ``` Engine/src/ main.rs -- Point d'entree config.rs -- Configuration unifiee scene.rs -- Parsing markdown -> scenes video_assembler.rs -- NEW: Images -> MP4 (ffmpeg CLI) audio_analyzer.rs -- NEW: BPM/beats (natif Rust) qdrant_client.rs -- NEW: RAG vectoriel prompt_remixer.rs -- NEW: Remix via Ollama generators/ wan2.rs -- Generation Wan2 (appel Python - difficile a migrer) ssd.rs -- Generation SSD-1B (appel Python - difficile a migrer) open_sora.rs -- Generation OpenSora (appel Python - difficile a migrer) ollama.rs -- LLM local renderer/ vfx.rs -- Effets visuels (grain, glitch, vignette) image_processor.rs -- Traitement image (resize, color grade) postprocessing.rs -- Post-prod (contrast, saturation) depth.rs -- Cartes de profondeur animation.rs -- Ken Burns, pan, zoom ``` ## Ce Qui RESTE en Python (impossible a migrer) Les generateurs d'images IA (wan2, ssd, open_sora) doivent rester en Python car: - Les modeles PyTorch/diffusers n'ont pas d'equivalent Rust mature - Le code Rust les appelle deja via `Command::new("python")` ce qui est la bonne approche - Migrer necessiterait des bindings ONNX/TensorRT complexes ## Commandes Utiles ```bash # Compiler cd Engine && cargo build --release # Tester le parseur de scenes cargo run --release -- --test-parse "../../stories/Quebec/La Chasse-Galerie/story.md" # Lancer le generateur cd Engine && launch_generator.bat # Lancer le StudioHub cd StudioHub && cargo run --release ``` ## Fixes Deja Appliques (ne pas refaire) - scene.rs: Reecrit sans regex, gere "scene" et "scene" (accent) - main.rs: Mode wan2 a maintenant update_task_json + assemblage video - story_to_video.py: Fix variable scene_idx dans add_dynamic_subtitles - launch_generator.bat: IMAGE_GEN_MODE aligne sur wan2 - .env racine: Nettoye, garde seulement QDRANT_* - current_task.json: Reset a l'etat initial