omarbajouk's picture
Update src/ui.py
26908ae verified
import gradio as gr
import os
from .config import THEMES
from .tts_utils import get_edge_voices, init_edge_voices
from .capsule_builder import (
build_capsule, table_capsules, assemble_final, supprimer_capsule, deplacer_capsule
)
def build_ui():
print("[INIT] Lancement de Gradio...")
init_edge_voices()
with gr.Blocks(title="Créateur de Capsules CPAS – Version avec vidéo présentateur",
theme=gr.themes.Soft()) as demo:
gr.Markdown("## 🎬 Créateur de Capsules CPAS – Version avec vidéo présentateur")
gr.Markdown("**Nouveau** : Utilisez directement une vidéo de présentateur au lieu d'une image.")
with gr.Tab("Créer une capsule"):
with gr.Row():
with gr.Column():
image_fond = gr.Image(label="🖼 Image de fond", type="filepath")
fond_mode = gr.Radio(["plein écran", "moitié gauche", "moitié droite", "moitié bas"],
label="Mode d'affichage du fond", value="plein écran")
logo_path = gr.Image(label="🏛 Logo", type="filepath")
logo_pos = gr.Radio(["haut-gauche","haut-droite","centre"],
label="Position logo", value="haut-gauche")
video_presentateur = gr.File(label="🎬 Vidéo ou image du présentateur", type="filepath")
position_presentateur = gr.Radio(["bas-droit","bas-gauche","haut-droit","haut-gauche","centre"],
label="Position", value="bas-droit")
plein = gr.Checkbox(label="Plein écran", value=False)
with gr.Column():
titre = gr.Textbox(label="Titre", value="")
sous_titre = gr.Textbox(label="Sous-titre", value="")
theme = gr.Radio(list(THEMES.keys()), label="Thème", value="Bleu Professionnel")
langue = gr.Radio(["fr", "nl"], label="Langue de la voix", value="fr")
def maj_voix(lang):
try:
voices = get_edge_voices(lang)
return gr.update(choices=voices, value=voices[0] if voices else None)
except Exception:
return gr.update(choices=[], value=None)
speaker_id = gr.Dropdown(
label="🎙 Voix Edge-TTS",
choices=get_edge_voices("fr"),
value="fr-FR-DeniseNeural",
info="Liste dynamique des voix Edge-TTS (FR & NL)"
)
langue.change(maj_voix, [langue], [speaker_id])
voix_type = gr.Radio(["Féminine","Masculine"], label="Voix IA", value="Féminine")
moteur_voix = gr.Radio(["Edge-TTS (recommandé)", "gTTS (fallback)"],
label="Moteur voix", value="Edge-TTS (recommandé)")
texte_voix = gr.Textbox(label="Texte voix off", lines=4,
value="")
texte_ecran = gr.Textbox(label="Texte à l'écran", lines=4,
value="")
btn = gr.Button("🎬 Créer Capsule", variant="primary")
sortie = gr.Video(label="Capsule générée")
srt_out = gr.File(label="Sous-titres .srt")
statut = gr.Markdown()
with gr.Tab("Gestion & Assemblage"):
gr.Markdown("### 🗂 Gestion des capsules")
liste = gr.Dataframe(
headers=["N°","Titre","Langue","Durée","Thème","Voix","Fichier"],
value=table_capsules(),
interactive=False
)
with gr.Row():
index = gr.Number(label="Index capsule", value=1, precision=0)
btn_up = gr.Button("⬆️ Monter")
btn_down = gr.Button("⬇️ Descendre")
btn_del = gr.Button("🗑 Supprimer")
message = gr.Markdown()
btn_up.click(lambda i: deplacer_capsule(i, "up"), [index], [message, liste])
btn_down.click(lambda i: deplacer_capsule(i, "down"), [index], [message, liste])
btn_del.click(supprimer_capsule, [index], [message, liste])
gr.Markdown("### 🎬 Assemblage final")
btn_asm = gr.Button("🎥 Assembler la vidéo complète", variant="primary")
sortie_finale = gr.Video(label="Vidéo finale")
btn_asm.click(lambda: assemble_final(), [], [sortie_finale, message])
# --- Export ZIP intégré ---
from .capsule_builder import export_project_zip
btn_zip = gr.Button("📦 Télécharger projet complet (ZIP)", variant="secondary")
zip_file = gr.File(label="ZIP exporté")
def zip_action():
path = export_project_zip()
if path and os.path.exists(path):
return path
else:
raise gr.Error("Erreur : impossible de générer le ZIP.")
btn_zip.click(zip_action, [], [zip_file])
def creer_capsule_ui(t, st, tv, te, th, img, fmode, logo, pos_logo, vp, vx, pos_p, plein, motor, lang, speaker):
try:
vid, msg, srt = build_capsule(t, st, tv, te, th,
img, logo, pos_logo, fmode,
vp, vx, pos_p, plein,
motor, lang, speaker=speaker)
return vid, srt, msg, table_capsules()
except Exception as e:
import traceback
return None, None, f"❌ Erreur: {e}\n\n{traceback.format_exc()}", table_capsules()
btn.click(
creer_capsule_ui,
[titre, sous_titre, texte_voix, texte_ecran, theme,
image_fond, fond_mode, logo_path, logo_pos,
video_presentateur, voix_type, position_presentateur,
plein, moteur_voix, langue, speaker_id],
[sortie, srt_out, statut, liste]
)
return demo