import gradio as gr import tempfile import os import subprocess import json from openai import OpenAI from moviepy.editor import VideoFileClip def extract_audio(video_path): """Extract audio from video file and save it as a temporary mp3 file.""" temp_audio = tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) temp_audio.close() video = VideoFileClip(video_path) video.audio.write_audiofile(temp_audio.name, verbose=False, logger=None) return temp_audio.name def transcribe_with_timestamps(audio_path, api_key): """Transcribe audio with word-level timestamps using OpenAI's Whisper API.""" client = OpenAI(api_key=api_key) try: with open(audio_path, "rb") as audio_file: response = client.audio.transcriptions.create( model="whisper-1", # or "gpt-4o-transcribe" if available file=audio_file, response_format="verbose_json", timestamp_granularities=["word"] ) # Format the results words = [] for segment in response.segments: for word in segment.words: words.append({ "word": word.word, "start": word.start, "end": word.end }) return words, response.text except Exception as e: return None, f"Error during transcription: {str(e)}" def process_video(video, api_key): """Process uploaded video, extract audio, and transcribe with timestamps.""" if not video or not api_key: return "Please provide both a video file and an OpenAI API key.", None try: # Extract audio from video audio_path = extract_audio(video) # Get transcription with timestamps word_timestamps, full_text = transcribe_with_timestamps(audio_path, api_key) # Clean up temporary files os.unlink(audio_path) if word_timestamps: # Format results for display timestamp_text = "" for word_info in word_timestamps: start_time = format_time(word_info["start"]) timestamp_text += f"[{start_time}] {word_info['word']} " return full_text, timestamp_text else: return full_text, None except Exception as e: return f"Error processing video: {str(e)}", None def format_time(seconds): """Format time in seconds to MM:SS.ms format.""" minutes = int(seconds // 60) seconds = seconds % 60 return f"{minutes:02d}:{seconds:05.2f}" # Create Gradio interface with gr.Blocks(title="Video Transcription App") as app: gr.Markdown("# Video Transcription with Word-Level Timestamps") gr.Markdown("Upload a video file and get word-by-word transcription with timestamps.") with gr.Row(): with gr.Column(): api_key = gr.Textbox(label="OpenAI API Key", placeholder="Enter your OpenAI API key", type="password") video_input = gr.Video(label="Upload Video") submit_btn = gr.Button("Transcribe Video") with gr.Column(): full_text = gr.Textbox(label="Full Transcription", lines=10) timestamp_text = gr.Textbox(label="Word-by-Word with Timestamps", lines=15) submit_btn.click( fn=process_video, inputs=[video_input, api_key], outputs=[full_text, timestamp_text] ) gr.Markdown(""" ## How It Works 1. Upload your video file 2. Enter your OpenAI API key (required for using Whisper API) 3. Click 'Transcribe Video' 4. View the full transcription and word-by-word timestamps Note: This app extracts audio from your video and sends it to OpenAI's Whisper API for transcription. Your API key is used only for this request and is not stored. """) # Launch the app if __name__ == "__main__": app.launch()