Sayiqa commited on
Commit
42fde0f
Β·
verified Β·
1 Parent(s): 7d97b0f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +371 -160
app.py CHANGED
@@ -130,65 +130,374 @@ import re
130
  from collections import Counter
131
  from googleapiclient.discovery import build
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  def process_youtube_video(url="", keywords=""):
134
  try:
135
- #Initialize variables
136
  thumbnail = None
137
  summary = "No transcript available"
138
  sentiment_label = "N/A"
139
  recommendations = ""
140
  subtitle_info = "No additional information available"
141
 
142
- if not url.strip():
143
- return None, "Please enter a YouTube URL", "N/A", "", ""
144
-
145
- video_id = extract_video_id(url)
146
- if not video_id:
147
- return None, "Invalid YouTube URL", "N/A", "", ""
148
 
149
- thumbnail = f"https://img.youtube.com/vi/{video_id}/maxresdefault.jpg"
150
 
151
- try:
152
- # Fetch transcript
153
- transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
154
- transcript = None
155
  try:
156
- transcript = transcript_list.find_transcript(['en'])
157
- except:
158
- transcript = transcript_list.find_generated_transcript(['en'])
159
-
160
- text = " ".join([t['text'] for t in transcript.fetch()])
161
- if not text.strip():
162
- raise ValueError("Transcript is empty")
163
-
164
- # Clean up the text for sentiment analysis
165
- cleaned_text = clean_text_for_analysis(text)
166
-
167
- # Sentiment analysis
168
- sentiment = TextBlob(cleaned_text).sentiment # Use cleaned text for sentiment analysis
169
- sentiment_label = f"{'Positive' if sentiment.polarity > 0 else 'Negative' if sentiment.polarity < 0 else 'Neutral'} ({sentiment.polarity:.2f})"
170
-
171
- # Generate summary
172
- model = genai.GenerativeModel("gemini-pro")
173
- summary = model.generate_content(f"Summarize this: {cleaned_text[:4000]}").text
174
-
175
- # Extract subtitle information
176
- subtitle_info = extract_subtitle_info(cleaned_text)
177
-
178
- except TranscriptsDisabled:
179
- metadata = get_video_metadata(video_id)
180
- summary = metadata.get("description", "⚠️ This video has disabled subtitles.")
181
- sentiment_label = "N/A"
182
- subtitle_info = "No subtitles available for analysis."
183
- except NoTranscriptFound:
184
- metadata = get_video_metadata(video_id)
185
- summary = metadata.get("description", "⚠️ No English transcript available.")
186
- sentiment_label = "N/A"
187
- subtitle_info = "No subtitles available for analysis."
188
- except Exception as e:
189
- return thumbnail, f"⚠️ Error processing transcript: {str(e)}", "N/A", "", ""
190
-
191
- # Get recommendations
 
 
 
 
192
  if keywords.strip():
193
  recommendations = get_recommendations(keywords)
194
 
@@ -197,104 +506,6 @@ def process_youtube_video(url="", keywords=""):
197
  except Exception as e:
198
  return None, f"Error: {str(e)}", "N/A", "", ""
199
 
200
-
201
- def extract_video_id(url):
202
- """
203
- Extracts the video ID from a YouTube URL.
204
- """
205
- match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11})", url)
206
- return match.group(1) if match else None
207
-
208
-
209
- def get_video_metadata(video_id):
210
- """
211
- Fetches video metadata such as title and description using the YouTube Data API.
212
- """
213
- try:
214
- YOUTUBE_API_KEY = "AIzaSyD_SDF4lC3vpHVAMnBOcN2ZCTz7dRjUc98" # Replace with your YouTube Data API key
215
- youtube = build("youtube", "v3", developerKey=YOUTUBE_API_KEY)
216
- request = youtube.videos().list(part="snippet", id=video_id)
217
- response = request.execute()
218
-
219
- if "items" in response and len(response["items"]) > 0:
220
- snippet = response["items"][0]["snippet"]
221
- return {
222
- "title": snippet.get("title", "No title available"),
223
- "description": snippet.get("description", "No description available"),
224
- }
225
- return {}
226
-
227
- except Exception as e:
228
- return {"title": "Error fetching metadata", "description": str(e)}
229
-
230
-
231
- def extract_subtitle_info(text):
232
- """
233
- Extracts meaningful information from the subtitles.
234
- This could include topics, key insights, or a breakdown of the content.
235
- """
236
- try:
237
- # Split text into sentences for better analysis
238
- sentences = text.split(". ")
239
-
240
- # Example: Extract key topics or keywords
241
- words = text.split()
242
- common_words = Counter(words).most_common(10)
243
- key_topics = ", ".join([word for word, count in common_words])
244
-
245
- # Example: Provide a breakdown of the content
246
- info = f"Key topics discussed: {key_topics}. \nNumber of sentences: {len(sentences)}. \nTotal words: {len(words)}."
247
-
248
- return info
249
- except Exception as e:
250
- return f"Error extracting subtitle information: {str(e)}"
251
-
252
-
253
- def clean_text_for_analysis(text):
254
- """
255
- Cleans the transcript text by removing extra spaces, line breaks, and non-text elements.
256
- """
257
- # Remove extra spaces and line breaks
258
- cleaned_text = " ".join(text.split())
259
- return cleaned_text
260
-
261
-
262
- def get_recommendations(keywords):
263
- """
264
- Fetches related video recommendations based on the provided keywords.
265
- This function can be expanded with a proper API or custom logic.
266
- """
267
- # Placeholder for fetching recommendations based on keywords
268
- return f"Recommendations for: {keywords}" # Dummy return for now
269
- ######################################
270
-
271
- def get_recommendations(keywords, max_results=5):
272
- if not keywords:
273
- return "Please provide search keywords"
274
- try:
275
- response = requests.get(
276
- "https://www.googleapis.com/youtube/v3/search",
277
- params={
278
- "part": "snippet",
279
- "q": f"educational {keywords}",
280
- "type": "video",
281
- "maxResults": max_results,
282
- "relevanceLanguage": "en",
283
- "key": YOUTUBE_API_KEY
284
- }
285
- ).json()
286
-
287
- results = []
288
- for item in response.get("items", []):
289
- title = item["snippet"]["title"]
290
- channel = item["snippet"]["channelTitle"]
291
- video_id = item["id"]["videoId"]
292
- results.append(f"πŸ“Ί {title}\nπŸ‘€ {channel}\nπŸ”— https://youtube.com/watch?v={video_id}\n")
293
-
294
- return "\n".join(results) if results else "No recommendations found"
295
- except Exception as e:
296
- return f"Error: {str(e)}"
297
-
298
  # Gradio Interface
299
  with gr.Blocks(theme=gr.themes.Soft()) as app:
300
  # Login Page
@@ -304,7 +515,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
304
  password = gr.Textbox(label="Password", type="password")
305
  login_btn = gr.Button("Login", variant="primary")
306
  login_msg = gr.Markdown()
307
-
308
  # Main Interface
309
  with gr.Group(visible=False) as main_page:
310
  with gr.Row():
@@ -316,7 +527,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
316
  nav_courses = gr.Button("πŸ“š Courses")
317
  nav_youtube = gr.Button("πŸŽ₯ YouTube Tool")
318
  logout_btn = gr.Button("πŸšͺ Logout", variant="stop")
319
-
320
  with gr.Column(scale=3):
321
  # Dashboard Content
322
  dashboard_page = gr.Group()
@@ -327,13 +538,13 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
327
  - πŸ‘₯ Total Students: {len(students_data)}
328
  - πŸ‘¨β€πŸ« Total Teachers: {len(teachers_data)}
329
  - πŸ“š Total Courses: {len(courses_data)}
330
-
331
  ### Quick Actions
332
  - View student performance
333
  - Access course materials
334
  - Generate learning insights
335
  """)
336
-
337
  # Students Content
338
  students_page = gr.Group(visible=False)
339
  with students_page:
@@ -342,7 +553,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
342
  value=students_data,
343
  headers=["ID", "Name", "Grade", "Program"]
344
  )
345
-
346
  # Teachers Content
347
  teachers_page = gr.Group(visible=False)
348
  with teachers_page:
@@ -351,7 +562,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
351
  value=teachers_data,
352
  headers=["ID", "Name", "Subject", "Qualification"]
353
  )
354
-
355
  # Courses Content
356
  courses_page = gr.Group(visible=False)
357
  with courses_page:
@@ -360,7 +571,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
360
  value=courses_data,
361
  headers=["ID", "Name", "Instructor", "Level"]
362
  )
363
-
364
  # YouTube Tool Content
365
  youtube_page = gr.Group(visible=False)
366
  with youtube_page:
@@ -376,10 +587,10 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
376
  placeholder="e.g., python programming, machine learning"
377
  )
378
  analyze_btn = gr.Button("πŸ” Analyze Video", variant="primary")
379
-
380
  with gr.Column(scale=1):
381
  video_thumbnail = gr.Image(label="Video Preview")
382
-
383
  with gr.Row():
384
  with gr.Column():
385
  summary = gr.Textbox(label="πŸ“ Summary", lines=8)
@@ -399,7 +610,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
399
  main_page: gr.update(visible=False),
400
  login_msg: "❌ Invalid credentials"
401
  }
402
-
403
  def show_page(page_name):
404
  updates = {
405
  dashboard_page: gr.update(visible=False),
@@ -410,26 +621,26 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
410
  }
411
  updates[page_name] = gr.update(visible=True)
412
  return updates
413
-
414
  # Event Handlers
415
  login_btn.click(
416
  login_check,
417
  inputs=[username, password],
418
  outputs=[login_page, main_page, login_msg]
419
  )
420
-
421
  nav_dashboard.click(lambda: show_page(dashboard_page), outputs=list(show_page(dashboard_page).keys()))
422
  nav_students.click(lambda: show_page(students_page), outputs=list(show_page(students_page).keys()))
423
  nav_teachers.click(lambda: show_page(teachers_page), outputs=list(show_page(teachers_page).keys()))
424
  nav_courses.click(lambda: show_page(courses_page), outputs=list(show_page(courses_page).keys()))
425
  nav_youtube.click(lambda: show_page(youtube_page), outputs=list(show_page(youtube_page).keys()))
426
-
427
  analyze_btn.click(
428
  process_youtube_video,
429
  inputs=[video_url, keywords],
430
  outputs=[video_thumbnail, summary, sentiment, recommendations]
431
  )
432
-
433
  logout_btn.click(
434
  lambda: {
435
  login_page: gr.update(visible=True),
 
130
  from collections import Counter
131
  from googleapiclient.discovery import build
132
 
133
+ # def process_youtube_video(url="", keywords=""):
134
+ # try:
135
+ # #Initialize variables
136
+ # thumbnail = None
137
+ # summary = "No transcript available"
138
+ # sentiment_label = "N/A"
139
+ # recommendations = ""
140
+ # subtitle_info = "No additional information available"
141
+
142
+ # if not url.strip():
143
+ # return None, "Please enter a YouTube URL", "N/A", "", ""
144
+
145
+ # video_id = extract_video_id(url)
146
+ # if not video_id:
147
+ # return None, "Invalid YouTube URL", "N/A", "", ""
148
+
149
+ # thumbnail = f"https://img.youtube.com/vi/{video_id}/maxresdefault.jpg"
150
+
151
+ # try:
152
+ # # Fetch transcript
153
+ # transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
154
+ # transcript = None
155
+ # try:
156
+ # transcript = transcript_list.find_transcript(['en'])
157
+ # except:
158
+ # transcript = transcript_list.find_generated_transcript(['en'])
159
+
160
+ # text = " ".join([t['text'] for t in transcript.fetch()])
161
+ # if not text.strip():
162
+ # raise ValueError("Transcript is empty")
163
+
164
+ # # Clean up the text for sentiment analysis
165
+ # cleaned_text = clean_text_for_analysis(text)
166
+
167
+ # # Sentiment analysis
168
+ # sentiment = TextBlob(cleaned_text).sentiment # Use cleaned text for sentiment analysis
169
+ # sentiment_label = f"{'Positive' if sentiment.polarity > 0 else 'Negative' if sentiment.polarity < 0 else 'Neutral'} ({sentiment.polarity:.2f})"
170
+
171
+ # # Generate summary
172
+ # model = genai.GenerativeModel("gemini-pro")
173
+ # summary = model.generate_content(f"Summarize this: {cleaned_text[:4000]}").text
174
+
175
+ # # Extract subtitle information
176
+ # subtitle_info = extract_subtitle_info(cleaned_text)
177
+
178
+ # except TranscriptsDisabled:
179
+ # metadata = get_video_metadata(video_id)
180
+ # summary = metadata.get("description", "⚠️ This video has disabled subtitles.")
181
+ # sentiment_label = "N/A"
182
+ # subtitle_info = "No subtitles available for analysis."
183
+ # except NoTranscriptFound:
184
+ # metadata = get_video_metadata(video_id)
185
+ # summary = metadata.get("description", "⚠️ No English transcript available.")
186
+ # sentiment_label = "N/A"
187
+ # subtitle_info = "No subtitles available for analysis."
188
+ # except Exception as e:
189
+ # return thumbnail, f"⚠️ Error processing transcript: {str(e)}", "N/A", "", ""
190
+
191
+ # # Get recommendations
192
+ # if keywords.strip():
193
+ # recommendations = get_recommendations(keywords)
194
+
195
+ # return thumbnail, summary, sentiment_label, subtitle_info, recommendations
196
+
197
+ # except Exception as e:
198
+ # return None, f"Error: {str(e)}", "N/A", "", ""
199
+
200
+
201
+ # def extract_video_id(url):
202
+ # """
203
+ # Extracts the video ID from a YouTube URL.
204
+ # """
205
+ # match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11})", url)
206
+ # return match.group(1) if match else None
207
+
208
+
209
+ # def get_video_metadata(video_id):
210
+ # """
211
+ # Fetches video metadata such as title and description using the YouTube Data API.
212
+ # """
213
+ # try:
214
+ # YOUTUBE_API_KEY = "AIzaSyD_SDF4lC3vpHVAMnBOcN2ZCTz7dRjUc98" # Replace with your YouTube Data API key
215
+ # youtube = build("youtube", "v3", developerKey=YOUTUBE_API_KEY)
216
+ # request = youtube.videos().list(part="snippet", id=video_id)
217
+ # response = request.execute()
218
+
219
+ # if "items" in response and len(response["items"]) > 0:
220
+ # snippet = response["items"][0]["snippet"]
221
+ # return {
222
+ # "title": snippet.get("title", "No title available"),
223
+ # "description": snippet.get("description", "No description available"),
224
+ # }
225
+ # return {}
226
+
227
+ # except Exception as e:
228
+ # return {"title": "Error fetching metadata", "description": str(e)}
229
+
230
+
231
+ # def extract_subtitle_info(text):
232
+ # """
233
+ # Extracts meaningful information from the subtitles.
234
+ # This could include topics, key insights, or a breakdown of the content.
235
+ # """
236
+ # try:
237
+ # # Split text into sentences for better analysis
238
+ # sentences = text.split(". ")
239
+
240
+ # # Example: Extract key topics or keywords
241
+ # words = text.split()
242
+ # common_words = Counter(words).most_common(10)
243
+ # key_topics = ", ".join([word for word, count in common_words])
244
+
245
+ # # Example: Provide a breakdown of the content
246
+ # info = f"Key topics discussed: {key_topics}. \nNumber of sentences: {len(sentences)}. \nTotal words: {len(words)}."
247
+
248
+ # return info
249
+ # except Exception as e:
250
+ # return f"Error extracting subtitle information: {str(e)}"
251
+
252
+
253
+ # def clean_text_for_analysis(text):
254
+ # """
255
+ # Cleans the transcript text by removing extra spaces, line breaks, and non-text elements.
256
+ # """
257
+ # # Remove extra spaces and line breaks
258
+ # cleaned_text = " ".join(text.split())
259
+ # return cleaned_text
260
+
261
+
262
+ # def get_recommendations(keywords):
263
+ # """
264
+ # Fetches related video recommendations based on the provided keywords.
265
+ # This function can be expanded with a proper API or custom logic.
266
+ # """
267
+ # # Placeholder for fetching recommendations based on keywords
268
+ # return f"Recommendations for: {keywords}" # Dummy return for now
269
+
270
+
271
+ # def get_recommendations(keywords, max_results=5):
272
+ # if not keywords:
273
+ # return "Please provide search keywords"
274
+ # try:
275
+ # response = requests.get(
276
+ # "https://www.googleapis.com/youtube/v3/search",
277
+ # params={
278
+ # "part": "snippet",
279
+ # "q": f"educational {keywords}",
280
+ # "type": "video",
281
+ # "maxResults": max_results,
282
+ # "relevanceLanguage": "en",
283
+ # "key": YOUTUBE_API_KEY
284
+ # }
285
+ # ).json()
286
+
287
+ # results = []
288
+ # for item in response.get("items", []):
289
+ # title = item["snippet"]["title"]
290
+ # channel = item["snippet"]["channelTitle"]
291
+ # video_id = item["id"]["videoId"]
292
+ # results.append(f"πŸ“Ί {title}\nπŸ‘€ {channel}\nπŸ”— https://youtube.com/watch?v={video_id}\n")
293
+
294
+ # return "\n".join(results) if results else "No recommendations found"
295
+ # except Exception as e:
296
+ # return f"Error: {str(e)}"
297
+
298
+ # # Gradio Interface
299
+ # with gr.Blocks(theme=gr.themes.Soft()) as app:
300
+ # # Login Page
301
+ # with gr.Group() as login_page:
302
+ # gr.Markdown("# πŸŽ“ Educational Learning Management System")
303
+ # username = gr.Textbox(label="Username")
304
+ # password = gr.Textbox(label="Password", type="password")
305
+ # login_btn = gr.Button("Login", variant="primary")
306
+ # login_msg = gr.Markdown()
307
+
308
+ # # Main Interface
309
+ # with gr.Group(visible=False) as main_page:
310
+ # with gr.Row():
311
+ # with gr.Column(scale=1):
312
+ # gr.Markdown("### πŸ“‹ Navigation")
313
+ # nav_dashboard = gr.Button("πŸ“Š Dashboard", variant="primary")
314
+ # nav_students = gr.Button("πŸ‘₯ Students")
315
+ # nav_teachers = gr.Button("πŸ‘¨β€πŸ« Teachers")
316
+ # nav_courses = gr.Button("πŸ“š Courses")
317
+ # nav_youtube = gr.Button("πŸŽ₯ YouTube Tool")
318
+ # logout_btn = gr.Button("πŸšͺ Logout", variant="stop")
319
+
320
+ # with gr.Column(scale=3):
321
+ # # Dashboard Content
322
+ # dashboard_page = gr.Group()
323
+ # with dashboard_page:
324
+ # gr.Markdown("## πŸ“Š Dashboard")
325
+ # gr.Markdown(f"""
326
+ # ### System Overview
327
+ # - πŸ‘₯ Total Students: {len(students_data)}
328
+ # - πŸ‘¨β€πŸ« Total Teachers: {len(teachers_data)}
329
+ # - πŸ“š Total Courses: {len(courses_data)}
330
+
331
+ # ### Quick Actions
332
+ # - View student performance
333
+ # - Access course materials
334
+ # - Generate learning insights
335
+ # """)
336
+
337
+ # # Students Content
338
+ # students_page = gr.Group(visible=False)
339
+ # with students_page:
340
+ # gr.Markdown("## πŸ‘₯ Students")
341
+ # gr.DataFrame(
342
+ # value=students_data,
343
+ # headers=["ID", "Name", "Grade", "Program"]
344
+ # )
345
+
346
+ # # Teachers Content
347
+ # teachers_page = gr.Group(visible=False)
348
+ # with teachers_page:
349
+ # gr.Markdown("## πŸ‘¨β€πŸ« Teachers")
350
+ # gr.DataFrame(
351
+ # value=teachers_data,
352
+ # headers=["ID", "Name", "Subject", "Qualification"]
353
+ # )
354
+
355
+ # # Courses Content
356
+ # courses_page = gr.Group(visible=False)
357
+ # with courses_page:
358
+ # gr.Markdown("## πŸ“š Courses")
359
+ # gr.DataFrame(
360
+ # value=courses_data,
361
+ # headers=["ID", "Name", "Instructor", "Level"]
362
+ # )
363
+
364
+ # # YouTube Tool Content
365
+ # youtube_page = gr.Group(visible=False)
366
+ # with youtube_page:
367
+ # gr.Markdown("## Agent for YouTube Content Exploration")
368
+ # with gr.Row():
369
+ # with gr.Column(scale=2):
370
+ # video_url = gr.Textbox(
371
+ # label="YouTube URL",
372
+ # placeholder="https://youtube.com/watch?v=..."
373
+ # )
374
+ # keywords = gr.Textbox(
375
+ # label="Keywords for Recommendations",
376
+ # placeholder="e.g., python programming, machine learning"
377
+ # )
378
+ # analyze_btn = gr.Button("πŸ” Analyze Video", variant="primary")
379
+
380
+ # with gr.Column(scale=1):
381
+ # video_thumbnail = gr.Image(label="Video Preview")
382
+
383
+ # with gr.Row():
384
+ # with gr.Column():
385
+ # summary = gr.Textbox(label="πŸ“ Summary", lines=8)
386
+ # sentiment = gr.Textbox(label="😊 Content Sentiment")
387
+ # with gr.Column():
388
+ # recommendations = gr.Textbox(label="🎯 Related Videos", lines=10)
389
+
390
+ # def login_check(user, pwd):
391
+ # if USER_CREDENTIALS.get(user) == pwd:
392
+ # return {
393
+ # login_page: gr.update(visible=False),
394
+ # main_page: gr.update(visible=True),
395
+ # login_msg: ""
396
+ # }
397
+ # return {
398
+ # login_page: gr.update(visible=True),
399
+ # main_page: gr.update(visible=False),
400
+ # login_msg: "❌ Invalid credentials"
401
+ # }
402
+
403
+ # def show_page(page_name):
404
+ # updates = {
405
+ # dashboard_page: gr.update(visible=False),
406
+ # students_page: gr.update(visible=False),
407
+ # teachers_page: gr.update(visible=False),
408
+ # courses_page: gr.update(visible=False),
409
+ # youtube_page: gr.update(visible=False)
410
+ # }
411
+ # updates[page_name] = gr.update(visible=True)
412
+ # return updates
413
+
414
+ # # Event Handlers
415
+ # login_btn.click(
416
+ # login_check,
417
+ # inputs=[username, password],
418
+ # outputs=[login_page, main_page, login_msg]
419
+ # )
420
+
421
+ # nav_dashboard.click(lambda: show_page(dashboard_page), outputs=list(show_page(dashboard_page).keys()))
422
+ # nav_students.click(lambda: show_page(students_page), outputs=list(show_page(students_page).keys()))
423
+ # nav_teachers.click(lambda: show_page(teachers_page), outputs=list(show_page(teachers_page).keys()))
424
+ # nav_courses.click(lambda: show_page(courses_page), outputs=list(show_page(courses_page).keys()))
425
+ # nav_youtube.click(lambda: show_page(youtube_page), outputs=list(show_page(youtube_page).keys()))
426
+
427
+ # analyze_btn.click(
428
+ # process_youtube_video,
429
+ # inputs=[video_url, keywords],
430
+ # outputs=[video_thumbnail, summary, sentiment, recommendations]
431
+ # )
432
+
433
+ # logout_btn.click(
434
+ # lambda: {
435
+ # login_page: gr.update(visible=True),
436
+ # main_page: gr.update(visible=False)
437
+ # },
438
+ # outputs=[login_page, main_page]
439
+ # )
440
+
441
+ # if __name__ == "__main__":
442
+ # app.launch()
443
  def process_youtube_video(url="", keywords=""):
444
  try:
445
+ # Initialize variables
446
  thumbnail = None
447
  summary = "No transcript available"
448
  sentiment_label = "N/A"
449
  recommendations = ""
450
  subtitle_info = "No additional information available"
451
 
452
+ # If URL is provided, process the YouTube video
453
+ if url.strip():
454
+ video_id = extract_video_id(url)
455
+ if not video_id:
456
+ return None, "Invalid YouTube URL", "N/A", "", ""
 
457
 
458
+ thumbnail = f"https://img.youtube.com/vi/{video_id}/maxresdefault.jpg"
459
 
 
 
 
 
460
  try:
461
+ # Fetch transcript
462
+ transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
463
+ transcript = None
464
+ try:
465
+ transcript = transcript_list.find_transcript(['en'])
466
+ except:
467
+ transcript = transcript_list.find_generated_transcript(['en'])
468
+
469
+ text = " ".join([t['text'] for t in transcript.fetch()])
470
+ if not text.strip():
471
+ raise ValueError("Transcript is empty")
472
+
473
+ # Clean up the text for sentiment analysis
474
+ cleaned_text = clean_text_for_analysis(text)
475
+
476
+ # Sentiment analysis
477
+ sentiment = TextBlob(cleaned_text).sentiment # Use cleaned text for sentiment analysis
478
+ sentiment_label = f"{'Positive' if sentiment.polarity > 0 else 'Negative' if sentiment.polarity < 0 else 'Neutral'} ({sentiment.polarity:.2f})"
479
+
480
+ # Generate summary
481
+ model = genai.GenerativeModel("gemini-pro")
482
+ summary = model.generate_content(f"Summarize this: {cleaned_text[:4000]}").text
483
+
484
+ # Extract subtitle information
485
+ subtitle_info = extract_subtitle_info(cleaned_text)
486
+
487
+ except TranscriptsDisabled:
488
+ metadata = get_video_metadata(video_id)
489
+ summary = metadata.get("description", "⚠️ This video has disabled subtitles.")
490
+ sentiment_label = "N/A"
491
+ subtitle_info = "No subtitles available for analysis."
492
+ except NoTranscriptFound:
493
+ metadata = get_video_metadata(video_id)
494
+ summary = metadata.get("description", "⚠️ No English transcript available.")
495
+ sentiment_label = "N/A"
496
+ subtitle_info = "No subtitles available for analysis."
497
+ except Exception as e:
498
+ return thumbnail, f"⚠️ Error processing transcript: {str(e)}", "N/A", "", ""
499
+
500
+ # If keywords are provided, get recommendations
501
  if keywords.strip():
