abesh-meena commited on
Commit
54d0c79
Β·
verified Β·
1 Parent(s): 943a15e

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +384 -148
src/streamlit_app.py CHANGED
@@ -1,218 +1,454 @@
1
  """
2
- src/streamlit_hf_optimized.py
3
 
4
- Hugging Face Spaces Optimized Version
5
- Memory-efficient, error-handling, and robust
6
- Run with: streamlit run src/streamlit_hf_optimized.py
7
  """
8
  import streamlit as st
9
- import numpy as np
10
- from PIL import Image
11
  import tempfile
12
  import os
13
  import sys
14
- import gc
15
- import warnings
 
16
 
17
- # Suppress warnings
18
- warnings.filterwarnings("ignore")
19
- os.environ.setdefault("TF_USE_LEGACY_KERAS", "1")
20
- os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", "3")
21
-
22
- # Page configuration - MUST be first
23
  st.set_page_config(
24
- page_title="DeepGuard AI - Hugging Face",
25
  page_icon="πŸ›‘οΈ",
26
  layout="wide",
27
  initial_sidebar_state="expanded"
28
  )
29
 
30
- # Add project root to path
31
  ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
32
  if ROOT_DIR not in sys.path:
33
  sys.path.insert(0, ROOT_DIR)
34
 
35
- # Import optimized model loading
36
  try:
37
- from src.model_optimized import load_model_optimized, predict_memory_efficient
38
- TENSORFLOW_AVAILABLE = True
 
 
 
 
 
 
 
39
  except ImportError as e:
40
- st.error(f"Model optimization failed: {e}")
41
- TENSORFLOW_AVAILABLE = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- # Custom CSS
44
  st.markdown("""
45
  <style>
46
- .main { padding-top: 0rem; background-color: #f3f4f6; }
47
- .header { background: linear-gradient(135deg, #1f2937 0%, #4f46e5 100%);
48
- padding: 2rem 0; margin: -1rem -1rem 2rem -1rem; }
49
- .header-title { color: #f9fafb; font-size: 3rem; font-weight: bold;
50
- text-align: center; text-shadow: 2px 2px 6px rgba(15, 23, 42, 0.6); }
51
- .header-subtitle { color: rgba(249, 250, 251, 0.9); text-align: center; margin-top: 0.5rem; }
52
- .status-indicator { display: inline-block; width: 12px; height: 12px;
53
- border-radius: 50%; margin-right: 8px; }
54
- .status-ready { background-color: #10b981; }
55
- .status-error { background-color: #ef4444; }
56
- .stButton > button { background: linear-gradient(135deg, #4f46e5 0%, #6366f1 100%);
57
- color: white; border: none; border-radius: 6px;
58
- padding: 0.6rem 2.2rem; font-weight: 600; }
59
- #MainMenu {visibility: hidden;} footer {visibility: hidden;} header {visibility: hidden;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  </style>
61
  """, unsafe_allow_html=True)
62
 
63
  # Header
64
  st.markdown("""
65
  <div class="header">
66
- <div style="text-align: center;">
67
  <h1 class="header-title">πŸ›‘οΈ DeepGuard AI</h1>
68
- <p class="header-subtitle">Hugging Face Spaces Optimized | Memory Efficient DeepFake Detection</p>
69
  </div>
70
  </div>
71
  """, unsafe_allow_html=True)
72
 
73
- # Model loading with caching and error handling
74
- @st.cache_resource
75
- def load_model_safe():
76
- """Safe model loading with multiple fallbacks"""
77
- if not TENSORFLOW_AVAILABLE:
78
- return None, "TensorFlow not available"
79
-
80
- models_to_try = [
81
- "hybrid_deepfake_model.h5",
82
- "xception_deepfake_model.h5"
83
- ]
84
-
85
- for model_name in models_to_try:
86
- model_path = os.path.join(ROOT_DIR, model_name)
87
- if os.path.exists(model_path):
88
- try:
89
- st.info(f"πŸ”„ Loading {model_name}...")
90
- model = load_model_optimized(model_path)
91
- if model is not None:
92
- st.success(f"βœ… {model_name} loaded successfully!")
93
- return model, None
94
- else:
95
- st.warning(f"⚠️ {model_name} failed to load")
96
- except Exception as e:
97
- st.error(f"❌ Error loading {model_name}: {str(e)}")
98
- continue
99
-
100
- return None, "No model could be loaded"
101
-
102
- # Load model
103
- model, model_error = load_model_safe()
104
-
105
- # Sidebar
106
  with st.sidebar:
