Athspi commited on
Commit
9ee527e
·
verified ·
1 Parent(s): baaf165

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +107 -205
templates/index.html CHANGED
@@ -175,13 +175,6 @@
175
  box-shadow: 0 5px 15px rgba(63, 55, 201, 0.3);
176
  }
177
 
178
- .btn:disabled {
179
- background: var(--gray);
180
- cursor: not-allowed;
181
- transform: none;
182
- box-shadow: none;
183
- }
184
-
185
  .btn i {
186
  font-size: 1.2rem;
187
  }
@@ -208,63 +201,71 @@
208
  border: 1px solid rgba(247, 37, 133, 0.2);
209
  }
210
 
211
- .progress-container {
212
- margin: 2rem 0;
 
 
 
213
  display: none;
214
  }
215
 
216
- .progress-header {
 
 
 
217
  display: flex;
218
- justify-content: space-between;
219
- margin-bottom: 0.5rem;
220
- }
221
-
222
- .progress-bar {
223
- height: 10px;
224
- background: #e9ecef;
225
- border-radius: 5px;
226
- overflow: hidden;
227
- }
228
-
229
- .progress-fill {
230
- height: 100%;
231
- background: var(--primary);
232
- width: 0%;
233
- transition: width 0.3s ease;
234
- }
235
-
236
- .progress-details {
237
- margin-top: 1rem;
238
- font-size: 0.9rem;
239
- color: var(--gray);
240
- }
241
-
242
- .result-container {
243
- display: none;
244
- margin-top: 2rem;
245
- animation: fadeIn 0.5s ease;
246
  }
247
 
248
- @keyframes fadeIn {
249
- from { opacity: 0; }
250
- to { opacity: 1; }
251
  }
252
 
253
  .result-video {
254
  width: 100%;
255
  border-radius: var(--border-radius);
256
  margin-bottom: 1.5rem;
257
- aspect-ratio: 16/9;
258
  background: black;
259
  }
260
 
261
- .script-container {
262
  background: var(--dark);
263
  color: white;
264
  padding: 1.5rem;
265
  border-radius: var(--border-radius);
266
  max-height: 300px;
267
  overflow-y: auto;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
269
 
270
  @media (max-width: 768px) {
@@ -299,7 +300,18 @@
299
  </header>
300
 
301
  <div class="content">
302
- <div id="upload-container">
 
 
 
 
 
 
 
 
 
 
 
303
  <div class="upload-area" id="upload-area">
304
  <div class="upload-icon">
305
  <i class="fas fa-cloud-upload-alt"></i>
@@ -307,7 +319,7 @@
307
  <h3>Drag & Drop Video File</h3>
308
  <p>or click to browse (MP4, MOV, WEBM, AVI)</p>
309
  <div id="file-info" class="file-info">No file selected</div>
310
- <input type="file" id="video-input" class="file-input" accept="video/*">
311
  </div>
312
 
313
  <div class="options">
@@ -316,7 +328,7 @@
316
  <i class="fas fa-microphone"></i>
317
  Voice Style
318
  </div>
319
- <div class="radio-group" id="voice-options">
320
  {% for voice, value in voices.items() %}
321
  <label class="radio-option">
322
  <input type="radio" name="voice" value="{{ value }}" {% if loop.first %}checked{% endif %}>
@@ -333,97 +345,80 @@
333
  </div>
334
  <div class="checkbox-group">
335
  <label class="checkbox-option">
336
- <input type="checkbox" name="tone" id="tone-option">
337
  Cheerful Tone
338
  </label>
339
  </div>
340
  </div>
341
  </div>
342
 
343
- <button id="process-btn" class="btn" disabled>
344
  <i class="fas fa-magic"></i>
345
  Generate Dubbed Video
346
  </button>
347
- </div>
348
 
349
- <div class="progress-container" id="progress-container">
350
- <div class="progress-header">
351
- <span>Processing your video</span>
352
- <span id="eta">Estimating time...</span>
353
- </div>
354
- <div class="progress-bar">
355
- <div class="progress-fill" id="progress-fill"></div>
356
- </div>
357
- <div class="progress-details" id="progress-message">
358
- Preparing to process your video...
359
- </div>
360
  </div>
361
 
362
- <div class="result-container" id="result-container">
363
- <h2>Your Dubbed Video</h2>
364
- <video controls class="result-video" id="result-video">
 
 
 
 
 
365
  Your browser does not support the video tag.
366
  </video>
367
 
368
- <h2>Generated Script</h2>
369
- <div class="script-container" id="script-container"></div>
 
 
 
370
  </div>
 
371
  </div>
372
  </div>
373
 
374
  <script>
375
- // DOM Elements
 
376
  const uploadArea = document.getElementById('upload-area');
377
- const fileInput = document.getElementById('video-input');
378
  const fileInfo = document.getElementById('file-info');
379
- const processBtn = document.getElementById('process-btn');
380
- const uploadContainer = document.getElementById('upload-container');
381
- const progressContainer = document.getElementById('progress-container');
382
- const progressFill = document.getElementById('progress-fill');
383
- const progressMessage = document.getElementById('progress-message');
384
- const etaDisplay = document.getElementById('eta');
385
- const resultContainer = document.getElementById('result-container');
386
- const resultVideo = document.getElementById('result-video');
387
- const scriptContainer = document.getElementById('script-container');
388
-
389
- // State
390
- let currentTaskId = null;
391
- let statusCheckInterval = null;
392
-
393
- // Event Listeners
394
- fileInput.addEventListener('change', handleFileSelect);
395
- uploadArea.addEventListener('dragover', handleDragOver);
396
- uploadArea.addEventListener('dragleave', handleDragLeave);
397
- uploadArea.addEventListener('drop', handleDrop);
398
- processBtn.addEventListener('click', startProcessing);
399
-
400
- // Functions
401
- function handleFileSelect() {
402
  if (this.files.length > 0) {
403
  fileInfo.textContent = this.files[0].name;
404
  uploadArea.style.borderColor = '#4361ee';
405
  uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.05)';
406
- processBtn.disabled = false;
407
 
408
  // Hide any previous results
409
- resultContainer.style.display = 'none';
 
 
410
  }
411
- }
412
 
413
- function handleDragOver(e) {
 
414
  e.preventDefault();
415
  uploadArea.style.borderColor = '#4361ee';
416
  uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.1)';
417
- }
418
 
