Subham629 commited on
Commit
4e48c0a
Β·
verified Β·
1 Parent(s): 2b4ed0c

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +694 -0
app.py ADDED
@@ -0,0 +1,694 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import requests
4
+ import json
5
+ import base64
6
+ import plotly.express as px
7
+ import plotly.graph_objects as go
8
+ import os
9
+ from io import BytesIO
10
+ from datetime import datetime
11
+
12
+ # Set page configuration
13
+ st.set_page_config(
14
+ page_title="News Summarization & Analysis",
15
+ page_icon="πŸ“°",
16
+ layout="wide",
17
+ initial_sidebar_state="expanded"
18
+ )
19
+
20
+ # API endpoint (Flask backend)
21
+ API_URL = "http://0.0.0.0:8000"
22
+
23
+ def get_company_news(company_name):
24
+ """Fetch news articles for a given company via API"""
25
+ try:
26
+ response = requests.get(f"{API_URL}/news/{company_name}")
27
+ if response.status_code == 200:
28
+ return response.json()
29
+ else:
30
+ st.error(f"Error fetching news: {response.text}")
31
+ return None
32
+ except Exception as e:
33
+ st.error(f"API connection error: {str(e)}")
34
+ return None
35
+
36
+ def get_analysis(company_name, articles):
37
+ """Get sentiment analysis and comparative analysis via API"""
38
+ try:
39
+ response = requests.post(
40
+ f"{API_URL}/analyze",
41
+ json={
42
+ "company": company_name,
43
+ "articles": articles
44
+ }
45
+ )
46
+ if response.status_code == 200:
47
+ return response.json()
48
+ else:
49
+ st.error(f"Error analyzing content: {response.text}")
50
+ return None
51
+ except Exception as e:
52
+ st.error(f"API connection error: {str(e)}")
53
+ return None
54
+
55
+ def get_tts(text, language='hi'):
56
+ """Get TTS audio in the specified language via API"""
57
+ try:
58
+ response = requests.post(
59
+ f"{API_URL}/tts",
60
+ json={
61
+ "text": text,
62
+ "language": language
63
+ }
64
+ )
65
+ if response.status_code == 200:
66
+ return response.content, language
67
+ else:
68
+ st.error(f"Error generating speech: {response.text}")
69
+ return None, language
70
+ except Exception as e:
71
+ st.error(f"API connection error: {str(e)}")
72
+ return None, language
73
+
74
+ def create_audio_player(audio_bytes):
75
+ """Create an HTML audio player for the TTS audio"""
76
+ audio_base64 = base64.b64encode(audio_bytes).decode()
77
+ audio_html = f"""
78
+ <audio controls>
79
+ <source src="data:audio/mp3;base64,{audio_base64}" type="audio/mp3">
80
+ Your browser does not support the audio element.
81
+ </audio>
82
+ """
83
+ return audio_html
84
+
85
+ def display_article_details(articles):
86
+ """Display detailed information about each article in a card layout"""
87
+ st.markdown("""
88
+ <style>
89
+ .article-card {
90
+ background-color: #f9f9f9;
91
+ border-radius: 10px;
92
+ padding: 20px;
93
+ margin-bottom: 20px;
94
+ border-left: 5px solid #4CAF50;
95
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
96
+ }
97
+ .article-negative {
98
+ border-left: 5px solid #F44336;
99
+ }
100
+ .article-neutral {
101
+ border-left: 5px solid #9E9E9E;
102
+ }
103
+ .article-title {
104
+ font-size: 18px;
105
+ font-weight: bold;
106
+ margin-bottom: 10px;
107
+ }
108
+ .article-meta {
109
+ color: #666;
110
+ font-size: 14px;
111
+ margin-bottom: 10px;
112
+ }
113
+ .article-summary {
114
+ margin-bottom: 15px;
115
+ }
116
+ .article-sentiment {
117
+ display: inline-block;
118
+ padding: 5px 10px;
119
+ border-radius: 20px;
120
+ font-size: 14px;
121
+ margin-right: 10px;
122
+ }
123
+ .sentiment-positive {
124
+ background-color: rgba(76, 175, 80, 0.2);
125
+ color: #2E7D32;
126
+ }
127
+ .sentiment-negative {
128
+ background-color: rgba(244, 67, 54, 0.2);
129
+ color: #C62828;
130
+ }
131
+ .sentiment-neutral {
132
+ background-color: rgba(158, 158, 158, 0.2);
133
+ color: #616161;
134
+ }
135
+ .topic-tag {
136
+ display: inline-block;
137
+ background-color: #E0E0E0;
138
+ padding: 3px 10px;
139
+ border-radius: 15px;
140
+ margin-right: 8px;
141
+ margin-bottom: 8px;
142
+ font-size: 12px;
143
+ }
144
+ </style>
145
+ """, unsafe_allow_html=True)
146
+
147
+ cols = st.columns(1)
148
+
149
+ for i, article in enumerate(articles):
150
+ sentiment = article['Sentiment']
151
+ sentiment_class = ""
152
+ tag_class = ""
153
+
154
+ if sentiment == "Positive":
155
+ sentiment_class = "article-positive"
156
+ tag_class = "sentiment-positive"
157
+ elif sentiment == "Negative":
158
+ sentiment_class = "article-negative"
159
+ tag_class = "sentiment-negative"
160
+ else:
161
+ sentiment_class = "article-neutral"
162
+ tag_class = "sentiment-neutral"
163
+
164
+ article_html = f"""
165
+ <div class="article-card {sentiment_class}">
166
+ <div class="article-title">{article['Title']}</div>
167
+ <div class="article-meta">
168
+ Source: {article.get('Source', 'Unknown')} |
169
+ Date: {article.get('Date', 'N/A')}
170
+ </div>
171
+ <div class="article-summary">{article['Summary']}</div>
172
+ <div class="article-sentiment {tag_class}">{sentiment}</div>
173
+ """
174
+
175
+ # Add topics as tags
176
+ if 'Topics' in article and article['Topics']:
177
+ article_html += '<div class="article-topics">'
178
+ for topic in article['Topics']:
179
+ article_html += f'<span class="topic-tag">{topic}</span>'
180
+ article_html += '</div>'
181
+
182
+ article_html += f"""
183
+ <div style="margin-top: 10px;">
184
+ <a href="{article.get('URL', '#')}" target="_blank" style="text-decoration: none;">
185
+ <span style="color: #1E88E5;">Read original article β†’</span>
186
+ </a>
187
+ </div>
188
+ </div>
189
+ """
190
+
191
+ cols[0].markdown(article_html, unsafe_allow_html=True)
192
+
193
+ def display_sentiment_distribution(analysis):
194
+ """Display sentiment distribution chart with enhanced styling"""
195
+ if 'Comparative Sentiment Score' in analysis and 'Sentiment Distribution' in analysis['Comparative Sentiment Score']:
196
+ dist = analysis['Comparative Sentiment Score']['Sentiment Distribution']
197
+ data = {
198
+ 'Sentiment': list(dist.keys()),
199
+ 'Count': list(dist.values())
200
+ }
201
+ df = pd.DataFrame(data)
202
+
203
+ # Create color map
204
+ color_map = {
205
+ 'Positive': '#4CAF50',
206
+ 'Negative': '#F44336',
207
+ 'Neutral': '#9E9E9E'
208
+ }
209
+
210
+ # Create a card container for the chart
211
+ st.markdown("""
212
+ <div style="background-color:white; padding:20px; border-radius:10px; box-shadow:0 4px 6px rgba(0,0,0,0.1); margin-bottom:20px;">
213
+ <h3 style="margin-bottom:15px; border-bottom:1px solid #eee; padding-bottom:10px;">Sentiment Distribution</h3>
214
+ </div>
215
+ """, unsafe_allow_html=True)
216
+
217
+ # Create pie chart for sentiment distribution
218
+ labels = list(dist.keys())
219
+ values = list(dist.values())
220
+ colors = [color_map[label] for label in labels]
221
+
222
+ # Create two columns for different chart types
223
+ col1, col2 = st.columns(2)
224
+
225
+ with col1:
226
+ # Bar chart
227
+ fig_bar = px.bar(
228
+ df,
229
+ x='Sentiment',
230
+ y='Count',
231
+ color='Sentiment',
232
+ color_discrete_map=color_map,
233
+ title="Sentiment Distribution (Bar Chart)"
234
+ )
235
+ fig_bar.update_layout(
236
+ plot_bgcolor='rgba(0,0,0,0)',
237
+ paper_bgcolor='rgba(0,0,0,0)',
238
+ font=dict(size=14),
239
+ margin=dict(l=20, r=20, t=40, b=20),
240
+ height=350
241
+ )
242
+ st.plotly_chart(fig_bar, use_container_width=True)
243
+
244
+ with col2:
245
+ # Pie chart
246
+ fig_pie = go.Figure(data=[go.Pie(
247
+ labels=labels,
248
+ values=values,
249
+ marker=dict(colors=colors),
250
+ textinfo='percent+label',
251
+ hole=.4
252
+ )])
253
+ fig_pie.update_layout(
254
+ title_text="Sentiment Distribution (Pie Chart)",
255
+ annotations=[dict(text='Sentiment', x=0.5, y=0.5, font_size=14, showarrow=False)],
256
+ plot_bgcolor='rgba(0,0,0,0)',
257
+ paper_bgcolor='rgba(0,0,0,0)',
258
+ font=dict(size=14),
259
+ margin=dict(l=20, r=20, t=40, b=20),
260
+ height=350
261
+ )
262
+ st.plotly_chart(fig_pie, use_container_width=True)
263
+
264
+ # Add a summary of the sentiment distribution
265
+ total = sum(values)
266
+ if total > 0:
267
+ percentages = {label: (count/total*100) for label, count in zip(labels, values)}
268
+
269
+ # Create a summary card
270
+ summary_html = """
271
+ <div style="background-color:#f8f9fa; padding:15px; border-radius:8px; margin-top:10px;">
272
+ <h4 style="margin-bottom:10px;">Summary</h4>
273
+ <p style="font-size:15px; line-height:1.5;">
274
+ """
275
+
276
+ for label in labels:
277
+ if label in percentages:
278
+ color = color_map[label]
279
+ summary_html += f'<span style="color:{color}; font-weight:bold;">{label}</span>: {percentages[label]:.1f}% | '
280
+
281
+ summary_html = summary_html.rstrip(' | ') + '</p></div>'
282
+ st.markdown(summary_html, unsafe_allow_html=True)
283
+
284
+ def display_topic_analysis(analysis):
285
+ """Display topic analysis visualization"""
286
+ if 'Comparative Sentiment Score' in analysis and 'Topic Overlap' in analysis['Comparative Sentiment Score']:
287
+ topic_data = analysis['Comparative Sentiment Score']['Topic Overlap']
288
+
289
+ # Prepare data for visualization
290
+ all_topics = set()
291
+ if 'Common Topics' in topic_data:
292
+ all_topics.update(topic_data['Common Topics'])
293
+
294
+ for i in range(1, 11): # Check for unique topics in each article
295
+ key = f"Unique Topics in Article {i}"
296
+ if key in topic_data and topic_data[key]:
297
+ all_topics.update(topic_data[key])
298
+
299
+ # Count topic occurrences across articles
300
+ topic_counts = {}
301
+ for topic in all_topics:
302
+ count = 0
303
+ if 'Common Topics' in topic_data and topic in topic_data['Common Topics']:
304
+ count += len(analysis['Articles']) # All articles have common topics
305
+
306
+ for i in range(1, 11):
307
+ key = f"Unique Topics in Article {i}"
308
+ if key in topic_data and topic in topic_data[key]:
309
+ count += 1
310
+
311
+ topic_counts[topic] = count
312
+
313
+ # Create DataFrame and visualization
314
+ topic_df = pd.DataFrame({
315
+ 'Topic': list(topic_counts.keys()),
316
+ 'Occurrence': list(topic_counts.values())
317
+ }).sort_values('Occurrence', ascending=False)
318
+
319
+ fig = px.bar(
320
+ topic_df,
321
+ x='Topic',
322
+ y='Occurrence',
323
+ title="Topic Distribution Across Articles",
324
+ color='Occurrence',
325
+ color_continuous_scale=px.colors.sequential.Viridis
326
+ )
327
+ st.plotly_chart(fig, use_container_width=True)
328
+
329
+ def display_comparative_analysis(analysis):
330
+ """Display comparative analysis details"""
331
+ if 'Comparative Sentiment Score' in analysis and 'Coverage Differences' in analysis['Comparative Sentiment Score']:
332
+ differences = analysis['Comparative Sentiment Score']['Coverage Differences']
333
+
334
+ st.subheader("Comparative Analysis")
335
+ for i, diff in enumerate(differences):
336
+ with st.expander(f"Comparison {i+1}"):
337
+ st.write(f"**Comparison**: {diff['Comparison']}")
338
+ st.write(f"**Impact**: {diff['Impact']}")
339
+
340
+ # Main app layout with enhanced design and better readability
341
+ st.markdown("""
342
+ <style>
343
+ .main-header {
344
+ text-align: center;
345
+ padding: 2rem 0;
346
+ background: linear-gradient(to right, #2E7D32, #1565C0);
347
+ color: white;
348
+ border-radius: 10px;
349
+ margin-bottom: 30px;
350
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
351
+ }
352
+ .app-title {
353
+ font-size: 36px;
354
+ font-weight: bold;
355
+ text-shadow: 1px 1px 3px rgba(0,0,0,0.3);
356
+ margin-bottom: 15px;
357
+ }
358
+ .app-description {
359
+ font-size: 18px;
360
+ color: white;
361
+ max-width: 800px;
362
+ margin: 0 auto;
363
+ line-height: 1.6;
364
+ text-shadow: 0px 1px 2px rgba(0,0,0,0.2);
365
+ }
366
+ .benefits-container {
367
+ display: flex;
368
+ justify-content: center;
369
+ gap: 20px;
370
+ margin-top: 20px;
371
+ flex-wrap: wrap;
372
+ }
373
+ .benefit-item {
374
+ background-color: rgba(255,255,255,0.25);
375
+ padding: 8px 15px;
376
+ border-radius: 20px;
377
+ font-size: 14px;
378
+ font-weight: 500;
379
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
380
+ text-shadow: 0px 1px 1px rgba(0,0,0,0.1);
381
+ }
382
+ </style>
383
+
384
+ <div class="main-header">
385
+ <div class="app-title">πŸ“° News Summarization & Sentiment Analysis</div>
386
+ <p class="app-description">
387
+ Analyze recent news articles about any company. Get sentiment analysis, topic extraction,
388
+ and multilingual text-to-speech summaries instantly in 10 different languages.
389
+ </p>
390
+ <div class="benefits-container">
391
+ <div class="benefit-item">βœ… Real-time News Analysis</div>
392
+ <div class="benefit-item">πŸ“Š Sentiment Visualization</div>
393
+ <div class="benefit-item">πŸ” Topic Extraction</div>
394
+ <div class="benefit-item">🎧 Multilingual Text-to-Speech</div>
395
+ </div>
396
+ </div>
397
+ """, unsafe_allow_html=True)
398
+
399
+ # Input form with enhanced styling
400
+ st.markdown("""
401
+ <style>
402
+ .search-container {
403
+ background-color: white;
404
+ padding: 25px;
405
+ border-radius: 10px;
406
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
407
+ margin-bottom: 30px;
408
+ }
409
+ .search-title {
410
+ font-size: 20px;
411
+ font-weight: bold;
412
+ margin-bottom: 15px;
413
+ color: #333;
414
+ }
415
+ .search-description {
416
+ color: #666;
417
+ margin-bottom: 20px;
418
+ font-size: 16px;
419
+ }
420
+ </style>
421
+ <div class="search-container">
422
+ <div class="search-title">πŸ” Search for Company News</div>
423
+ <div class="search-description">
424
+ Enter a company name below to analyze its recent news coverage.
425
+ Try companies like Tesla, Apple, Microsoft, Google, or Amazon.
426
+ </div>
427
+ </div>
428
+ """, unsafe_allow_html=True)
429
+
430
+ with st.form("search_form"):
431
+ col1, col2 = st.columns([3, 1])
432
+ with col1:
433
+ company_name = st.text_input("Company Name", placeholder="Enter company name (e.g., Tesla)", label_visibility="collapsed")
434
+ with col2:
435
+ submit_button = st.form_submit_button("πŸ” Analyze News")
436
+
437
+ # Add some example buttons below the form
438
+ st.markdown("""
439
+ <style>
440
+ .example-row {
441
+ display: flex;
442
+ gap: 10px;
443
+ margin-top: 10px;
444
+ flex-wrap: wrap;
445
+ justify-content: center;
446
+ }
447
+ .example-chip {
448
+ background-color: #f0f2f6;
449
+ border-radius: 20px;
450
+ padding: 5px 15px;
451
+ font-size: 12px;
452
+ cursor: pointer;
453
+ transition: all 0.2s;
454
+ }
455
+ .example-chip:hover {
456
+ background-color: #4CAF50;
457
+ color: white;
458
+ }
459
+ </style>
460
+ <div style="text-align: center; margin-top: 10px; font-size: 12px; color: #666;">
461
+ Try analyzing news for:
462
+ <div class="example-row">
463
+ <div class="example-chip">Tesla</div>
464
+ <div class="example-chip">Apple</div>
465
+ <div class="example-chip">Microsoft</div>
466
+ <div class="example-chip">Google</div>
467
+ <div class="example-chip">Amazon</div>
468
+ </div>
469
+ </div>
470
+ """, unsafe_allow_html=True)
471
+
472
+ # Process form submission
473
+ if submit_button and company_name:
474
+ with st.spinner(f"Fetching news articles about {company_name}..."):
475
+ articles_data = get_company_news(company_name)
476
+
477
+ if articles_data and 'articles' in articles_data and len(articles_data['articles']) > 0:
478
+ articles = articles_data['articles']
479
+
480
+ with st.spinner("Performing sentiment analysis..."):
481
+ analysis_result = get_analysis(company_name, articles)
482
+
483
+ if analysis_result:
484
+ # Store complete analysis in session state
485
+ st.session_state.analysis = analysis_result
486
+
487
+ # Display summary and stats
488
+ st.header(f"Analysis Results for {company_name}")
489
+
490
+ # Create a nice header with company logo or icon
491
+ company_icon = "🏒" # Default company icon
492
+ if company_name.lower() == "tesla":
493
+ company_icon = "πŸš—"
494
+ elif company_name.lower() == "apple":
495
+ company_icon = "🍎"
496
+ elif company_name.lower() == "microsoft":
497
+ company_icon = "πŸ’»"
498
+ elif company_name.lower() == "amazon":
499
+ company_icon = "πŸ“¦"
500
+ elif company_name.lower() == "google":
501
+ company_icon = "πŸ”"
502
+
503
+ st.markdown(f"""
504
+ <div style="background-color:#f0f2f6; padding:20px; border-radius:10px; margin-bottom:20px;">
505
+ <h1 style="text-align:center; margin-bottom:20px;">{company_icon} {company_name} News Analysis</h1>
506
+ <p style="text-align:center; font-size:16px; color:#666;">
507
+ Analysis of {len(analysis_result['Articles'])} news articles | Generated on {datetime.now().strftime('%B %d, %Y')}
508
+ </p>
509
+ </div>
510
+ """, unsafe_allow_html=True)
511
+
512
+ # Display visualization tabs with custom styling
513
+ st.markdown("""
514
+ <style>
515
+ .stTabs [data-baseweb="tab-list"] {
516
+ gap: 8px;
517
+ }
518
+ .stTabs [data-baseweb="tab"] {
519
+ border-radius: 4px 4px 0px 0px;
520
+ padding: 10px 16px;
521
+ background-color: #f0f2f6;
522
+ }
523
+ .stTabs [aria-selected="true"] {
524
+ background-color: #4CAF50 !important;
525
+ color: white !important;
526
+ }
527
+ </style>
528
+ """, unsafe_allow_html=True)
529
+
530
+ tab1, tab2, tab3, tab4 = st.tabs(["πŸ“Š Overview", "😊 Sentiment Analysis", "πŸ” Topic Analysis", "πŸ“° Article Details"])
531
+
532
+ with tab1:
533
+ # Create a card-style container for the summary
534
+ st.markdown("""
535
+ <div style="background-color:white; padding:25px; border-radius:10px; box-shadow:0 4px 6px rgba(0,0,0,0.1); margin-bottom:20px;">
536
+ <h3 style="margin-bottom:15px; border-bottom:1px solid #eee; padding-bottom:10px;">Executive Summary</h3>
537
+ """, unsafe_allow_html=True)
538
+
539
+ summary_text = analysis_result.get("Final Sentiment Analysis", "No summary available")
540
+ st.markdown(f"<p style='font-size:16px; line-height:1.6;'>{summary_text}</p>", unsafe_allow_html=True)
541
+
542
+ st.markdown("</div>", unsafe_allow_html=True)
543
+
544
+ if "Final Sentiment Analysis" in analysis_result:
545
+ # Language selection for TTS
546
+ language_options = {
547
+ "hi": "Hindi",
548
+ "en": "English",
549
+ "es": "Spanish",
550
+ "fr": "French",
551
+ "de": "German",
552
+ "ja": "Japanese",
553
+ "zh-CN": "Chinese",
554
+ "ru": "Russian",
555
+ "ar": "Arabic",
556
+ "it": "Italian"
557
+ }
558
+
559
+ selected_language = st.selectbox(
560
+ "Select Language for Text-to-Speech",
561
+ options=list(language_options.keys()),
562
+ format_func=lambda x: language_options[x],
563
+ index=0 # Default to Hindi
564
+ )
565
+
566
+ with st.spinner(f"Generating {language_options[selected_language]} text-to-speech..."):
567
+ audio_bytes, language = get_tts(analysis_result["Final Sentiment Analysis"], selected_language)
568
+
569
+ if audio_bytes:
570
+ st.markdown(f"""
571
+ <div style="background-color:white; padding:25px; border-radius:10px; box-shadow:0 4px 6px rgba(0,0,0,0.1);">
572
+ <h3 style="margin-bottom:15px; border-bottom:1px solid #eee; padding-bottom:10px;">
573
+ <span style="vertical-align:middle;">πŸ”Š</span> {language_options[language]} Text-to-Speech Summary
574
+ </h3>
575
+ """, unsafe_allow_html=True)
576
+
577
+ st.markdown(create_audio_player(audio_bytes), unsafe_allow_html=True)
578
+ st.markdown("</div>", unsafe_allow_html=True)
579
+
580
+ with tab2:
581
+ st.subheader("Sentiment Distribution")
582
+ display_sentiment_distribution(analysis_result)
583
+ display_comparative_analysis(analysis_result)
584
+
585
+ with tab3:
586
+ st.subheader("Topic Analysis")
587
+ display_topic_analysis(analysis_result)
588
+
589
+ with tab4:
590
+ st.subheader("Article Details")
591
+ display_article_details(analysis_result['Articles'])
592
+
593
+ # Add video download tab
594
+ tab5 = st.tabs(["πŸ“Ή Demo Video"])[0]
595
+ with tab5:
596
+ st.subheader("Record and Download Demo")
597
+ if st.button("Record Demo (30s)"):
598
+ with st.spinner("Recording demo video..."):
599
+ try:
600
+ from record_demo import record_demo
601
+ record_demo()
602
+ st.success("Recording completed!")
603
+
604
+ # Display download button
605
+ with open('demo_video.mp4', 'rb') as video_file:
606
+ video_bytes = video_file.read()
607
+ st.download_button(
608
+ label="Download Demo Video",
609
+ data=video_bytes,
610
+ file_name="company_analysis_demo.mp4",
611
+ mime="video/mp4"
612
+ )
613
+ except Exception as e:
614
+ st.error(f"Error recording video: {str(e)}")
615
+
616
+ # Display JSON output option
617
+ st.subheader("Raw JSON Output")
618
+ with st.expander("Show JSON"):
619
+ st.json(analysis_result)
620
+
621
+ else:
622
+ st.error("Failed to perform analysis. Please try again.")
623
+ else:
624
+ st.warning(f"No news articles found for {company_name}. Please try another company name.")
625
+
626
+ # Footer with enhanced design and improved readability
627
+ st.markdown("""
628
+ <style>
629
+ .footer {
630
+ background: linear-gradient(to right, #2E7D32, #1565C0);
631
+ padding: 30px 10px;
632
+ color: white;
633
+ border-radius: 10px;
634
+ text-align: center;
635
+ margin-top: 40px;
636
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
637
+ }
638
+ .footer-content {
639
+ max-width: 800px;
640
+ margin: 0 auto;
641
+ }
642
+ .footer-title {
643
+ font-size: 22px;
644
+ margin-bottom: 15px;
645
+ font-weight: bold;
646
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.3);
647
+ }
648
+ .footer-text {
649
+ font-size: 15px;
650
+ line-height: 1.6;
651
+ margin-bottom: 15px;
652
+ text-shadow: 0px 1px 1px rgba(0,0,0,0.2);
653
+ }
654
+ .footer-features {
655
+ display: flex;
656
+ justify-content: center;
657
+ gap: 15px;
658
+ margin: 20px 0;
659
+ flex-wrap: wrap;
660
+ }
661
+ .footer-feature {
662
+ background-color: rgba(255,255,255,0.25);
663
+ padding: 8px 15px;
664
+ border-radius: 20px;
665
+ font-size: 14px;
666
+ font-weight: 500;
667
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
668
+ text-shadow: 0px 1px 1px rgba(0,0,0,0.1);
669
+ }
670
+ .footer-copyright {
671
+ margin-top: 15px;
672
+ font-size: 14px;
673
+ opacity: 0.9;
674
+ text-shadow: 0px 1px 1px rgba(0,0,0,0.1);
675
+ }
676
+ </style>
677
+
678
+ <div class="footer">
679
+ <div class="footer-content">
680
+ <div class="footer-title">πŸ“° News Summarization & Analysis Application</div>
681
+ <div class="footer-text">
682
+ A powerful tool for analyzing news content, extracting sentiments, and generating insights.
683
+ Get comprehensive analysis of any company's news coverage within seconds.
684
+ </div>
685
+ <div class="footer-features">
686
+ <div class="footer-feature">⚑ Real-time News Extraction</div>
687
+ <div class="footer-feature">πŸ“Š Sentiment Analysis</div>
688
+ <div class="footer-feature">πŸ” Topic Analysis</div>
689
+ <div class="footer-feature">🎧 Multilingual Text-to-Speech</div>
690
+ </div>
691
+ <div class="footer-copyright">Created with Streamlit β€’ {datetime.now().year}</div>
692
+ </div>
693
+ </div>
694
+ """, unsafe_allow_html=True)