Spaces:
Runtime error
Runtime error
Upload 2 files
Browse files- app.py +163 -0
- requirements.txt +5 -0
app.py
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from dotenv import load_dotenv
|
3 |
+
import os
|
4 |
+
import google.generativeai as genai
|
5 |
+
from textblob import TextBlob
|
6 |
+
|
7 |
+
from youtube_transcript_api import YouTubeTranscriptApi
|
8 |
+
from youtube_transcript_api.formatters import JSONFormatter
|
9 |
+
|
10 |
+
load_dotenv() # Load all the environment variables
|
11 |
+
|
12 |
+
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
|
13 |
+
|
14 |
+
prompt = """**You are a YouTube video summarizer.** You will be taking the transcript text
|
15 |
+
and summarizing the entire video and providing the important summary in points
|
16 |
+
within 250 words. Please provide the summary of the text given here: """
|
17 |
+
|
18 |
+
|
19 |
+
# Function to extract transcript data from YouTube videos
|
20 |
+
def extract_transcript_details(youtube_video_url):
|
21 |
+
try:
|
22 |
+
video_id = youtube_video_url.split("=")[1]
|
23 |
+
|
24 |
+
transcript_text = YouTubeTranscriptApi.get_transcript(video_id)
|
25 |
+
|
26 |
+
transcript = ""
|
27 |
+
for i in transcript_text:
|
28 |
+
transcript += " " + i["text"]
|
29 |
+
|
30 |
+
return transcript
|
31 |
+
|
32 |
+
except Exception as e:
|
33 |
+
raise e
|
34 |
+
|
35 |
+
|
36 |
+
# Function to generate summary based on prompt using Google Gemini Pro
|
37 |
+
def generate_gemini_content(transcript_text, prompt, max_length):
|
38 |
+
model = genai.GenerativeModel("gemini-pro")
|
39 |
+
response = model.generate_content(prompt + transcript_text)
|
40 |
+
summary = response.text
|
41 |
+
|
42 |
+
# Split the summary into words and limit the length
|
43 |
+
words = summary.split()
|
44 |
+
if len(words) > max_length:
|
45 |
+
summary = ' '.join(words[:max_length])
|
46 |
+
|
47 |
+
return summary
|
48 |
+
|
49 |
+
|
50 |
+
# Function to analyze sentiment of text
|
51 |
+
def analyze_sentiment(text):
|
52 |
+
blob = TextBlob(text)
|
53 |
+
sentiment_score = blob.sentiment.polarity
|
54 |
+
if sentiment_score > 0:
|
55 |
+
return "Positive"
|
56 |
+
elif sentiment_score == 0:
|
57 |
+
return "Neutral"
|
58 |
+
else:
|
59 |
+
return "Negative"
|
60 |
+
|
61 |
+
|
62 |
+
# Streamlit app
|
63 |
+
st.set_page_config(page_title="YouTube Summarizer and Sentiment Analyzer", page_icon=":clapper:", layout="wide")
|
64 |
+
|
65 |
+
st.title("π₯ YouTube Sentiment Analyzer")
|
66 |
+
|
67 |
+
st.sidebar.header("Options")
|
68 |
+
youtube_link = st.sidebar.text_input("Enter YouTube Video Link:")
|
69 |
+
action = st.sidebar.selectbox("Select Action:", ["Choose", "Get Detailed Summary", "Analyze Sentiment"])
|
70 |
+
|
71 |
+
if action == "Get Detailed Summary":
|
72 |
+
max_length = st.sidebar.slider("Select Maximum Summary Length (words)", min_value=50, max_value=500, value=250)
|
73 |
+
|
74 |
+
if st.sidebar.button("π Perform Action"):
|
75 |
+
if action == "Get Detailed Summary":
|
76 |
+
transcript_text = extract_transcript_details(youtube_link)
|
77 |
+
if transcript_text:
|
78 |
+
summary = generate_gemini_content(transcript_text, prompt, max_length)
|
79 |
+
st.markdown("## Detailed Summary:")
|
80 |
+
st.write(summary)
|
81 |
+
|
82 |
+
elif action == "Analyze Sentiment":
|
83 |
+
transcript_text = extract_transcript_details(youtube_link)
|
84 |
+
if transcript_text:
|
85 |
+
sentiment = analyze_sentiment(transcript_text)
|
86 |
+
st.markdown("## Sentiment Analysis:")
|
87 |
+
st.write(f"The sentiment of the video is: {sentiment}")
|
88 |
+
|
89 |
+
# Show YouTube video thumbnail if link provided
|
90 |
+
if youtube_link:
|
91 |
+
video_id = youtube_link.split("=")[1]
|
92 |
+
st.image(f"http://img.youtube.com/vi/{video_id}/0.jpg", use_column_width=True)
|
93 |
+
else:
|
94 |
+
# Stretched GIF
|
95 |
+
st.markdown('<div style="font-family:Arial; text-align:center;"><iframe allow="fullscreen" frameBorder="0" height="400" src="https://giphy.com/embed/SNHd3FpcOrPHoBHtLD/video" width="800"></iframe></div>', unsafe_allow_html=True)
|
96 |
+
|
97 |
+
# Footer
|
98 |
+
footer_with_image_light_blue = """
|
99 |
+
<style>
|
100 |
+
.footer {
|
101 |
+
background-color: #E0F2F1;
|
102 |
+
padding: 20px;
|
103 |
+
border-radius: 10px;
|
104 |
+
text-align: center;
|
105 |
+
animation: fadeIn 1s;
|
106 |
+
}
|
107 |
+
|
108 |
+
.footer img {
|
109 |
+
max-width: 100%;
|
110 |
+
border-radius: 10px;
|
111 |
+
margin-top: 10px;
|
112 |
+
}
|
113 |
+
|
114 |
+
.footer .line {
|
115 |
+
height: 1px;
|
116 |
+
background-color: #B2DFDB;
|
117 |
+
margin: 10px 0;
|
118 |
+
}
|
119 |
+
|
120 |
+
.footer .connect-text {
|
121 |
+
color: #004D40;
|
122 |
+
font-weight: bold;
|
123 |
+
margin-bottom: 10px;
|
124 |
+
}
|
125 |
+
|
126 |
+
.footer a {
|
127 |
+
margin: 0 10px;
|
128 |
+
}
|
129 |
+
|
130 |
+
.footer .powered-by {
|
131 |
+
color: #004D40;
|
132 |
+
font-size: 14px;
|
133 |
+
margin-top: 10px;
|
134 |
+
}
|
135 |
+
|
136 |
+
.bright-text {
|
137 |
+
color: #004D40;
|
138 |
+
}
|
139 |
+
|
140 |
+
/* Add Animation */
|
141 |
+
@keyframes fadeIn {
|
142 |
+
from { opacity: 0; }
|
143 |
+
to { opacity: 1; }
|
144 |
+
}
|
145 |
+
|
146 |
+
.chat-message {
|
147 |
+
animation: fadeIn 0.5s ease-out;
|
148 |
+
}
|
149 |
+
</style>
|
150 |
+
<div class="footer">
|
151 |
+
<div class="line"></div>
|
152 |
+
<div class="connect-text">Connect with me at</div>
|
153 |
+
<a href="https://github.com/FasilHameed" target="_blank"><img src="https://img.icons8.com/plasticine/30/000000/github.png" alt="GitHub"></a>
|
154 |
+
<a href="https://www.linkedin.com/in/faisal--hameed/" target="_blank"><img src="https://img.icons8.com/plasticine/30/000000/linkedin.png" alt="LinkedIn"></a>
|
155 |
+
<a href="tel:+917006862681"><img src="https://img.icons8.com/plasticine/30/000000/phone.png" alt="Phone"></a>
|
156 |
+
<a href="mailto:faisalhameed763@gmail.com"><img src="https://img.icons8.com/plasticine/30/000000/gmail.png" alt="Gmail"></a>
|
157 |
+
<div class="line"></div>
|
158 |
+
<div class="powered-by">Powered By <img src="https://img.icons8.com/clouds/30/000000/gemini.png" alt="Gemini"> Gemini π« and Streamlit π</div>
|
159 |
+
</div>
|
160 |
+
"""
|
161 |
+
|
162 |
+
# Render Footer
|
163 |
+
st.markdown(footer_with_image_light_blue, unsafe_allow_html=True)
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
python-dotenv
|
3 |
+
google.generativeai
|
4 |
+
youtube_transcript_api
|
5 |
+
textblob
|