mini / app1.py
Asad235's picture
Rename app.py to app1.py
c63a95a verified
Raw
History Blame Contribute Delete
8.24 kB
#!/usr/bin/env python3
"""
Voiceover Generator with MiniCPM-o-2.6 (CPU Optimized - No Whisper)
"""
import gradio as gr
import torch
import tempfile
import random
import numpy as np
from pathlib import Path
import warnings
warnings.filterwarnings('ignore')
# ============================================================
# CONFIGURATION
# ============================================================
OUTPUT_DIR = Path("./generated_voiceovers")
OUTPUT_DIR.mkdir(exist_ok=True)
VOICE_STYLES = {
"1": {"name": "Professional Narrator", "emotion": "neutral", "speed": 0.9},
"2": {"name": "Enthusiastic YouTuber", "emotion": "happy", "speed": 1.1},
"3": {"name": "Calm Teacher", "emotion": "neutral", "speed": 0.8},
"4": {"name": "Energetic Announcer", "emotion": "happy", "speed": 1.2},
"5": {"name": "Deep Documentary Voice", "emotion": "neutral", "speed": 0.75},
"6": {"name": "Friendly Explainer", "emotion": "happy", "speed": 1.0},
}
# Templates for voiceover text
INTROS = ["Watch how", "See how", "Discover how", "Learn how", "Ever wondered how"]
OUTROS = ["That's engineering in action!", "Simple mechanics, powerful results!", "That's how industry gets things done!"]
ACTION_DESCS = {
"increasing torque": ["multiplies rotational force", "boosts pulling power"],
"reducing speed": ["controls motion safely", "slows down rotation"],
"transferring power": ["sends energy efficiently", "transmits mechanical force"],
"lifting heavy loads": ["raises massive weights", "hoists heavy objects"],
"driving conveyor belts": ["moves products along", "keeps production flowing"],
}
# ============================================================
# LOAD MODEL (WITHOUT WHISPER)
# ============================================================
_model = None
_tokenizer = None
def load_model():
"""Load MiniCPM-o-2.6 without Whisper dependencies"""
global _model, _tokenizer
if _model is not None:
return _model, _tokenizer
print("πŸ”„ Loading MiniCPM-o-2.6 model...")
try:
from transformers import AutoModel, AutoTokenizer
# Load with specific config to avoid Whisper
_model = AutoModel.from_pretrained(
'openbmb/MiniCPM-o-2_6',
trust_remote_code=True,
torch_dtype=torch.float32,
low_cpu_mem_usage=True,
use_safetensors=True
)
_model = _model.eval().to('cpu')
_tokenizer = AutoTokenizer.from_pretrained(
'openbmb/MiniCPM-o-2_6',
trust_remote_code=True
)
# Initialize TTS
if hasattr(_model, 'init_tts'):
_model.init_tts()
print("βœ… Model loaded successfully!")
return _model, _tokenizer
except ImportError as e:
print(f"❌ Import Error: {e}")
print("πŸ’‘ Run: pip install transformers==4.35.0")
return None, None
except Exception as e:
print(f"❌ Model Error: {e}")
return None, None
# ============================================================
# FALLBACK TTS (Edge TTS - Works without Whisper)
# ============================================================
def generate_audio_fallback(text, voice_style, output_path):
"""Use Edge TTS as fallback (always works)"""
import asyncio
import edge_tts
voice_map = {
"1": "en-US-JennyNeural",
"2": "en-US-GuyNeural",
"3": "en-GB-SoniaNeural",
"4": "en-US-DavisNeural",
"5": "en-US-ChristopherNeural",
"6": "en-US-AnaNeural",
}
voice = voice_map.get(voice_style, "en-US-JennyNeural")
async def generate():
communicate = edge_tts.Communicate(text, voice)
await communicate.save(output_path)
asyncio.run(generate())
return output_path
# ============================================================
# GENERATE VOICEOVER
# ============================================================
def generate_natural_voiceover(raw_prompt):
"""Convert technical prompt to natural voiceover"""
if not raw_prompt:
return ""
parts = raw_prompt.split(" in ", 1)
mechanism_action = parts[0]
industry = parts[1].split(" -")[0] if len(parts) > 1 else "industrial setting"
words = mechanism_action.split()
mechanism = words[0] if words else "mechanism"
action = " ".join(words[1:]) if len(words) > 1 else "operating"
# Find action description
action_desc = None
for key, descs in ACTION_DESCS.items():
if key in action.lower():
action_desc = random.choice(descs)
break
if not action_desc:
action_desc = f"{action} with precision and reliability"
intro = random.choice(INTROS)
outro = random.choice(OUTROS)
article = "an" if mechanism[0].lower() in 'aeiou' else "a"
return f"{intro} {article} {mechanism} {action} inside {article} {industry}. This clever mechanism {action_desc}. {outro}"
def process_prompt(prompt_text, voice_choice, auto_convert):
"""Main processing function"""
if not prompt_text:
return None, "⚠️ Please enter a prompt!", ""
try:
# Generate natural text
if auto_convert:
voiceover_text = generate_natural_voiceover(prompt_text)
else:
voiceover_text = prompt_text
# Generate audio using Edge TTS (reliable fallback)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
audio_path = generate_audio_fallback(voiceover_text, voice_choice, tmp.name)
info = f"""
βœ… Voiceover Generated!
πŸ“ Prompt: {prompt_text[:80]}...
🎭 Voice: {VOICE_STYLES[voice_choice]['name']}
"""
return audio_path, info, voiceover_text
except Exception as e:
return None, f"❌ Error: {str(e)}", ""
# ============================================================
# GRADIO INTERFACE
# ============================================================
def create_interface():
with gr.Blocks(title="Voiceover Generator", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# πŸŽ™οΈ AI Voiceover Generator
**Convert technical prompts to natural voiceovers**
Example: `"planetary gear increasing torque in automotive plant"`
""")
with gr.Row():
with gr.Column():
prompt_input = gr.Textbox(
label="Technical Prompt",
placeholder="planetary gear increasing torque in automotive plant",
lines=3
)
voice_dropdown = gr.Dropdown(
choices=list(VOICE_STYLES.keys()),
label="Voice Style",
value="1"
)
auto_convert = gr.Checkbox(label="Auto-convert to natural voiceover", value=True)
generate_btn = gr.Button("Generate Voiceover", variant="primary")
with gr.Column():
audio_output = gr.Audio(label="Generated Voiceover")
info_output = gr.Textbox(label="Status", lines=5)
text_output = gr.Textbox(label="Voiceover Script", lines=4)
generate_btn.click(
fn=process_prompt,
inputs=[prompt_input, voice_dropdown, auto_convert],
outputs=[audio_output, info_output, text_output]
)
return demo
# ============================================================
# MAIN
# ============================================================
if __name__ == "__main__":
print("=" * 60)
print("πŸŽ™οΈ Voiceover Generator")
print("=" * 60)
# Install edge-tts if not present
try:
import edge_tts
except ImportError:
print("πŸ“¦ Installing edge-tts...")
import subprocess
subprocess.check_call(['pip', 'install', 'edge-tts'])
demo = create_interface()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=True
)