File size: 6,342 Bytes
a30e87b d24a2f3 74d8a08 8a409a5 d24a2f3 d6208ae 202112a 8a409a5 08c3547 d24a2f3 352553f 08c3547 8a409a5 a30e87b 352553f a30e87b 352553f a30e87b d6208ae d24a2f3 352553f ab46005 352553f ab46005 352553f d24a2f3 352553f 74d8a08 352553f a30e87b 352553f a30e87b 352553f 74d8a08 352553f 8a409a5 352553f 8a409a5 352553f a30e87b d6208ae a30e87b 9814147 a30e87b 352553f a30e87b 352553f d6208ae 352553f a30e87b 352553f d6208ae 352553f a30e87b d6208ae 352553f 08c3547 352553f a30e87b 8a409a5 352553f 8a409a5 352553f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# 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) |