Last active
May 3, 2025 11:22
-
-
Save Ifihan/a99c63e40c6ffc6d8557c1465a8f3292 to your computer and use it in GitHub Desktop.
Build a Gemini-Powered YouTube Summarizer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from flask import Flask, render_template, request, jsonify | |
from google import genai | |
from google.genai import types | |
app = Flask(__name__) | |
PROJECT_ID = "build-with-vertex-ai" | |
client = genai.Client( | |
vertexai=True, | |
project=PROJECT_ID, | |
location="us-central1", | |
) | |
# Define the home page route. | |
@app.route('/', methods=['GET']) | |
def index(): | |
''' | |
Renders the home page. | |
Returns:The rendered template. | |
''' | |
return render_template('index.html') | |
def generate(youtube_link, model, additional_prompt): | |
# Prepare youtube video using the provided link | |
youtube_video = types.Part.from_uri( | |
file_uri=youtube_link, | |
mime_type="video/*", | |
) | |
# If addtional prompt is not provided, just append a space | |
if not additional_prompt: | |
additional_prompt = " " | |
# Prepare content to send to the model | |
contents = [ | |
youtube_video, | |
types.Part.from_text(text="""Provide a summary of the video."""), | |
additional_prompt, | |
] | |
# Define content configuration | |
generate_content_config = types.GenerateContentConfig( | |
temperature = 1, | |
top_p = 0.95, | |
max_output_tokens = 8192, | |
response_modalities = ["TEXT"], | |
) | |
return client.models.generate_content( | |
model = model, | |
contents = contents, | |
config = generate_content_config, | |
).text | |
@app.route('/summarize', methods=['POST']) | |
def summarize(): | |
''' | |
Summarize the user provided YouTube video. | |
Returns: JSON with summary. | |
''' | |
# Process the form data | |
youtube_link = request.form['youtube_link'] | |
model = request.form['model'] | |
additional_prompt = request.form['additional_prompt'] | |
# Generate the summary. | |
try: | |
summary = generate(youtube_link, model, additional_prompt) | |
return jsonify({"success": True, "summary": summary}) | |
except ValueError as e: | |
return jsonify({"success": False, "error": str(e)}), 400 | |
if __name__ == '__main__': | |
server_port = os.environ.get('PORT', '8080') | |
app.run(debug=False, port=server_port, host='0.0.0.0') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>YouTube Summarizer</title> | |
<style> | |
body { | |
font-family: sans-serif; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
min-height: 100vh; | |
background-color: #f4f4f4; | |
margin: 0; | |
padding: 20px; | |
} | |
.container { | |
background-color: white; | |
padding: 30px; | |
border-radius: 8px; | |
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); | |
text-align: center; | |
width: 100%; | |
max-width: 800px; | |
} | |
h2 { | |
text-align: center; | |
margin-bottom: 20px; | |
} | |
input[type="text"], textarea, select { | |
width: 100%; | |
padding: 10px; | |
margin-bottom: 15px; | |
border: 1px solid #ccc; | |
border-radius: 4px; | |
box-sizing: border-box; | |
} | |
button { | |
background-color: #4CAF50; | |
color: white; | |
padding: 12px 20px; | |
border: none; | |
border-radius: 4px; | |
cursor: pointer; | |
} | |
#loading { | |
display: none; | |
margin-top: 20px; | |
} | |
#summary-container { | |
margin-top: 30px; | |
display: none; | |
text-align: left; | |
} | |
#summary-text { | |
background-color: #f9f9f9; | |
padding: 15px; | |
border-radius: 4px; | |
border-left: 4px solid #4CAF50; | |
white-space: pre-wrap; | |
} | |
.error { | |
color: #f44336; | |
margin-top: 15px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h2>YouTube Summarizer</h2> | |
<form id="summarize-form"> | |
<input type="text" name="youtube_link" id="youtube_link" placeholder="Enter YouTube Link" required> | |
<select name="model" id="model"> | |
<option value="gemini-2.0-flash-001">Gemini 2.0 Flash</option> | |
</select> | |
<textarea name="additional_prompt" id="additional_prompt" placeholder="Write your additional prompt here. For example: 'explain to me like I am five years old'"></textarea> | |
<button type="submit">Summarize</button> | |
</form> | |
<div id="loading"> | |
<p>Generating summary... This may take a moment.</p> | |
</div> | |
<div id="error-message" class="error"></div> | |
<div id="summary-container"> | |
<h3>Summary</h3> | |
<div id="summary-text"></div> | |
</div> | |
</div> | |
<script> | |
document.getElementById('summarize-form').addEventListener('submit', function(e) { | |
e.preventDefault(); | |
// Show loading message | |
document.getElementById('loading').style.display = 'block'; | |
document.getElementById('summary-container').style.display = 'none'; | |
document.getElementById('error-message').textContent = ''; | |
// Get form data | |
const youtubeLink = document.getElementById('youtube_link').value; | |
const model = document.getElementById('model').value; | |
const additionalPrompt = document.getElementById('additional_prompt').value; | |
// Create form data object | |
const formData = new FormData(); | |
formData.append('youtube_link', youtubeLink); | |
formData.append('model', model); | |
formData.append('additional_prompt', additionalPrompt); | |
// Send AJAX request | |
fetch('/summarize', { | |
method: 'POST', | |
body: formData | |
}) | |
.then(response => response.json()) | |
.then(data => { | |
// Hide loading message | |
document.getElementById('loading').style.display = 'none'; | |
if (data.success) { | |
// Show summary | |
document.getElementById('summary-container').style.display = 'block'; | |
document.getElementById('summary-text').textContent = data.summary; | |
} else { | |
// Show error message | |
document.getElementById('error-message').textContent = data.error || 'An error occurred while generating the summary.'; | |
} | |
}) | |
.catch(error => { | |
// Hide loading message and show error | |
document.getElementById('loading').style.display = 'none'; | |
document.getElementById('error-message').textContent = 'An error occurred. Please try again.'; | |
console.error('Error:', error); | |
}); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment