Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import os | |
| from youtube_transcript_api import YouTubeTranscriptApi | |
| from google import genai | |
| import re | |
| # Initialize Gemini client | |
| def get_gemini_client(): | |
| api_key = os.getenv("GEMINI_API_KEY") | |
| if not api_key: | |
| raise ValueError("Gemini API key not found. Please set GEMINI_API_KEY environment variable.") | |
| return genai.Client(api_key=api_key) | |
| def get_video_id(url_link): | |
| """Extract video ID from YouTube URL""" | |
| # Handle different YouTube URL formats | |
| patterns = [ | |
| r'(?:youtube\.com/watch\?v=|youtu\.be/|youtube\.com/embed/)([^&\n?#]+)', | |
| r'youtube\.com/watch\?.*v=([^&\n?#]+)' | |
| ] | |
| for pattern in patterns: | |
| match = re.search(pattern, url_link) | |
| if match: | |
| return match.group(1) | |
| raise ValueError("Invalid YouTube URL format") | |
| def get_transcript(video_id): | |
| """Get transcript from YouTube video""" | |
| try: | |
| transcript = YouTubeTranscriptApi.get_transcript(video_id) | |
| transcript_text = " ".join([line['text'] for line in transcript]) | |
| return transcript_text | |
| except Exception as e: | |
| raise Exception(f"Error getting transcript: {str(e)}") | |
| def summarize_with_gemini(transcript, question="What is this video about?", model="gemini-2.0-flash"): | |
| """Summarize transcript using Google Gemini""" | |
| try: | |
| client = get_gemini_client() | |
| # Limit transcript length to avoid token limits (Gemini has generous limits but still good practice) | |
| max_transcript_length = 8000 | |
| if len(transcript) > max_transcript_length: | |
| transcript = transcript[:max_transcript_length] + "..." | |
| prompt = f"""Based on the following video transcript, {question} | |
| Transcript: {transcript} | |
| Please provide a comprehensive and well-structured answer.""" | |
| response = client.models.generate_content( | |
| model=model, | |
| contents=prompt | |
| ) | |
| return response.text | |
| except Exception as e: | |
| raise Exception(f"Error with Gemini API: {str(e)}") | |
| def process_youtube_video(youtube_url, question, model_choice): | |
| """Main function to process YouTube video""" | |
| try: | |
| # Validate inputs | |
| if not youtube_url.strip(): | |
| return "Please enter a valid YouTube URL.", "" | |
| if not question.strip(): | |
| question = "What is this video about? Please provide a detailed summary." | |
| # Extract video ID | |
| video_id = get_video_id(youtube_url) | |
| # Get transcript | |
| transcript = get_transcript(video_id) | |
| # Check transcript length | |
| if len(transcript) < 50: | |
| return "Transcript is too short or unavailable for this video.", transcript[:500] + "..." | |
| # Generate summary using Gemini | |
| summary = summarize_with_gemini(transcript, question, model_choice) | |
| return summary, transcript[:1000] + "..." if len(transcript) > 1000 else transcript | |
| except Exception as e: | |
| return f"Error: {str(e)}", "" | |
| # Create Gradio interface | |
| def create_interface(): | |
| with gr.Blocks(title="YouTube Video Summarizer with Gemini", theme=gr.themes.Soft()) as iface: | |
| gr.Markdown("# π₯ YouTube Video Summarizer") | |
| gr.Markdown("Enter a YouTube URL and ask questions about the video content. The app will extract the transcript and use Google Gemini AI to provide answers.") | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| youtube_url = gr.Textbox( | |
| label="YouTube URL", | |
| placeholder="https://www.youtube.com/watch?v=...", | |
| lines=1 | |
| ) | |
| question = gr.Textbox( | |
| label="Question about the video", | |
| placeholder="What is this video about? What are the main points discussed?", | |
| lines=2, | |
| value="What is this video about? Please provide a detailed summary." | |
| ) | |
| model_choice = gr.Dropdown( | |
| choices=["gemini-2.0-flash", "gemini-1.5-pro", "gemini-1.5-flash"], | |
| label="Gemini Model", | |
| value="gemini-2.0-flash" | |
| ) | |
| submit_btn = gr.Button("π Analyze Video", variant="primary") | |
| with gr.Column(scale=1): | |
| gr.Markdown("### How to use:") | |
| gr.Markdown(""" | |
| 1. Paste a YouTube URL | |
| 2. Enter your question about the video | |
| 3. Choose a Gemini model | |
| 4. Click 'Analyze Video' | |
| **Note:** Make sure the video has captions/subtitles available. | |
| **Powered by Google Gemini 2.0 Flash** π | |
| """) | |
| with gr.Row(): | |
| with gr.Column(): | |
| summary_output = gr.Textbox( | |
| label="Gemini AI Summary/Answer", | |
| lines=12, | |
| max_lines=20 | |
| ) | |
| with gr.Column(): | |
| transcript_output = gr.Textbox( | |
| label="Video Transcript (Preview)", | |
| lines=12, | |
| max_lines=20 | |
| ) | |
| # Event handlers | |
| submit_btn.click( | |
| fn=process_youtube_video, | |
| inputs=[youtube_url, question, model_choice], | |
| outputs=[summary_output, transcript_output] | |
| ) | |
| # Examples | |
| gr.Examples( | |
| examples=[ | |
| ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "What is this video about?", "gemini-2.0-flash"], | |
| ["https://youtu.be/example", "What are the main points and key takeaways?", "gemini-2.0-flash"], | |
| ["https://www.youtube.com/watch?v=example", "Summarize this in bullet points", "gemini-1.5-pro"], | |
| ], | |
| inputs=[youtube_url, question, model_choice] | |
| ) | |
| gr.Markdown(""" | |
| --- | |
| **Requirements:** | |
| - Google Gemini API key must be set as environment variable `GEMINI_API_KEY` | |
| - Video must have available transcripts/captions | |
| - Some videos may not have transcripts available | |
| **Features:** | |
| - β¨ Powered by Google Gemini 2.0 Flash | |
| - π― Smart transcript analysis | |
| - π¬ Custom question answering | |
| - π Detailed summaries and insights | |
| """) | |
| return iface | |
| # Launch the app | |
| if __name__ == "__main__": | |
| # Create and launch the interface | |
| app = create_interface() | |
| app.launch( | |
| server_name="0.0.0.0", # Required for Hugging Face Spaces | |
| server_port=7860, # Default port for Hugging Face Spaces | |
| show_error=True | |
| ) |