502
  recommendations = get_recommendations(keywords)
503
 
 
506
  except Exception as e:
507
  return None, f"Error: {str(e)}", "N/A", "", ""
508
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
  # Gradio Interface
510
  with gr.Blocks(theme=gr.themes.Soft()) as app:
511
  # Login Page
 
515
  password = gr.Textbox(label="Password", type="password")
516
  login_btn = gr.Button("Login", variant="primary")
517
  login_msg = gr.Markdown()
518
+
519
  # Main Interface
520
  with gr.Group(visible=False) as main_page:
521
  with gr.Row():
 
527
  nav_courses = gr.Button("πŸ“š Courses")
528
  nav_youtube = gr.Button("πŸŽ₯ YouTube Tool")
529
  logout_btn = gr.Button("πŸšͺ Logout", variant="stop")
530
+
531
  with gr.Column(scale=3):
532
  # Dashboard Content
533
  dashboard_page = gr.Group()
 
538
  - πŸ‘₯ Total Students: {len(students_data)}
539
  - πŸ‘¨β€πŸ« Total Teachers: {len(teachers_data)}
540
  - πŸ“š Total Courses: {len(courses_data)}
541
+
542
  ### Quick Actions
543
  - View student performance
544
  - Access course materials
545
  - Generate learning insights
