Tu Nombre commited on
Commit
38d8665
Β·
1 Parent(s): 907148e

fase 2: cliente lee config (voz, subtitulos)

Browse files
Files changed (2) hide show
  1. cliente_template.py +25 -3
  2. main.py +6 -6
cliente_template.py CHANGED
@@ -13,6 +13,19 @@ import edge_tts
13
  from moviepy.editor import VideoFileClip, AudioFileClip, TextClip, CompositeVideoClip
14
 
15
  NICHO = "NICHO_PLACEHOLDER"
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  CLIENT_EMAIL = "EMAIL_PLACEHOLDER"
17
  HF_REPO = "REPO_PLACEHOLDER"
18
 
@@ -52,7 +65,16 @@ async def pipeline():
52
  guion = generar_guion()
53
  log("Guion listo")
54
  STATUS = "Generando voz..."
55
- await edge_tts.Communicate(guion, "es-ES-AlvaroNeural").save("voz.mp3")
 
 
 
 
 
 
 
 
 
56
  log("Voz lista")
57
  STATUS = "Descargando fondo..."
58
  h = {"Authorization": PEXELS_KEY}
@@ -94,9 +116,9 @@ async def pipeline():
94
  palabras = guion.split()
95
  frases = [" ".join(palabras[i:i+6]) for i in range(0,len(palabras),6)]
96
  t_f = voz.duration / max(len(frases),1)
97
- txts = [TextClip(t.upper(), fontsize=72, color="#D4AF37", font="DejaVu-Sans-Bold",
98
  stroke_color="black", stroke_width=2, method="caption",
99
- size=(clip.w*0.8,None)).set_start(i*t_f).set_duration(t_f).set_pos(("center",0.75), relative=True)
100
  for i,t in enumerate(frases)]
101
  final = CompositeVideoClip([clip]+txts).set_audio(voz)
102
  final.write_videofile("out.mp4", fps=15, codec="libx264", preset="ultrafast", logger=None, threads=2)
 
13
  from moviepy.editor import VideoFileClip, AudioFileClip, TextClip, CompositeVideoClip
14
 
15
  NICHO = "NICHO_PLACEHOLDER"
16
+ import json as _json
17
+ try:
18
+ CONFIG = _json.loads("""CONFIG_PLACEHOLDER""")
19
+ except:
20
+ CONFIG = {}
21
+
22
+ # Mapeo de voces edge-tts
23
+ VOCES = {
24
+ "es": {"masculina": "es-ES-AlvaroNeural", "femenina": "es-ES-ElviraNeural"},
25
+ "en": {"masculina": "en-US-GuyNeural", "femenina": "en-US-JennyNeural"},
26
+ "pt": {"masculina": "pt-BR-AntonioNeural", "femenina": "pt-BR-FranciscaNeural"},
27
+ "fr": {"masculina": "fr-FR-HenriNeural", "femenina": "fr-FR-DeniseNeural"}
28
+ }
29
  CLIENT_EMAIL = "EMAIL_PLACEHOLDER"
30
  HF_REPO = "REPO_PLACEHOLDER"
31
 
 
65
  guion = generar_guion()
66
  log("Guion listo")
67
  STATUS = "Generando voz..."
68
+ voz_ia_on = CONFIG.get("voz_ia", True)
69
+ if voz_ia_on:
70
+ idioma_v = CONFIG.get("idioma", "es")
71
+ genero_v = CONFIG.get("voz_genero", "masculina")
72
+ voz_seleccionada = VOCES.get(idioma_v, VOCES["es"]).get(genero_v, "es-ES-AlvaroNeural")
73
+ await edge_tts.Communicate(guion, voz_seleccionada).save("voz.mp3")
74
+ else:
75
+ # Sin voz IA: crear audio en silencio
76
+ import subprocess
77
+ subprocess.run(["ffmpeg","-y","-f","lavfi","-i","anullsrc=r=44100:cl=mono","-t","60","voz.mp3"], capture_output=True)
78
  log("Voz lista")
79
  STATUS = "Descargando fondo..."
80
  h = {"Authorization": PEXELS_KEY}
 
116
  palabras = guion.split()
117
  frases = [" ".join(palabras[i:i+6]) for i in range(0,len(palabras),6)]
118
  t_f = voz.duration / max(len(frases),1)
119
+ txts = [TextClip(t.upper(), fontsize=72, color=CONFIG.get("color_subtitulos","#D4AF37"), font="DejaVu-Sans-Bold",
120
  stroke_color="black", stroke_width=2, method="caption",
121
+ size=(clip.w*0.8,None)).set_start(i*t_f).set_duration(t_f).set_pos(("center", {"arriba":0.15,"centro":0.5,"abajo":0.75}.get(CONFIG.get("posicion_subtitulos","abajo"),0.75)), relative=True)
122
  for i,t in enumerate(frases)]
123
  final = CompositeVideoClip([clip]+txts).set_audio(voz)
124
  final.write_videofile("out.mp4", fps=15, codec="libx264", preset="ultrafast", logger=None, threads=2)
