compress / app.py
Asad235's picture
Update app.py
2a4f5a6 verified
Raw
History Blame Contribute Delete
7.77 kB
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 = '''
<!DOCTYPE html>
<html>
<head>
<title>Word-by-Word Subtitle Generator</title>
<style>
body { font-family: Arial; max-width: 600px; margin: 50px auto; padding: 20px; }
input, button { padding: 10px; margin: 10px 0; width: 100%; }
button { background: #007bff; color: white; border: none; cursor: pointer; }
button:hover { background: #0056b3; }
</style>
</head>
<body>
<h1>🎬 Word-by-Word Subtitle Generator</h1>
<p>Upload video (Urdu → Roman Urdu, English as is)</p>
<form action="/process" method="post" enctype="multipart/form-data">
<input type="file" name="video" accept="video/*" required>
<button type="submit">🎬 Generate Subtitles</button>
</form>
</body>
</html>
'''
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)