107
- st.markdown("### πŸ“Š System Status")
108
 
109
- # Model status
110
- if model is not None:
111
- st.markdown('<span class="status-indicator status-ready"></span>Model: Ready', unsafe_allow_html=True)
112
- st.success("οΏ½οΏ½ Memory Optimized")
 
 
113
  else:
114
- st.markdown('<span class="status-indicator status-error"></span>Model: Not Loaded', unsafe_allow_html=True)
115
- if model_error:
116
- st.error(model_error)
 
 
 
 
 
 
 
 
 
117
 
118
  st.markdown("---")
119
- st.markdown("### 🎯 Features")
120
  st.markdown("""
121
- - βœ… Memory Optimized
122
- - βœ… Hugging Face Ready
123
- - βœ… Error Handling
124
- - βœ… GPU/CPU Compatible
 
125
  """)
126
 
127
  st.markdown("---")
128
- st.markdown("### πŸ“‹ Supported")
129
  st.markdown("""
130
- **Images:** JPG, PNG, JPEG
131
- **Size:** < 10MB recommended
 
 
 
 
 
 
132
  """)
133
 
134
- # Main content
135
- if model is None:
136
- st.error("❌ Model not available. Please check model files.")
137
- st.stop()
 
 
 
138
 
139
- st.markdown("### πŸ“€ Upload Image for Analysis")
140
- uploaded_file = st.file_uploader(
141
- "Choose an image file",
142
- type=["jpg", "jpeg", "png"],
143
- help="Upload an image to detect deepfake content"
144
- )
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  if uploaded_file is not None:
147
- # File size check
148
- if uploaded_file.size > 10 * 1024 * 1024: # 10MB limit
149
- st.error("❌ File too large. Please upload < 10MB")
150
- st.stop()
151
 
152
  col1, col2 = st.columns([2, 1])
153
 
154
  with col1:
155
- st.image(uploaded_file, caption="Uploaded Image", use_column_width=True)
 
 
156
 
157
  with col2:
158
- st.markdown("### πŸ“Š File Info")
159
- st.metric("Size", f"{uploaded_file.size / (1024*1024):.2f} MB")
160
- st.metric("Type", uploaded_file.type)
 
 
161
 
162
  # Analyze button
163
- if st.button("πŸ” Analyze for DeepFake", use_container_width=True, type="primary"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  try:
165
- with st.spinner("πŸ”„ Analyzing..."):
166
- # Process image
167
- img = Image.open(uploaded_file).convert("RGB")
168
- img = img.resize((224, 224))
169
- arr = np.asarray(img)
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
- # Predict
172
- prediction = predict_memory_efficient(model, arr)
 
173
 
174
- if prediction is not None:
175
- # Process result
176
- if prediction.shape[-1] == 1:
177
- prob = float(prediction[0][0])
178
- pred_label = "FAKE" if prob >= 0.5 else "REAL"
179
- confidence = max(prob, 1-prob) * 100
180
- else:
181
- pred_idx = np.argmax(prediction[0])
182
- pred_label = "FAKE" if pred_idx == 1 else "REAL"
183
- confidence = float(np.max(prediction[0])) * 100
184
-
185
- # Display result
186
- col1, col2 = st.columns([1, 1])
187
-
188
- with col1:
189
- if pred_label == "FAKE":
190
- st.error(f"πŸ”΄ {pred_label}")
191
- else:
192
- st.success(f"🟒 {pred_label}")
193
-
194
- with col2:
195
- st.metric("Confidence", f"{confidence:.2f}%")
196
-
197
- st.success("βœ… Analysis completed!")
198
  else:
199
- st.error("❌ Prediction failed")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
- # Clear memory
202
- gc.collect()
203
 
 
 
 
 
204
  except Exception as e:
205
- st.error(f"❌ Analysis error: {str(e)}")
206
- gc.collect()
 
 
 
 
 
207
 
208
  else:
209
- st.info("πŸ‘† Upload an image to start analysis")
 
 
 
 
 
 
210
 
211
  # Footer
212
- st.markdown("---")
213
  st.markdown("""
214
- <div style='text-align: center; color: #666; padding: 2rem;'>
215
- <p>πŸ›‘οΈ DeepGuard AI | Optimized for Hugging Face Spaces</p>
216
- <p style='font-size: 0.9rem;'>Memory Efficient β€’ Production Ready</p>
217
- </div>
 
 
 
 
218
  """, unsafe_allow_html=True)
 
1
  """
2
+ src/streamlit_with_api.py
3
 
4
+ Professional Streamlit UI for DeepGuard AI - DeepFake Detection System
5
+ Integrated FastAPI Backend - Starts API in background thread
6
+ Run with: streamlit run src/streamlit_with_api.py
7
  """
8
  import streamlit as st
9
+ import requests
10
+ from io import BytesIO
11
  import tempfile
12
  import os
13
  import sys
14
+ import threading
15
+ import time
16
+ import uvicorn
17
 
18
+ # Page configuration - MUST be first Streamlit command
 
 
 
 
 
19
  st.set_page_config(
20
+ page_title="DeepGuard AI - DeepFake Detection",
21
  page_icon="πŸ›‘οΈ",
22
  layout="wide",
23
  initial_sidebar_state="expanded"
24
  )
25
 
26
+ # Add project root to path for imports
27
  ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
28
  if ROOT_DIR not in sys.path:
29
  sys.path.insert(0, ROOT_DIR)
30
 
31
+ # Import FastAPI app
32
  try:
33
+ # Add app directory to path
34
+ app_dir = os.path.join(ROOT_DIR, "app")
35
+ if app_dir not in sys.path:
36
+ sys.path.insert(0, app_dir)
37
+
38
+ # Import the FastAPI app
39
+ import main
40
+ fastapi_app = main.app
41
+ FASTAPI_AVAILABLE = True
42
  except ImportError as e:
43
+ st.error(f"FastAPI not available: {e}")
44
+ FASTAPI_AVAILABLE = False
45
+
46
+ # πŸ”₯ HF-Compatible Flow: Start FastAPI in background thread
47
+ def start_api():
48
+ """Start FastAPI server in background thread"""
49
+ if FASTAPI_AVAILABLE:
50
+ try:
51
+ uvicorn.run(
52
+ fastapi_app,
53
+ host="127.0.0.1",
54
+ port=8000,
55
+ log_level="warning"
56
+ )
57
+ except Exception as e:
58
+ print(f"Error starting FastAPI: {e}")
59
+
60
+ # Start FastAPI only once per session
61
+ if FASTAPI_AVAILABLE and "api_started" not in st.session_state:
62
+ api_thread = threading.Thread(target=start_api, daemon=True)
63
+ api_thread.start()
64
+ st.session_state.api_started = True
65
+ time.sleep(2) # Give API time to start
66
 
67
+ # Custom CSS for professional look
68
  st.markdown("""
69
  <style>
70
+ /* Main container styling */
71
+ .main {
72
+ padding-top: 0rem;
73
+ background-color: #f3f4f6; /* light gray for better contrast */
74
+ }
75
+
76
+ /* Header styling */
77
+ .header {
78
+ background: linear-gradient(135deg, #1f2937 0%, #4f46e5 100%);
79
+ padding: 2rem 0;
80
+ margin: -1rem -1rem 2rem -1rem;
81
+ box-shadow: 0 4px 6px rgba(15, 23, 42, 0.35);
82
+ }
83
+
84
+ .header-content {
85
+ max-width: 1200px;
86
+ margin: 0 auto;
87
+ padding: 0 2rem;
88
+ }
89
+
90
+ .header-title {
91
+ color: #f9fafb;
92
+ font-size: 3rem;
93
+ font-weight: bold;
94
+ margin: 0;
95
+ text-align: center;
96
+ text-shadow: 2px 2px 6px rgba(15, 23, 42, 0.6);
97
+ }
98
+
99
+ .header-subtitle {
100
+ color: rgba(249, 250, 251, 0.9);
101
+ font-size: 1.2rem;
102
+ text-align: center;
103
+ margin-top: 0.5rem;
104
+ }
105
+
106
+ /* Footer styling */
107
+ .footer {
108
+ background: linear-gradient(135deg, #111827 0%, #1f2937 100%);
109
+ color: #e5e7eb;
110
+ padding: 2rem 0;
111
+ margin: 3rem -1rem -1rem -1rem;
112
+ text-align: center;
113
+ box-shadow: 0 -4px 6px rgba(15, 23, 42, 0.4);
114
+ }
115
+
116
+ .footer-content {
117
+ max-width: 1200px;
118
+ margin: 0 auto;
119
+ padding: 0 2rem;
120
+ }
121
+
122
+ .footer-text {
123
+ color: rgba(229, 231, 235, 0.9);
124
+ font-size: 1rem;
125
+ margin: 0;
126
+ }
127
+
128
+ /* Card styling */
129
+ .card {
130
+ background: #ffffff;
131
+ border-radius: 10px;
132
+ padding: 2rem;
133
+ box-shadow: 0 2px 10px rgba(15, 23, 42, 0.12);
134
+ margin-bottom: 2rem;
135
+ }
136
+
137
+ /* Button styling */
138
+ .stButton > button {
139
+ background: linear-gradient(135deg, #4f46e5 0%, #6366f1 100%);
140
+ color: #f9fafb;
141
+ border: none;
142
+ border-radius: 6px;
143
+ padding: 0.6rem 2.2rem;
144
+ font-weight: 600;
145
+ letter-spacing: 0.02em;
146
+ transition: all 0.2s ease-in-out;
147
+ }
148
+
149
+ .stButton > button:hover {
150
+ transform: translateY(-1px);
151
+ box-shadow: 0 6px 14px rgba(79, 70, 229, 0.35);
152
+ }
153
+
154
+ /* File uploader styling */
155
+ .uploadedFile {
156
+ border: 2px dashed #4f46e5;
157
+ border-radius: 10px;
158
+ padding: 1rem;
159
+ background-color: #eef2ff;
160
+ }
161
+
162
+ /* Success/Error message styling */
163
+ .stSuccess, .stError {
164
+ border-radius: 6px;
165
+ }
166
+
167
+ /* Hide Streamlit default elements */
168
+ #MainMenu {visibility: hidden;}
169
+ footer {visibility: hidden;}
170
+ header {visibility: hidden;}
171
+
172
+ /* Info boxes */
173
+ .info-box {
174
+ background: linear-gradient(135deg, #e5edff 0%, #d1fae5 100%);
175
+ padding: 1.6rem;
176
+ border-radius: 12px;
177
+ margin: 1rem 0;
178
+ border-left: 5px solid #4f46e5;
179
+ color: #111827;
180
+ }
181
+ .info-box h3,
182
+ .info-box p {
183
+ color: #111827;
184
+ }
185
+
186
+ .feature-box {
187
+ background: #ffffff;
188
+ padding: 1.6rem;
189
+ border-radius: 12px;
190
+ margin: 1rem 0;
191
+ box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
192
+ border: 1px solid #e5e7eb;
193
+ color: #111827;
194
+ }
195
+ .feature-box h4,
196
+ .feature-box li {
197
+ color: #111827;
198
+ }
199
+
200
+ /* Status indicator */
201
+ .status-indicator {
202
+ display: inline-block;
203
+ width: 12px;
204
+ height: 12px;
205
+ border-radius: 50%;
206
+ margin-right: 8px;
207
+ }
208
+ .status-ready {
209
+ background-color: #10b981;
210
+ }
211
+ .status-loading {
212
+ background-color: #f59e0b;
213
+ animation: pulse 2s infinite;
214
+ }
215
+ .status-error {
216
+ background-color: #ef4444;
217
+ }
218
+ @keyframes pulse {
219
+ 0% { opacity: 1; }
220
+ 50% { opacity: 0.5; }
221
+ 100% { opacity: 1; }
222
+ }
223
  </style>
224
  """, unsafe_allow_html=True)
225
 
226
  # Header
227
  st.markdown("""
228
  <div class="header">
229
+ <div class="header-content">
230
  <h1 class="header-title">πŸ›‘οΈ DeepGuard AI</h1>
231
+ <p class="header-subtitle">Advanced DeepFake Detection System | Integrated FastAPI Backend</p>
232
  </div>
233
  </div>
234
  """, unsafe_allow_html=True)
235
 
236
+ # Sidebar for configuration
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  with st.sidebar:
238
+ st.markdown("### βš™οΈ Configuration")
239
 
240
+ # API Status
241
+ st.markdown("### πŸ“Š Model Status")
242
+ if FASTAPI_AVAILABLE and "api_started" in st.session_state:
243
+ st.markdown('<span class="status-indicator status-ready"></span>FastAPI: Running (127.0.0.1:8000)', unsafe_allow_html=True)
244
+ st.markdown('<span class="status-indicator status-ready"></span>Video Model: Optimized', unsafe_allow_html=True)
245
+ st.markdown('<span class="status-indicator status-error"></span>Image Model: Disabled', unsafe_allow_html=True)
246
  else:
247
+ st.markdown('<span class="status-indicator status-error"></span>FastAPI: Not Available', unsafe_allow_html=True)
248
+
249
+ st.markdown("---")
250
+
251
+ # βœ… API URL - Same as requested
252
+ API_URL = "http://127.0.0.1:8000/predict"
253
+ st.text_input(
254
+ "API Endpoint",
255
+ value=API_URL,
256
+ disabled=True,
257
+ help="FastAPI running internally on port 8000"
258
+ )
259
 
260
  st.markdown("---")
261
+ st.markdown("### πŸ“‹ Supported Formats")
262
  st.markdown("""
263
+ **Images:**
264
+ - JPG, JPEG, PNG
265
+
266
+ **Videos:**
267
+ - MP4, AVI, MOV, MKV
268
  """)
269
 
270
  st.markdown("---")
271
+ st.markdown("### ℹ️ About")
272
  st.markdown("""
273
+ DeepGuard AI uses advanced deep learning
274
+ models to detect deepfake content in
275
+ videos with high accuracy.
276
+
277
+ **Memory Optimized Version:**
278
+ - ❌ Image processing disabled
279
+ - βœ… Video processing only
280
+ - πŸš€ 50-70% less memory usage
281
  """)
282
 
283
+ # Main content area
284
+ st.markdown("""
285
+ <div class="info-box">
286
+ <h3>πŸ” How It Works</h3>
287
+ <p>Upload a video file to analyze. Our AI-powered system will detect if the content is real or a deepfake using state-of-the-art neural networks. This version is optimized for memory efficiency with video-only processing.</p>
288
+ </div>
289
+ """, unsafe_allow_html=True)
290
 
291
+ # File upload section
292
+ st.markdown("### πŸ“€ Upload Video for Analysis")
 
 
 
 
293
 
294
+ col1, col2 = st.columns([1, 1])
295
+
296
+ with col1:
297
+ uploaded_file = st.file_uploader(
298
+ "Choose a video file",
299
+ type=["mp4", "avi", "mov", "mkv", "flv", "wmv", "webm"],
300
+ help="Upload a video file to detect deepfakes (Image processing disabled)",
301
+ label_visibility="collapsed"
302
+ )
303
+
304
+ with col2:
305
+ st.markdown("""
306
+ <div class="feature-box">
307
+ <h4>✨ Features</h4>
308
+ <ul>
309
+ <li>Video DeepFake Detection</li>
310
+ <li>Memory Optimized</li>
311
+ <li>Real-time Analysis</li>
312
+ <li>50-70% Less Memory Usage</li>
313
+ <li>Fast Processing</li>
314
+ </ul>
315
+ </div>
316
+ """, unsafe_allow_html=True)
317
+
318
+ # Display uploaded file and process
319
  if uploaded_file is not None:
320
+ st.markdown("---")
321
+
322
+ # Always video (since only videos are allowed)
323
+ file_extension = uploaded_file.name.split('.')[-1].lower()
324
 
325
  col1, col2 = st.columns([2, 1])
326
 
327
  with col1:
328
+ st.markdown("### πŸ“Ή Uploaded Video")
329
+ st.info(f"Video file: {uploaded_file.name} ({uploaded_file.size / (1024*1024):.2f} MB)")
330
+ st.markdown("**Note:** Video processing optimized for memory efficiency.")
331
 
332
  with col2:
333
+ st.markdown("### πŸ“Š File Information")
334
+ st.metric("File Name", uploaded_file.name)
335
+ st.metric("File Size", f"{uploaded_file.size / (1024*1024):.2f} MB")
336
+ st.metric("File Type", "Video")
337
+ st.metric("Processing", "Optimized")
338
 
339
  # Analyze button
340
+ st.markdown("---")
341
+ col1, col2, col3 = st.columns([1, 2, 1])
342
+
343
+ with col2:
344
+ analyze_button = st.button(
345
+ "πŸ” Analyze Video for DeepFake",
346
+ use_container_width=True,
347
+ type="primary"
348
+ )
349
+
350
+ if analyze_button:
351
+ # Save uploaded file temporarily
352
+ with tempfile.NamedTemporaryFile(delete=False, suffix=f".{file_extension}") as tmp_file:
353
+ tmp_file.write(uploaded_file.getvalue())
354
+ tmp_path = tmp_file.name
355
+
356
  try:
357
+ # Prepare file for upload
358
+ files = {
359
+ "file": (
360
+ uploaded_file.name,
361
+ open(tmp_path, "rb"),
362
+ uploaded_file.type if hasattr(uploaded_file, 'type') else f"video/{file_extension}"
363
+ )
364
+ }
365
+
366
+ # Show progress
367
+ with st.spinner("πŸ”„ Analyzing video... Memory optimized processing..."):
368
+ response = requests.post(API_URL, files=files, timeout=180) # Longer timeout for videos
369
+
370
+ # Close file
371
+ files["file"][1].close()
372
+
373
+ if response.status_code == 200:
374
+ result = response.json()
375
 
376
+ # Display results in a nice format
377
+ st.markdown("---")
378
+ st.markdown("### πŸ“Š Analysis Results")
379
 
380
+ # Prediction result
381
+ prediction = result.get("prediction", "unknown")
382
+ probabilities = result.get("probabilities", [[0, 0]])
383
+
384
+ # Color coding
385
+ if prediction.lower() == "fake":
386
+ prediction_color = "πŸ”΄"
387
+ prediction_bg = "#ffebee"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  else:
389
+ prediction_color = "🟒"
390
+ prediction_bg = "#e8f5e9"
391
+
392
+ col1, col2 = st.columns([1, 1])
393
+
394
+ with col1:
395
+ st.markdown(f"""
396
+ <div style="background: {prediction_bg}; padding: 2rem; border-radius: 10px; text-align: center; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
397
+ <h2 style="margin: 0; color: #333;">{prediction_color} Prediction</h2>
398
+ <h1 style="margin: 0.5rem 0; color: #333; text-transform: uppercase;">{prediction}</h1>
399
+ </div>
400
+ """, unsafe_allow_html=True)
401
+
402
+ with col2:
403
+ # Probability display
404
+ if len(probabilities) > 0 and len(probabilities[0]) >= 2:
405
+ real_prob = probabilities[0][0] * 100
406
+ fake_prob = probabilities[0][1] * 100
407
+
408
+ st.markdown("### πŸ“ˆ Confidence Scores")
409
+ st.progress(real_prob / 100, text=f"Real: {real_prob:.2f}%")
410
+ st.progress(fake_prob / 100, text=f"Fake: {fake_prob:.2f}%")
411
+
412
+ # Detailed results
413
+ with st.expander("πŸ“‹ View Detailed Results"):
414
+ st.json(result)
415
+
416
+ # Success message
417
+ st.success("βœ… Analysis completed successfully!")
418
 
419
+ else:
420
+ st.error(f"❌ API Error {response.status_code}: {response.text}")
421
 
422
+ except requests.exceptions.Timeout:
423
+ st.error("⏱️ Request timed out. The file might be too large or the server is busy.")
424
+ except requests.exceptions.ConnectionError:
425
+ st.error("πŸ”Œ Connection error. Please make sure the API server is running.")
426
  except Exception as e:
427
+ st.error(f"❌ Error: {str(e)}")
428
+ finally:
429
+ # Clean up temp file
430
+ try:
431
+ os.unlink(tmp_path)
432
+ except:
433
+ pass
434
 
435
  else:
436
+ # Show placeholder when no file is uploaded
437
+ st.markdown("""
438
+ <div style="text-align: center; padding: 4rem 2rem; background: #f8f9fa; border-radius: 10px; margin: 2rem 0;">
439
+ <h3 style="color: #667eea;">πŸ‘† Upload a file to get started</h3>
440
+ <p style="color: #666;">Select an image or video file from your device to analyze for deepfake content</p>
441
+ </div>
442
+ """, unsafe_allow_html=True)
443
 
444
  # Footer
 
445
  st.markdown("""
446
+ <div class="footer">
447
+ <div class="footer-content">
448
+ <p class="footer-text">This project made by <strong>ABESH MEENA</strong></p>
449
+ <p class="footer-text" style="margin-top: 0.5rem; font-size: 0.9rem; opacity: 0.8;">
450
+ DeepGuard AI - Advanced DeepFake Detection System | Powered by Deep Learning
451
+ </p>
452
+ </div>
453
+ </div>
454
  """, unsafe_allow_html=True)