419
- function handleDragLeave() {
420
  uploadArea.style.borderColor = fileInput.files.length > 0 ? '#4361ee' : '#4895ef';
421
- uploadArea.style.backgroundColor = fileInput.files.length > 0
422
- ? 'rgba(67, 97, 238, 0.05)'
423
- : 'transparent';
424
- }
425
 
426
- function handleDrop(e) {
427
  e.preventDefault();
428
  uploadArea.style.borderColor = '#4361ee';
429
  uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.05)';
@@ -431,117 +426,24 @@
431
  if (e.dataTransfer.files.length) {
432
  fileInput.files = e.dataTransfer.files;
433
  fileInfo.textContent = e.dataTransfer.files[0].name;
434
- processBtn.disabled = false;
435
 
436
  // Hide any previous results
437
- resultContainer.style.display = 'none';
 
 
438
  }
439
- }
440
 
441
- function startProcessing() {
 
442
  if (!fileInput.files.length) {
 
443
  alert('Please select a video file first.');
444
- return;
445
- }
446
-
447
- // Get processing options
448
- const voice = document.querySelector('input[name="voice"]:checked').value;
449
- const cheerful = document.getElementById('tone-option').checked;
450
-
451
- // Prepare form data
452
- const formData = new FormData();
453
- formData.append('video', fileInput.files[0]);
454
- formData.append('voice', voice);
455
- formData.append('cheerful', cheerful);
456
-
457
- // Show progress UI
458
- uploadContainer.style.display = 'none';
459
- progressContainer.style.display = 'block';
460
- progressFill.style.width = '0%';
461
- progressMessage.textContent = 'Preparing to process your video...';
462
-
463
- // Start processing
464
- fetch('/upload', {
465
- method: 'POST',
466
- body: formData
467
- })
468
- .then(response => response.json())
469
- .then(data => {
470
- if (data.error) {
471
- throw new Error(data.error);
472
- }
473
- currentTaskId = data.task_id;
474
- startStatusChecking();
475
- })
476
- .catch(error => {
477
- showError(error.message);
478
- });
479
- }
480
-
481
- function startStatusChecking() {
482
- // Clear any existing interval
483
- if (statusCheckInterval) {
484
- clearInterval(statusCheckInterval);
485
- }
486
-
487
- // Check status every 3 seconds
488
- statusCheckInterval = setInterval(() => {
489
- fetch(`/status/${currentTaskId}`)
490
- .then(response => response.json())
491
- .then(updateStatus)
492
- .catch(error => {
493
- console.error('Status check failed:', error);
494
- });
495
- }, 3000);
496
- }
497
-
498
- function updateStatus(status) {
499
- if (status.error) {
500
- showError(status.error);
501
- clearInterval(statusCheckInterval);
502
- return;
503
- }
504
-
505
- // Update progress
506
- progressFill.style.width = `${status.progress}%`;
507
- progressMessage.textContent = status.message;
508
-
509
- // Update ETA if available
510
- if (status.eta) {
511
- etaDisplay.textContent = `ETA: ${status.eta}`;
512
  }
513
-
514
- // Handle completion
515
- if (status.status === 'complete') {
516
- clearInterval(statusCheckInterval);
517
- progressMessage.textContent = 'Processing complete!';
518
-
519
- // Show results
520
- resultVideo.src = status.result_url;
521
- scriptContainer.textContent = status.script;
522
- progressContainer.style.display = 'none';
523
- resultContainer.style.display = 'block';
524
-
525
- // Reset for next upload
526
- setTimeout(() => {
527
- uploadContainer.style.display = 'block';
528
- fileInput.value = '';
529
- fileInfo.textContent = 'No file selected';
530
- processBtn.disabled = true;
531
- uploadArea.style.borderColor = '#4895ef';
532
- uploadArea.style.backgroundColor = 'transparent';
533
- }, 5000);
534
- } else if (status.status === 'error') {
535
- showError(status.message);
536
- clearInterval(statusCheckInterval);
537
- }
538
- }
539
-
540
- function showError(message) {
541
- progressContainer.style.display = 'none';
542
- uploadContainer.style.display = 'block';
543
- alert(`Error: ${message}`);
544
- }
545
  </script>
