mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
Service ffmpeg-api réécrit (ffmpeg-service/app/) : - Appels FFmpeg asynchrones : le service ne se fige plus pendant un rendu - Vidéo récupérée par téléchargement (GET /files/…) au lieu de base64 en JSON - Vraies erreurs HTTP ; échec explicite si la voix demandée est impossible - 30 voix Gemini + ton de lecture (dynamique, chaleureux, promo, calme), clé en en-tête, modèle configurable avec repli - Edge TTS 7 (minutage des mots restauré), secours en voix françaises - Voix traitée : filtre, compression, niveau constant ; musique bouclée et baissée automatiquement sous la voix ; mix final à -14 LUFS - Sous-titres calés mot à mot (Whisper pour Gemini et la voix d'origine, à la place de ffsubsync), style Montserrat, placés hors des boutons Reels - Vidéo : plus de retouche luminosité forcée, scaling lanczos, HDR iPhone converti, BT.709, AAC 48 kHz 192k ; la vidéo s'allonge si la voix dépasse - Grand logo de fin affiché après la voix ; FFmpeg 7.0.2 épinglé, polices et modèle Whisper intégrés à l'image ; tests pytest et ruff Application : - Sélecteur de voix partagé (4 pages) : moteur, 30 voix, ton, écoute - Reel images : minutage réel des mots, interrupteur voix respecté - sync-info ne génère plus de voix à chaque frappe (estimation locale) - Stabilisation désactivée par défaut, route /reels/preview inutilisée retirée - Log « [ReelQueue] Worker démarré » pour vérifier la version déployée Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ze4bs7tpF1KGWUk6ZZSZ4
32 lines
1.2 KiB
Python
32 lines
1.2 KiB
Python
from app.align import Word, align_words, display_tokens, normalize
|
|
|
|
|
|
def test_normalize_strips_accents_and_punctuation():
|
|
assert normalize("Été,") == "ete"
|
|
assert normalize("«") == ""
|
|
|
|
|
|
def test_display_tokens_attach_isolated_punctuation():
|
|
assert display_tokens("Bonjour ! Venez vite .") == ["Bonjour!", "Venez", "vite."]
|
|
|
|
|
|
def test_align_uses_engine_timings_and_keeps_display_text():
|
|
spoken = [Word("Bonjour", 0.05, 0.6), Word("découvrez", 0.99, 1.35), Word("nos", 1.35, 1.44)]
|
|
words = align_words("Bonjour, découvrez nos", spoken)
|
|
assert [w.text for w in words] == ["Bonjour,", "découvrez", "nos"]
|
|
assert words[1].start == 0.99
|
|
|
|
|
|
def test_unmatched_words_are_interpolated_between_neighbours():
|
|
spoken = [Word("les", 0.0, 0.2), Word("prix", 1.0, 1.3)]
|
|
words = align_words("les super promos prix", spoken)
|
|
assert [w.text for w in words] == ["les", "super", "promos", "prix"]
|
|
assert 0.2 <= words[1].start < words[2].start < 1.0
|
|
assert all(b.start > a.start for a, b in zip(words, words[1:]))
|
|
|
|
|
|
def test_without_spoken_words_text_is_spread_over_duration():
|
|
words = align_words("un deux trois", [], total_duration=3.0)
|
|
assert words[0].start == 0.0
|
|
assert abs(words[-1].end - 3.0) < 1e-6
|