import os import math import tempfile import moviepy as mp import speech_recognition as sr import tkinter as tk from tkinter import filedialog, messagebox, ttk def format_time(seconds): hours = int(seconds // 3600) minutes = int((seconds % 3600) // 60) secs = int(seconds % 60) millis = int((seconds - int(seconds)) * 1000) return f"{hours:02}:{minutes:02}:{secs:02},{millis:03}" def wrap_text(text, max_len=40): """ Wraps text to ~max_len characters per line without cutting words. """ words = text.split() lines = [] current_line = "" for word in words: if len(current_line + " " + word) <= max_len: current_line += (" " if current_line else "") + word else: lines.append(current_line) current_line = word if current_line: lines.append(current_line) return "\n".join(lines) def write_srt(subtitles, output_path): with open(output_path, 'w', encoding='utf-8') as f: for i, sub in enumerate(subtitles, 1): f.write(f"{i}\n") f.write(f"{format_time(sub['start'])} --> {format_time(sub['end'])}\n") f.write(f"{wrap_text(sub['text'])}\n\n") def transcribe_video_to_srt(video_path, srt_output_path, progress_callback=None, chunk_duration=10): try: video = mp.VideoFileClip(video_path) audio = video.audio with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_audio_file: temp_audio_path = temp_audio_file.name audio.write_audiofile(temp_audio_path, logger=None) recognizer = sr.Recognizer() subtitles = [] with sr.AudioFile(temp_audio_path) as source: audio_duration = source.DURATION num_chunks = math.ceil(audio_duration / chunk_duration) for i in range(num_chunks): start_time = i * chunk_duration end_time = min((i + 1) * chunk_duration, audio_duration) source_offset = start_time duration = end_time - start_time audio_data = recognizer.record(source, offset=source_offset, duration=duration) try: text = recognizer.recognize_google(audio_data) subtitles.append({ "start": start_time, "end": end_time, "text": text }) except sr.UnknownValueError: pass except sr.RequestError as e: print(f"API error: {e}") # Update progress bar if progress_callback: progress_callback(i + 1, num_chunks) os.remove(temp_audio_path) write_srt(subtitles, srt_output_path) return True except Exception as e: print(f"Error: {e}") return False # -------------------- GUI -------------------- def select_file_and_generate(): video_path = filedialog.askopenfilename( title="Select a video file", filetypes=[("Video files", "*.mp4 *.mov *.avi *.mkv")] ) if not video_path: return srt_output_path = filedialog.asksaveasfilename( title="Save SRT subtitles as...", defaultextension=".srt", filetypes=[("Subtitle files", "*.srt")] ) if not srt_output_path: return progress_bar["value"] = 0 progress_label.config(text="Starting...") root.update() def update_progress(current, total): percent = (current / total) * 100 progress_bar["value"] = percent progress_label.config(text=f"Progress: {current}/{total} chunks") root.update() success = transcribe_video_to_srt(video_path, srt_output_path, progress_callback=update_progress) if success: messagebox.showinfo("Success", f"Subtitles saved to:\n{srt_output_path}") else: messagebox.showerror("Error", "Something went wrong. See console for details.") progress_label.config(text="Done") # GUI Setup root = tk.Tk() root.title("Auto Subtitle Generator (.srt) with Progress") frame = tk.Frame(root, padx=20, pady=20) frame.pack() label = tk.Label(frame, text="Select a video file to auto-generate subtitles (SRT):") label.pack(pady=(0, 10)) select_button = tk.Button(frame, text="Select Video and Generate Subtitles", command=select_file_and_generate) select_button.pack(pady=5) progress_bar = ttk.Progressbar(frame, length=300, mode="determinate") progress_bar.pack(pady=(15, 5)) progress_label = tk.Label(frame, text="Idle") progress_label.pack() root.mainloop()