546
  </body>
547
  </html>
 
175
  box-shadow: 0 5px 15px rgba(63, 55, 201, 0.3);
176
  }
177
 
 
 
 
 
 
 
 
178
  .btn i {
179
  font-size: 1.2rem;
180
  }
 
201
  border: 1px solid rgba(247, 37, 133, 0.2);
202
  }
203
 
204
+ .result-section {
205
+ margin-top: 2rem;
206
+ padding: 1.5rem;
207
+ background: #f8f9fe;
208
+ border-radius: var(--border-radius);
209
  display: none;
210
  }
211
 
212
+ .result-title {
213
+ font-size: 1.3rem;
214
+ margin-bottom: 1rem;
215
+ color: var(--secondary);
216
  display: flex;
217
+ align-items: center;
218
+ gap: 0.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  }
220
 
221
+ .result-title i {
222
+ font-size: 1.2rem;
 
223
  }
224
 
225
  .result-video {
226
  width: 100%;
227
  border-radius: var(--border-radius);
228
  margin-bottom: 1.5rem;
229
+ aspect-ratio: 16 / 9;
230
  background: black;
231
  }
232
 
233
+ .script-box {
234
  background: var(--dark);
235
  color: white;
236
  padding: 1.5rem;
237
  border-radius: var(--border-radius);
238
  max-height: 300px;
239
  overflow-y: auto;
240
+ font-family: monospace;
241
+ white-space: pre-wrap;
242
+ line-height: 1.6;
243
+ }
244
+
245
+ .loader {
246
+ display: none;
247
+ text-align: center;
248
+ padding: 2rem;
249
+ }
250
+
251
+ .spinner {
252
+ width: 50px;
253
+ height: 50px;
254
+ border: 5px solid rgba(67, 97, 238, 0.2);
255
+ border-top: 5px solid var(--primary);
256
+ border-radius: 50%;
257
+ animation: spin 1s linear infinite;
258
+ margin: 0 auto 1rem;
259
+ }
260
+
261
+ .loading-text {
262
+ font-weight: 500;
263
+ color: var(--dark);
264
+ }
265
+
266
+ @keyframes spin {
267
+ 0% { transform: rotate(0deg); }
268
+ 100% { transform: rotate(360deg); }
269
  }
270
 
