Translate / app.py
Athspi's picture
Update app.py
352553f verified
raw
history blame
6.34 kB
# app.py
import os
import time
import tempfile
import google.generativeai as genai
import requests
from flask import Flask, request, render_template, send_from_directory, url_for, flash
from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.audio.io.AudioFileClip import AudioFileClip
from werkzeug.utils import secure_filename
from dotenv import load_dotenv
# Initialize Flask app
load_dotenv()
app = Flask(__name__)
# Configuration
app.config.update({
'GEMINI_API_KEY': os.getenv('GEMINI_API_KEY'),
'TTS_API_URL': os.getenv('TTS_API_URL'),
'UPLOAD_FOLDER': 'uploads',
'DOWNLOAD_FOLDER': 'downloads',
'MAX_CONTENT_LENGTH': 100 * 1024 * 1024, # 100MB
'SECRET_KEY': os.urandom(24),
'ALLOWED_EXTENSIONS': {'mp4', 'mov', 'webm', 'avi'}
})
# Create directories if they don't exist
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
os.makedirs(app.config['DOWNLOAD_FOLDER'], exist_ok=True)
# Initialize Gemini AI
genai.configure(api_key=app.config['GEMINI_API_KEY'])
# Constants
VOICE_CHOICES = {
"Male (Deep Voice)": "deep_male",
"Female (Soft Tone)": "soft_female",
"Neutral (Professional)": "neutral"
}
GEMINI_PROMPT = """
You are an expert AI scriptwriter. Analyze this video and:
1. Transcribe ALL dialogue into continuous Tamil
2. Remove timestamps/speaker labels
3. Add expressive directions like [laugh] or [pause]
4. Keep natural flow and cultural context
Example Output:
[cheerful] வணக்கம்! [laugh] இன்று நிலைமை எப்படி இருக்கிறது? [serious] இதை கவனமாக கேளுங்கள்...
"""
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']
def generate_script(video_path):
"""Generate Tamil script using Gemini AI"""
try:
print("Uploading video to Gemini...")
video_file = genai.upload_file(video_path, mime_type="video/mp4")
# Wait for processing
while video_file.state.name == "PROCESSING":
time.sleep(5)
video_file = genai.get_file(video_file.name)
if video_file.state.name != "ACTIVE":
raise Exception("Gemini processing failed")
model = genai.GenerativeModel("models/gemini-pro-vision")
response = model.generate_content([GEMINI_PROMPT, video_file])
genai.delete_file(video_file.name)
return response.text.strip() if hasattr(response, 'text') else ""
except Exception as e:
print(f"Gemini Error: {str(e)}")
raise
def generate_audio(script, voice, tone):
"""Generate audio using TTS API"""
try:
response = requests.post(
app.config['TTS_API_URL'],
json={
"text": script,
"voice": voice,
"tone": tone
},
timeout=300
)
response.raise_for_status()
return response.content
except requests.exceptions.RequestException as e:
print(f"TTS API Error: {str(e)}")
raise
def process_video(input_path, audio_data, output_filename):
"""Combine video with new audio track"""
try:
with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as audio_temp:
audio_temp.write(audio_data)
audio_temp_path = audio_temp.name
video = VideoFileClip(input_path)
audio = AudioFileClip(audio_temp_path)
# Ensure audio matches video duration
if audio.duration > video.duration:
audio = audio.subclip(0, video.duration)
video.audio = audio
output_path = os.path.join(app.config['DOWNLOAD_FOLDER'], output_filename)
video.write_videofile(
output_path,
codec='libx264',
audio_codec='aac',
threads=4,
logger=None
)
return output_path
except Exception as e:
print(f"Video Processing Error: {str(e)}")
raise
finally:
if 'video' in locals(): video.close()
if 'audio' in locals(): audio.close()
if os.path.exists(audio_temp_path): os.remove(audio_temp_path)
@app.route('/', methods=['GET'])
def home():
return render_template('index.html', voices=VOICE_CHOICES)
@app.route('/process', methods=['POST'])
def process():
if 'video' not in request.files:
flash('No file selected', 'error')
return render_template('index.html', voices=VOICE_CHOICES)
file = request.files['video']
if file.filename == '':
flash('No file selected', 'error')
return render_template('index.html', voices=VOICE_CHOICES)
if not allowed_file(file.filename):
flash('Invalid file type. Allowed: MP4, MOV, WEBM, AVI', 'error')
return render_template('index.html', voices=VOICE_CHOICES)
try:
# Save uploaded file
filename = secure_filename(file.filename)
input_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(input_path)
# Get processing options
voice = request.form.get('voice', 'neutral')
tone = 'cheerful' if request.form.get('tone') == 'on' else 'neutral'
# Generate script and audio
script = generate_script(input_path)
audio_data = generate_audio(script, voice, tone)
# Process video
output_filename = f"dubbed_{filename}"
output_path = process_video(input_path, audio_data, output_filename)
flash('Processing completed successfully!', 'success')
return render_template('result.html',
video_url=url_for('download', filename=output_filename),
script=script)
except Exception as e:
flash(f'Processing failed: {str(e)}', 'error')
return render_template('index.html', voices=VOICE_CHOICES)
finally:
if 'input_path' in locals() and os.path.exists(input_path):
os.remove(input_path)
@app.route('/downloads/<filename>')
def download(filename):
return send_from_directory(app.config['DOWNLOAD_FOLDER'], filename)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)