546
  """)
547
+
548
  # Students Content
549
  students_page = gr.Group(visible=False)
550
  with students_page:
 
553
  value=students_data,
554
  headers=["ID", "Name", "Grade", "Program"]
555
  )
556
+
557
  # Teachers Content
558
  teachers_page = gr.Group(visible=False)
559
  with teachers_page:
 
562
  value=teachers_data,
563
  headers=["ID", "Name", "Subject", "Qualification"]
564
  )
565
+
566
  # Courses Content
567
  courses_page = gr.Group(visible=False)
568
  with courses_page:
 
571
  value=courses_data,
572
  headers=["ID", "Name", "Instructor", "Level"]
573
  )
574
+
575
  # YouTube Tool Content
576
  youtube_page = gr.Group(visible=False)
577
  with youtube_page:
 
587
  placeholder="e.g., python programming, machine learning"
588
  )
589
  analyze_btn = gr.Button("πŸ” Analyze Video", variant="primary")
590
+
591
  with gr.Column(scale=1):
592
  video_thumbnail = gr.Image(label="Video Preview")
593
+
594
  with gr.Row():
595
  with gr.Column():
596
  summary = gr.Textbox(label="πŸ“ Summary", lines=8)
 
610
  main_page: gr.update(visible=False),
611
  login_msg: "❌ Invalid credentials"
612
  }
613
+
614
  def show_page(page_name):
615
  updates = {
616
  dashboard_page: gr.update(visible=False),
 
621
  }
622
  updates[page_name] = gr.update(visible=True)
623
  return updates
624
+
625
  # Event Handlers
626
  login_btn.click(
627
  login_check,
628
  inputs=[username, password],
629
  outputs=[login_page, main_page, login_msg]
630
  )
631
+
632
  nav_dashboard.click(lambda: show_page(dashboard_page), outputs=list(show_page(dashboard_page).keys()))
633
  nav_students.click(lambda: show_page(students_page), outputs=list(show_page(students_page).keys()))
634
  nav_teachers.click(lambda: show_page(teachers_page), outputs=list(show_page(teachers_page).keys()))
635
  nav_courses.click(lambda: show_page(courses_page), outputs=list(show_page(courses_page).keys()))
636
  nav_youtube.click(lambda: show_page(youtube_page), outputs=list(show_page(youtube_page).keys()))
637
+
638
  analyze_btn.click(
639
  process_youtube_video,
640
  inputs=[video_url, keywords],
641
  outputs=[video_thumbnail, summary, sentiment, recommendations]
642
  )
643
+
644
  logout_btn.click(
645
  lambda: {
646
  login_page: gr.update(visible=True),