import os import uuid import subprocess import whisper from flask import Flask, request, send_file, render_template_string from werkzeug.utils import secure_filename import re import platform app = Flask(__name__) # Configuration UPLOAD_FOLDER = 'uploads' OUTPUT_FOLDER = 'outputs' os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(OUTPUT_FOLDER, exist_ok=True) # Load Whisper model print("🔄 Loading Whisper model...") model = whisper.load_model("small") print("✅ Model loaded!") # ========== DETECT SYSTEM AND GET FONT PATH ========== def get_system_font(): """Get appropriate font path based on operating system""" system = platform.system() if system == "Linux": # Linux fonts (Ubuntu/Debian) font_paths = [ "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf", "/usr/share/fonts/truetype/noto/NotoSans-Regular.ttf", "/usr/share/fonts/truetype/ubuntu/Ubuntu-Regular.ttf" ] elif system == "Windows": # Windows fonts font_paths = [ "C:\\Windows\\Fonts\\arial.ttf", "C:\\Windows\\Fonts\\consola.ttf", "C:\\Windows\\Fonts\\segoeui.ttf" ] elif system == "Darwin": # macOS font_paths = [ "/System/Library/Fonts/Arial.ttf", "/System/Library/Fonts/Helvetica.ttc" ] else: font_paths = ["Arial"] for font in font_paths: if os.path.exists(font): print(f"✅ Found font: {font}") return font print("⚠️ No specific font found, using 'Arial' as fallback") return "Arial" FONT_PATH = get_system_font() # ========== ROMAN URDU CONVERSION ========== def is_urdu_script(text): """Check if text contains Urdu/Arabic script characters""" urdu_range = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]') return bool(urdu_range.search(text)) def urdu_to_roman_simple(urdu_text): """Simple Urdu to Roman conversion""" urdu_to_roman = { 'ا': 'a', 'ب': 'b', 'پ': 'p', 'ت': 't', 'ٹ': 't', 'ث': 's', 'ج': 'j', 'چ': 'ch', 'ح': 'h', 'خ': 'kh', 'د': 'd', 'ڈ': 'd', 'ذ': 'z', 'ر': 'r', 'ڑ': 'r', 'ز': 'z', 'ژ': 'zh', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'z', 'ط': 't', 'ظ': 'z', 'ع': 'a', 'غ': 'gh', 'ف': 'f', 'ق': 'q', 'ک': 'k', 'گ': 'g', 'ل': 'l', 'م': 'm', 'ن': 'n', 'و': 'o', 'ہ': 'h', 'ھ': 'h', 'ء': 'a', 'ی': 'y', 'ے': 'e', ' ': ' ', '?': '?', '!': '!', '،': ',', '۔': '.', 'آ': 'a', 'ؤ': 'o', 'ئ': 'i', 'ۓ': 'e' } roman_chars = [] for char in urdu_text: if char in urdu_to_roman: roman_chars.append(urdu_to_roman[char]) else: roman_chars.append(char) roman_text = ''.join(roman_chars) roman_text = re.sub(r'aa', 'a', roman_text) roman_text = re.sub(r'ee', 'i', roman_text) roman_text = re.sub(r'oo', 'o', roman_text) return roman_text def convert_to_roman(text): """Convert Urdu script to Roman Urdu""" if is_urdu_script(text): return urdu_to_roman_simple(text) return text # HTML Template HTML = '''
Upload video (Urdu → Roman Urdu, English as is)
''' def extract_audio(video_path, audio_path): """Extract audio from video""" subprocess.run([ 'ffmpeg', '-i', video_path, '-ac', '1', '-ar', '16000', audio_path, '-y' ], capture_output=True, check=True) def get_word_timestamps(audio_path): """Get word-by-word timestamps""" result = model.transcribe(audio_path, word_timestamps=True) words = [] for segment in result['segments']: for word in segment.get('words', []): original = word['word'].strip() display = convert_to_roman(original) words.append({ 'word': display, 'start': word['start'], 'end': word['end'] }) return words def format_time(seconds): """Convert seconds to SRT time format""" hours = int(seconds // 3600) minutes = int((seconds % 3600) // 60) secs = seconds % 60 millis = int((secs % 1) * 1000) return f"{hours:02d}:{minutes:02d}:{int(secs):02d},{millis:03d}" def generate_srt(words, output_path): """Generate SRT file""" with open(output_path, 'w', encoding='utf-8') as f: for i, word in enumerate(words, 1): start = format_time(word['start']) end = format_time(word['end']) f.write(f"{i}\n{start} --> {end}\n{word['word']}\n\n") return output_path def add_subtitles(video_path, srt_path, output_path): """Burn subtitles using FFmpeg with proper font""" # CRITICAL FIX: Use proper font path font_style = f"FontName={FONT_PATH},FontSize=24,OutlineColour=&H00000000,BorderStyle=1" cmd = [ 'ffmpeg', '-i', video_path, '-vf', f"subtitles={srt_path}:force_style='{font_style}'", '-c:a', 'copy', '-preset', 'fast', output_path, '-y' ] print(f"🎨 Using font: {FONT_PATH}") subprocess.run(cmd, capture_output=True, check=True) return output_path @app.route('/') def home(): return render_template_string(HTML) @app.route('/process', methods=['POST']) def process_video(): if 'video' not in request.files: return "No video file", 400 file = request.files['video'] if file.filename == '': return "No file selected", 400 video_id = uuid.uuid4().hex[:8] filename = secure_filename(file.filename) input_path = os.path.join(UPLOAD_FOLDER, f"{video_id}_{filename}") audio_path = os.path.join(UPLOAD_FOLDER, f"{video_id}.wav") srt_path = os.path.join(OUTPUT_FOLDER, f"{video_id}.srt") output_path = os.path.join(OUTPUT_FOLDER, f"{video_id}_subtitled.mp4") try: file.save(input_path) print(f"📁 Video saved") print("🎵 Extracting audio...") extract_audio(input_path, audio_path) print("🎙️ Transcribing...") words = get_word_timestamps(audio_path) print(f"✅ Found {len(words)} words") print("📝 Generating subtitles...") generate_srt(words, srt_path) print("🔥 Burning subtitles...") add_subtitles(input_path, srt_path, output_path) return send_file(output_path, as_attachment=True, download_name="subtitled_video.mp4") except Exception as e: print(f"❌ Error: {e}") return f"Error: {str(e)}", 500 finally: for f in [input_path, audio_path, srt_path]: if os.path.exists(f): try: os.remove(f) except: pass @app.route('/health') def health(): return {"status": "ok"} if __name__ == '__main__': app.run(host='0.0.0.0', port=7860, debug=False)