main.py CHANGED
@@ -114,7 +114,7 @@ cargar_clientes()
114
  # ══════════════════════════════════════════
115
  # CREAR SPACE EN HUGGING FACE
116
  # ══════════════════════════════════════════
117
- async def crear_space(nicho: str, email: str, tipo: str = "largo") -> str:
118
  space_id = f"tb-{re.sub(r'[^a-z0-9]','', nicho.lower()[:12])}-{int(time.time())%9999}"
119
  cuentas = [
120
  (os.environ.get("HF_TOKEN_5",""), os.environ.get("HF_USER_5","Alejandro")),
@@ -131,7 +131,7 @@ async def crear_space(nicho: str, email: str, tipo: str = "largo") -> str:
131
  headers = {"Authorization": f"Bearer {token_actual}", "Content-Type": "application/json"}
132
 
133
  with open("cliente_template.py", "r") as _f:
134
- main_code = _f.read().replace("NICHO_PLACEHOLDER", nicho).replace("EMAIL_PLACEHOLDER", email).replace("REPO_PLACEHOLDER", f"{hf_user_actual}/{space_id}").replace("GROQ_PLACEHOLDER", os.environ.get("GROQ_KEY","")).replace("PEXELS_PLACEHOLDER", os.environ.get("PEXELS_KEY","")).replace("TIPO_PLACEHOLDER", tipo)
135
 
136
  req = "gradio\ngroq\nedge-tts\nmoviepy==1.0.3\nrequests\nhttpx\ngoogle-api-python-client\ngoogle-auth\ngoogle-auth-oauthlib\nimageio\nimageio-ffmpeg\ndecorator\ntqdm\nPillow\nnumpy\nopencv-python-headless"
137
 
@@ -661,14 +661,14 @@ async def crear(request: Request):
661
  canales_actuales = len(CLIENTES.get(email, {}).get("canales", []))
662
  if canales_actuales >= limite:
663
  return JSONResponse({"error": f"Has alcanzado el limite de tu plan {plan} ({limite} canales)"}, status_code=400)
664
- # Crear el canal
665
- resultado = await crear_space(nicho, email, tipo)
 
 
666
  if not resultado:
667
  return JSONResponse({"error": "No se pudo crear el canal"}, status_code=500)
668
  u = resultado["url"]
669
  repo = resultado["repo"]
670
- # Parsear preferencias del cliente con Groq
671
- config_parsed = await parsear_config_groq(config_libre)
672
  # Guardar en CLIENTES
673
  if email not in CLIENTES:
674
  CLIENTES[email] = {"canales": [], "plan": plan}
 
114
  # ══════════════════════════════════════════
115
  # CREAR SPACE EN HUGGING FACE
116
  # ══════════════════════════════════════════
117
+ async def crear_space(nicho: str, email: str, tipo: str = "largo", config_parsed: dict = None) -> str:
118
  space_id = f"tb-{re.sub(r'[^a-z0-9]','', nicho.lower()[:12])}-{int(time.time())%9999}"
119
  cuentas = [
120
  (os.environ.get("HF_TOKEN_5",""), os.environ.get("HF_USER_5","Alejandro")),
 
131
  headers = {"Authorization": f"Bearer {token_actual}", "Content-Type": "application/json"}
132
 
133
  with open("cliente_template.py", "r") as _f:
134
+ main_code = _f.read().replace("NICHO_PLACEHOLDER", nicho).replace("EMAIL_PLACEHOLDER", email).replace("REPO_PLACEHOLDER", f"{hf_user_actual}/{space_id}").replace("GROQ_PLACEHOLDER", os.environ.get("GROQ_KEY","")).replace("PEXELS_PLACEHOLDER", os.environ.get("PEXELS_KEY","")).replace("TIPO_PLACEHOLDER", tipo).replace("CONFIG_PLACEHOLDER", __import__("json").dumps(config_parsed or {}))
135
 
136
  req = "gradio\ngroq\nedge-tts\nmoviepy==1.0.3\nrequests\nhttpx\ngoogle-api-python-client\ngoogle-auth\ngoogle-auth-oauthlib\nimageio\nimageio-ffmpeg\ndecorator\ntqdm\nPillow\nnumpy\nopencv-python-headless"
137
 
 
661
  canales_actuales = len(CLIENTES.get(email, {}).get("canales", []))
662
  if canales_actuales >= limite:
663
  return JSONResponse({"error": f"Has alcanzado el limite de tu plan {plan} ({limite} canales)"}, status_code=400)
664
+ # Parsear preferencias del cliente con Groq ANTES de crear
665
+ config_parsed = await parsear_config_groq(config_libre)
666
+ # Crear el canal pasando la config
667
+ resultado = await crear_space(nicho, email, tipo, config_parsed)
668
  if not resultado:
669
  return JSONResponse({"error": "No se pudo crear el canal"}, status_code=500)
670
  u = resultado["url"]
671
  repo = resultado["repo"]
 
 
672
  # Guardar en CLIENTES
673
  if email not in CLIENTES:
674
  CLIENTES[email] = {"canales": [], "plan": plan}