271
  @media (max-width: 768px) {
 
300
  </header>
301
 
302
  <div class="content">
303
+ {% with messages = get_flashed_messages(with_categories=true) %}
304
+ {% if messages %}
305
+ {% for category, message in messages %}
306
+ <div class="alert alert-{{ category }}">
307
+ <i class="fas {% if category == 'success' %}fa-check-circle{% else %}fa-exclamation-circle{% endif %}"></i>
308
+ {{ message }}
309
+ </div>
310
+ {% endfor %}
311
+ {% endif %}
312
+ {% endwith %}
313
+
314
+ <form id="dubbing-form" action="/process" method="POST" enctype="multipart/form-data">
315
  <div class="upload-area" id="upload-area">
316
  <div class="upload-icon">
317
  <i class="fas fa-cloud-upload-alt"></i>
 
319
  <h3>Drag & Drop Video File</h3>
320
  <p>or click to browse (MP4, MOV, WEBM, AVI)</p>
321
  <div id="file-info" class="file-info">No file selected</div>
322
+ <input type="file" id="video" name="video" class="file-input" accept="video/*">
323
  </div>
324
 
325
  <div class="options">
 
328
  <i class="fas fa-microphone"></i>
329
  Voice Style
330
  </div>
331
+ <div class="radio-group">
332
  {% for voice, value in voices.items() %}
333
  <label class="radio-option">
334
  <input type="radio" name="voice" value="{{ value }}" {% if loop.first %}checked{% endif %}>
 
345
  </div>
346
  <div class="checkbox-group">
347
  <label class="checkbox-option">
348
+ <input type="checkbox" name="tone">
349
  Cheerful Tone
350
  </label>
351
  </div>
352
  </div>
353
  </div>
354
 
355
+ <button type="submit" class="btn">
356
  <i class="fas fa-magic"></i>
357
  Generate Dubbed Video
358
  </button>
359
+ </form>
360
 
361
+ <div class="loader" id="loader">
362
+ <div class="spinner"></div>
363
+ <p class="loading-text">Processing your video. Please wait...</p>
 
 
 
 
 
 
 
 
364
  </div>
365
 
366
+ {% if result_video %}
367
+ <div class="result-section" id="result-section" style="display: block;">
368
+ <div class="result-title">
369
+ <i class="fas fa-video"></i>
370
+ Your Dubbed Video
371
+ </div>
372
+ <video controls class="result-video">
373
+ <source src="{{ result_video }}" type="video/mp4">
374
  Your browser does not support the video tag.
375
  </video>
376
 
377
+ <div class="result-title">
378
+ <i class="fas fa-scroll"></i>
379
+ Generated Script
380
+ </div>
381
+ <div class="script-box">{{ script }}</div>
382
  </div>
383
+ {% endif %}
384
  </div>
385
  </div>
386
 
387
  <script>
388
+ const form = document.getElementById('dubbing-form');
389
+ const loader = document.getElementById('loader');
390
  const uploadArea = document.getElementById('upload-area');
391
+ const fileInput = document.getElementById('video');
392
  const fileInfo = document.getElementById('file-info');
393
+ const resultSection = document.getElementById('result-section');
394
+
395
+ // Handle file selection
396
+ fileInput.addEventListener('change', function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  if (this.files.length > 0) {
398
  fileInfo.textContent = this.files[0].name;
399
  uploadArea.style.borderColor = '#4361ee';
400
  uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.05)';
 
401
 
402
  // Hide any previous results
403
+ if (resultSection) {
404
+ resultSection.style.display = 'none';
405
+ }
406
  }
407
+ });
408
 
409
+ // Drag and drop functionality
410
+ uploadArea.addEventListener('dragover', (e) => {
411
  e.preventDefault();
412
  uploadArea.style.borderColor = '#4361ee';
413
  uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.1)';
414
+ });
415
 
416
+ uploadArea.addEventListener('dragleave', () => {
417
  uploadArea.style.borderColor = fileInput.files.length > 0 ? '#4361ee' : '#4895ef';
418
+ uploadArea.style.backgroundColor = fileInput.files.length > 0 ? 'rgba(67, 97, 238, 0.05)' : 'transparent';
419
+ });
 
 
420
 
421
+ uploadArea.addEventListener('drop', (e) => {
422
  e.preventDefault();
423
  uploadArea.style.borderColor = '#4361ee';
424
  uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.05)';
 
426
  if (e.dataTransfer.files.length) {
427
  fileInput.files = e.dataTransfer.files;
428
  fileInfo.textContent = e.dataTransfer.files[0].name;
 
429
 
430
  // Hide any previous results
431
+ if (resultSection) {
432
+ resultSection.style.display = 'none';
433
+ }
434
  }
435
+ });
436
 
437
+ // Form submission
438
+ form.addEventListener('submit', function(e) {
439
  if (!fileInput.files.length) {
440
+ e.preventDefault();
441
  alert('Please select a video file first.');
442
+ } else {
443
+ form.style.display = 'none';
444
+ loader.style.display = 'block';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  }
446
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  </script>
448
  </body>
449
  </html>