""" Convierte TREBEP.md a audio dividido por Títulos. Genera un MP3 por Título (8 Títulos + Disposiciones) en audios/mp3/bloque1/. Usa edge_tts (es-ES-AlvaroNeural) + ffmpeg, igual que md_a_audio_con_edge_y_metadatos.py """ import asyncio import edge_tts import re import os from pathlib import Path def limpiar_markdown(texto): texto = re.sub(r'```.*?```', ' [código] ', texto, flags=re.DOTALL) texto = re.sub(r'\|.*?\|', '', texto) texto = re.sub(r'[#*_~`>]', '', texto) return ' '.join(texto.split()) def dividir_por_titulos(md_path): """ Devuelve lista de (nombre_fichero, titulo_meta, texto_seccion). Las secciones son los 8 Títulos + un bloque final de Disposiciones. """ texto = Path(md_path).read_text(encoding='utf-8') secciones = [] # Separar por ## TÍTULO partes = re.split(r'(?=^## TÍTULO)', texto, flags=re.MULTILINE) for parte in partes: if not parte.strip(): continue match = re.match(r'^## (TÍTULO ([IVX]+)) · (.+)', parte, re.MULTILINE) if match: titulo_num = match.group(2) titulo_texto = match.group(3).strip() num_romano = {'I': 1, 'II': 2, 'III': 3, 'IV': 4, 'V': 5, 'VI': 6, 'VII': 7, 'VIII': 8}.get(titulo_num, 0) nombre = f'trebep_titulo{num_romano:02d}_audio' meta = f'TREBEP · Título {titulo_num}: {titulo_texto}' # Si hay disposiciones al final de TÍTULO VIII, separarlas idx_disp = parte.find('\n#### Disposición adicional primera') if idx_disp != -1: secciones.append((nombre, meta, parte[:idx_disp])) disp_texto = parte[idx_disp:] secciones.append(('trebep_disposiciones_audio', 'TREBEP · Disposiciones adicionales, transitorias y finales', disp_texto)) else: secciones.append((nombre, meta, parte)) else: # Bloque inicial (antes del primer Título): ignorar si es mínimo if len(parte.strip()) > 100: secciones.append(('trebep_intro_audio', 'TREBEP · Introducción', parte)) return secciones async def generar_audio(nombre, meta, texto, mp3_dir): mp3_path = mp3_dir / f'{nombre.replace("_audio", "")}.mp3' temp_path = mp3_dir / f'{nombre}.temp.mp3' if mp3_path.exists(): print(f'⏭️ Ya existe, omitiendo: {mp3_path.name}') return texto_limpio = limpiar_markdown(texto) print(f'🎙️ Generando: {mp3_path.name} ({len(texto_limpio.split())} palabras)...') comunicar = edge_tts.Communicate(texto_limpio, 'es-ES-AlvaroNeural') await comunicar.save(str(temp_path)) meta_escaped = meta.replace('"', '\\"') comando = ( f'ffmpeg -i "{temp_path}" -codec:a libmp3lame -b:a 192k -ar 44100 ' f'-metadata title="{meta_escaped}" -id3v2_version 3 -write_id3v1 1 ' f'-y "{mp3_path}" > /dev/null 2>&1' ) os.system(comando) if temp_path.exists(): temp_path.unlink() print(f'✅ Listo: {mp3_path.name} (Título: {meta})') async def main(): base_dir = Path(__file__).parent.parent md_path = base_dir / 'bloque1' / 'leyes' / 'TREBEP.md' mp3_dir = base_dir / 'audios' / 'mp3' / 'bloque1' mp3_dir.mkdir(parents=True, exist_ok=True) secciones = dividir_por_titulos(md_path) print(f'\nTREBEP.md → {len(secciones)} secciones de audio\n') for nombre, meta, texto in secciones: await generar_audio(nombre, meta, texto, mp3_dir) print('\n🎧 Todos los audios del TREBEP generados en:', mp3_dir) if __name__ == '__main__': asyncio.run(main())