vedio-editor / app.py
umerfarooq29's picture
Update app.py
3a12b87 verified
import os
import subprocess
import tempfile
from pathlib import Path
from typing import Optional
import streamlit as st
from faster_whisper import WhisperModel
from googletrans import Translator
# ---------------- CONFIG ----------------
MODEL_NAME = os.environ.get("WHISPER_MODEL", "large-v2")
DEVICE = "cuda" if (os.environ.get("CUDA_VISIBLE_DEVICES") or False) else "cpu"
_model = None
def get_model():
global _model
if _model is None:
compute_type = "float16" if DEVICE.startswith("cuda") else "int8"
_model = WhisperModel(MODEL_NAME, device=DEVICE, compute_type=compute_type)
return _model
def extract_audio(input_video_path: str, output_audio_path: str):
cmd = [
"ffmpeg", "-y", "-i", input_video_path,
"-vn", "-acodec", "pcm_s16le", "-ar", "16000", "-ac", "1",
output_audio_path,
]
subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def segments_to_srt(segments):
def fmt_time(s):
h = int(s // 3600)
m = int((s % 3600) // 60)
sec = s % 60
return f"{h:02d}:{m:02d}:{sec:06.3f}".replace('.', ',')
srt_lines = []
for i, seg in enumerate(segments, start=1):
start = fmt_time(seg["start"])
end = fmt_time(seg["end"])
text = seg["text"].strip()
srt_lines.append(f"{i}\n{start} --> {end}\n{text}\n")
return "\n".join(srt_lines)
def transcribe_and_translate(video_file: str, target_lang: Optional[str], burn_subs: bool):
model = get_model()
tempdir = Path(tempfile.mkdtemp())
input_path = Path(video_file)
audio_path = tempdir / "audio.wav"
srt_path = tempdir / f"subtitles_{input_path.stem}.srt"
processed_video_path = None
extract_audio(str(input_path), str(audio_path))
segments_all = []
transcribe_options = {"beam_size": 5, "word_timestamps": False}
for segment in model.transcribe(str(audio_path), beam_size=5, vad_filter=True, **transcribe_options):
segments_all.append({"start": segment.start, "end": segment.end, "text": segment.text})
if target_lang and target_lang.lower() not in ["", "none"]:
translator = Translator()
translated_segments = []
for seg in segments_all:
src_text = seg["text"].strip()
try:
res = translator.translate(src_text, dest=target_lang)
translated_text = res.text
except Exception:
translated_text = src_text
translated_segments.append({"start": seg["start"], "end": seg["end"], "text": translated_text})
segments_used = translated_segments
else:
segments_used = segments_all
srt_text = segments_to_srt(segments_used)
srt_path.write_text(srt_text, encoding="utf-8")
if burn_subs:
out_video = tempdir / f"burned_{input_path.name}"
cmd = [
"ffmpeg", "-y", "-i", str(input_path),
"-vf", f"subtitles={str(srt_path)}:force_style='FontName=Arial,FontSize=24'",
"-c:a", "copy", str(out_video),
]
subprocess.run(cmd, check=True)
processed_video_path = str(out_video)
return str(srt_path), processed_video_path
# ---------------- UI (Streamlit) ----------------
st.set_page_config(page_title="Video Subtitle Editor + Translator", layout="wide")
st.title("🎬 Video Subtitle Editor + Translator (Streamlit)")
video_file = st.file_uploader("Upload your video (mp4, mov, mkv)", type=["mp4", "mov", "mkv"])
lang_choice = st.selectbox(
"Translate subtitles to:",
["None", "English (en)", "Urdu (ur)", "Hindi (hi)", "Spanish (es)", "French (fr)", "German (de)"]
)
burn_option = st.checkbox("Burn subtitles into video (hardcoded) - slow but permanent", value=False)
if st.button("Run"):
if video_file is None:
st.warning("Please upload a video file first.")
else:
with st.spinner("Processing... Please wait ⏳"):
temp_input = Path(tempfile.mkdtemp()) / video_file.name
with open(temp_input, "wb") as f:
f.write(video_file.read())
lang_code = lang_choice.split("(")[-1].replace(")", "").strip().lower() if "(" in lang_choice else "none"
try:
srt_path, processed_video = transcribe_and_translate(str(temp_input), lang_code, burn_option)
st.success("✅ Done! Subtitles generated successfully.")
st.download_button("📥 Download SRT", open(srt_path, "rb"), file_name=os.path.basename(srt_path))
if processed_video:
st.download_button("📽️ Download Video with Subtitles", open(processed_video, "rb"), file_name=os.path.basename(processed_video))
except subprocess.CalledProcessError as e:
st.error(f"ffmpeg error: {e}")
except Exception as e:
st.error(f"Error: {e}")