Athspi commited on
Commit
572dd26
·
verified ·
1 Parent(s): 352553f

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +169 -158
templates/index.html CHANGED
@@ -6,6 +6,7 @@
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>AI Video Dubbing</title>
8
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
 
9
  <style>
10
  :root {
11
  --primary: #4361ee;
@@ -13,9 +14,9 @@
13
  --secondary: #3f37c9;
14
  --dark: #1a1a2e;
15
  --light: #f8f9fa;
16
- --success: #4cc9f0;
17
- --warning: #f72585;
18
  --gray: #6c757d;
 
 
19
  --border-radius: 12px;
20
  --shadow: 0 10px 30px rgba(0,0,0,0.1);
21
  --transition: all 0.3s ease;
@@ -32,31 +33,37 @@
32
  background-color: #f5f7ff;
33
  color: var(--dark);
34
  line-height: 1.6;
 
35
  }
36
 
37
  .container {
38
  max-width: 800px;
39
- margin: 2rem auto;
40
- padding: 2rem;
41
  background: white;
42
  border-radius: var(--border-radius);
43
  box-shadow: var(--shadow);
 
44
  }
45
 
46
  header {
 
 
 
47
  text-align: center;
48
- margin-bottom: 2rem;
49
  }
50
 
51
  h1 {
52
- color: var(--primary);
53
- font-size: 2.5rem;
54
  margin-bottom: 0.5rem;
55
  }
56
 
57
  .subtitle {
58
- color: var(--gray);
59
- font-size: 1.1rem;
 
 
 
 
60
  }
61
 
62
  .upload-area {
@@ -67,6 +74,7 @@
67
  margin-bottom: 2rem;
68
  transition: var(--transition);
69
  cursor: pointer;
 
70
  }
71
 
72
  .upload-area:hover {
@@ -81,13 +89,19 @@
81
  }
82
 
83
  .file-input {
84
- display: none;
 
 
 
 
 
 
85
  }
86
 
87
- .file-name {
88
  margin-top: 1rem;
89
- color: var(--gray);
90
  font-size: 0.9rem;
 
91
  }
92
 
93
  .options {
@@ -103,32 +117,57 @@
103
 
104
  .option-title {
105
  font-weight: 600;
106
- margin-bottom: 0.5rem;
107
  color: var(--secondary);
 
 
 
108
  }
109
 
110
- .radio-options, .checkbox-options {
 
 
 
 
111
  display: flex;
112
- gap: 1.5rem;
 
113
  }
114
 
115
  .radio-option, .checkbox-option {
116
  display: flex;
117
  align-items: center;
118
  gap: 0.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  }
120
 
121
  .btn {
122
  background: var(--primary);
123
  color: white;
124
  border: none;
125
- padding: 1rem 2rem;
126
  border-radius: var(--border-radius);
127
  font-size: 1.1rem;
128
  font-weight: 500;
129
  cursor: pointer;
130
  width: 100%;
131
  transition: var(--transition);
 
 
 
 
132
  }
133
 
134
  .btn:hover {
@@ -137,39 +176,30 @@
137
  box-shadow: 0 5px 15px rgba(63, 55, 201, 0.3);
138
  }
139
 
140
- .result {
141
- margin-top: 2rem;
142
- animation: fadeIn 0.5s ease;
143
  }
144
 
145
- .result-title {
146
- color: var(--primary);
147
- margin-bottom: 1rem;
148
- text-align: center;
149
- }
150
-
151
- .video-container {
152
- width: 100%;
153
  border-radius: var(--border-radius);
154
- overflow: hidden;
155
- margin-bottom: 2rem;
156
- box-shadow: var(--shadow);
 
 
157
  }
158
 
159
- video {
160
- width: 100%;
161
- display: block;
 
162
  }
163
 
164
- .script-container {
165
- background: var(--dark);
166
- color: var(--light);
167
- padding: 1.5rem;
168
- border-radius: var(--border-radius);
169
- max-height: 300px;
170
- overflow-y: auto;
171
- font-family: 'Courier New', monospace;
172
- white-space: pre-wrap;
173
  }
174
 
175
  .loader {
@@ -188,23 +218,9 @@
188
  margin: 0 auto 1rem;
189
  }
190
 
191
- .alert {
192
- padding: 1rem;
193
- border-radius: var(--border-radius);
194
- margin-bottom: 1.5rem;
195
  font-weight: 500;
196
- }
197
-
198
- .alert-success {
199
- background: rgba(76, 201, 240, 0.2);
200
- color: #0a9396;
201
- border: 1px solid rgba(76, 201, 240, 0.3);
202
- }
203
-
204
- .alert-error {
205
- background: rgba(247, 37, 133, 0.1);
206
- color: var(--warning);
207
- border: 1px solid rgba(247, 37, 133, 0.2);
208
  }
209
 
210
  @keyframes spin {
@@ -212,24 +228,26 @@
212
  100% { transform: rotate(360deg); }
213
  }
214
 
215
- @keyframes fadeIn {
216
- from { opacity: 0; transform: translateY(20px); }
217
- to { opacity: 1; transform: translateY(0); }
218
- }
219
-
220
  @media (max-width: 768px) {
221
- .container {
222
- margin: 1rem;
 
 
 
223
  padding: 1.5rem;
224
  }
225
 
226
  h1 {
227
- font-size: 2rem;
 
 
 
 
228
  }
229
 
230
- .radio-options, .checkbox-options {
231
  flex-direction: column;
232
- gap: 0.5rem;
233
  }
234
  }
235
  </style>
@@ -238,129 +256,122 @@
238
  <div class="container">
239
  <header>
240
  <h1>AI Video Dubbing</h1>
241
- <p class="subtitle">Upload your video to generate a Tamil dubbed version</p>
242
  </header>
243
 
244
- {% with messages = get_flashed_messages(with_categories=true) %}
245
- {% if messages %}
246
- {% for category, message in messages %}
247
- <div class="alert alert-{{ category }}">{{ message }}</div>
248
- {% endfor %}
249
- {% endif %}
250
- {% endwith %}
251
-
252
- <form id="dub-form" action="/process" method="POST" enctype="multipart/form-data">
253
- <label class="upload-area" id="upload-label">
254
- <div class="upload-icon">
255
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
256
- <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
257
- <polyline points="17 8 12 3 7 8"></polyline>
258
- <line x1="12" y1="3" x2="12" y2="15"></line>
259
- </svg>
260
- </div>
261
- <h3>Click to upload video</h3>
262
- <p>MP4, MOV, or WebM (Max 100MB)</p>
263
- <div id="file-name" class="file-name">No file selected</div>
264
- <input type="file" id="video" name="video" class="file-input" accept="video/*">
265
- </label>
266
-
267
- <div class="options">
268
- <div class="option-group">
269
- <div class="option-title">Voice Style</div>
270
- <div class="radio-options">
271
- {% for voice, value in VOICE_CHOICES.items() %}
272
- <label class="radio-option">
273
- <input type="radio" name="voice_choice" value="{{ voice }}" {% if loop.first %}checked{% endif %}>
274
- {{ voice }}
275
- </label>
276
- {% endfor %}
277
  </div>
 
 
 
 
278
  </div>
279
 
280
- <div class="option-group">
281
- <div class="option-title">Tone Options</div>
282
- <div class="checkbox-options">
283
- <label class="checkbox-option">
284
- <input type="checkbox" name="cheerful">
285
- Cheerful tone
286
- </label>
 
 
 
 
 
 
 
287
  </div>
288
- </div>
289
- </div>
290
 
291
- <button type="submit" class="btn">Generate Dubbed Video</button>
292
- </form>
 
 
 
 
 
 
 
 
 
 
 
293
 
294
- <div class="loader" id="loader">
295
- <div class="spinner"></div>
296
- <p>Processing your video. This may take a few minutes...</p>
297
- </div>
 
298
 
299
- {% if result_video %}
300
- <div class="result">
301
- <h2 class="result-title">Your Dubbed Video</h2>
302
- <div class="video-container">
303
- <video controls>
304
- <source src="{{ result_video }}" type="video/mp4">
305
- Your browser does not support the video tag.
306
- </video>
307
  </div>
308
-
309
- <h2 class="result-title">Generated Script</h2>
310
- <div class="script-container">{{ script }}</div>
311
  </div>
312
- {% endif %}
313
  </div>
314
 
315
  <script>
316
- const form = document.getElementById('dub-form');
317
  const loader = document.getElementById('loader');
318
- const uploadLabel = document.getElementById('upload-label');
319
  const fileInput = document.getElementById('video');
320
- const fileName = document.getElementById('file-name');
321
 
322
  // Handle file selection
323
  fileInput.addEventListener('change', function() {
324
  if (this.files.length > 0) {
325
- fileName.textContent = this.files[0].name;
326
- uploadLabel.style.borderColor = '#4361ee';
327
- } else {
328
- fileName.textContent = 'No file selected';
329
- uploadLabel.style.borderColor = '#4895ef';
330
- }
331
- });
332
-
333
- // Form submission
334
- form.addEventListener('submit', function(e) {
335
- if (fileInput.files.length === 0) {
336
- e.preventDefault();
337
- alert('Please select a video file to upload.');
338
- } else {
339
- form.style.display = 'none';
340
- loader.style.display = 'block';
341
  }
342
  });
343
 
344
  // Drag and drop functionality
345
- uploadLabel.addEventListener('dragover', (e) => {
346
  e.preventDefault();
347
- uploadLabel.style.borderColor = '#4361ee';
348
- uploadLabel.style.backgroundColor = 'rgba(67, 97, 238, 0.05)';
349
  });
350
 
351
- uploadLabel.addEventListener('dragleave', () => {
352
- uploadLabel.style.borderColor = fileInput.files.length > 0 ? '#4361ee' : '#4895ef';
353
- uploadLabel.style.backgroundColor = 'transparent';
354
  });
355
 
356
- uploadLabel.addEventListener('drop', (e) => {
357
  e.preventDefault();
358
- uploadLabel.style.borderColor = '#4361ee';
359
- uploadLabel.style.backgroundColor = 'transparent';
360
 
361
  if (e.dataTransfer.files.length) {
362
  fileInput.files = e.dataTransfer.files;
363
- fileName.textContent = e.dataTransfer.files[0].name;
 
 
 
 
 
 
 
 
 
 
 
364
  }
365
  });
366
  </script>
 
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>AI Video Dubbing</title>
8
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
9
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
10
  <style>
11
  :root {
12
  --primary: #4361ee;
 
14
  --secondary: #3f37c9;
15
  --dark: #1a1a2e;
16
  --light: #f8f9fa;
 
 
17
  --gray: #6c757d;
18
+ --success: #4cc9f0;
19
+ --error: #f72585;
20
  --border-radius: 12px;
21
  --shadow: 0 10px 30px rgba(0,0,0,0.1);
22
  --transition: all 0.3s ease;
 
33
  background-color: #f5f7ff;
34
  color: var(--dark);
35
  line-height: 1.6;
36
+ padding: 20px;
37
  }
38
 
39
  .container {
40
  max-width: 800px;
41
+ margin: 0 auto;
 
42
  background: white;
43
  border-radius: var(--border-radius);
44
  box-shadow: var(--shadow);
45
+ overflow: hidden;
46
  }
47
 
48
  header {
49
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
50
+ color: white;
51
+ padding: 2rem;
52
  text-align: center;
 
53
  }
54
 
55
  h1 {
56
+ font-size: 2.2rem;
 
57
  margin-bottom: 0.5rem;
58
  }
59
 
60
  .subtitle {
61
+ font-weight: 300;
62
+ opacity: 0.9;
63
+ }
64
+
65
+ .content {
66
+ padding: 2rem;
67
  }
68
 
69
  .upload-area {
 
74
  margin-bottom: 2rem;
75
  transition: var(--transition);
76
  cursor: pointer;
77
+ position: relative;
78
  }
79
 
80
  .upload-area:hover {
 
89
  }
90
 
91
  .file-input {
92
+ position: absolute;
93
+ width: 100%;
94
+ height: 100%;
95
+ top: 0;
96
+ left: 0;
97
+ opacity: 0;
98
+ cursor: pointer;
99
  }
100
 
101
+ .file-info {
102
  margin-top: 1rem;
 
103
  font-size: 0.9rem;
104
+ color: var(--gray);
105
  }
106
 
107
  .options {
 
117
 
118
  .option-title {
119
  font-weight: 600;
120
+ margin-bottom: 0.8rem;
121
  color: var(--secondary);
122
+ display: flex;
123
+ align-items: center;
124
+ gap: 0.5rem;
125
  }
126
 
127
+ .option-title i {
128
+ font-size: 1.1rem;
129
+ }
130
+
131
+ .radio-group, .checkbox-group {
132
  display: flex;
133
+ flex-wrap: wrap;
134
+ gap: 1rem;
135
  }
136
 
137
  .radio-option, .checkbox-option {
138
  display: flex;
139
  align-items: center;
140
  gap: 0.5rem;
141
+ background: white;
142
+ padding: 0.8rem 1.2rem;
143
+ border-radius: 8px;
144
+ box-shadow: 0 2px 5px rgba(0,0,0,0.05);
145
+ transition: var(--transition);
146
+ }
147
+
148
+ .radio-option:hover, .checkbox-option:hover {
149
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
150
+ }
151
+
152
+ .radio-option input, .checkbox-option input {
153
+ accent-color: var(--primary);
154
  }
155
 
156
  .btn {
157
  background: var(--primary);
158
  color: white;
159
  border: none;
160
+ padding: 1rem;
161
  border-radius: var(--border-radius);
162
  font-size: 1.1rem;
163
  font-weight: 500;
164
  cursor: pointer;
165
  width: 100%;
166
  transition: var(--transition);
167
+ display: flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ gap: 0.8rem;
171
  }
172
 
173
  .btn:hover {
 
176
  box-shadow: 0 5px 15px rgba(63, 55, 201, 0.3);
177
  }
178
 
179
+ .btn i {
180
+ font-size: 1.2rem;
 
181
  }
182
 
183
+ .alert {
184
+ padding: 1rem;
 
 
 
 
 
 
185
  border-radius: var(--border-radius);
186
+ margin-bottom: 1.5rem;
187
+ font-weight: 500;
188
+ display: flex;
189
+ align-items: center;
190
+ gap: 0.8rem;
191
  }
192
 
193
+ .alert-success {
194
+ background: rgba(76, 201, 240, 0.2);
195
+ color: #0a9396;
196
+ border: 1px solid rgba(76, 201, 240, 0.3);
197
  }
198
 
199
+ .alert-error {
200
+ background: rgba(247, 37, 133, 0.1);
201
+ color: var(--error);
202
+ border: 1px solid rgba(247, 37, 133, 0.2);
 
 
 
 
 
203
  }
204
 
205
  .loader {
 
218
  margin: 0 auto 1rem;
219
  }
220
 
221
+ .loading-text {
 
 
 
222
  font-weight: 500;
223
+ color: var(--dark);
 
 
 
 
 
 
 
 
 
 
 
224
  }
225
 
226
  @keyframes spin {
 
228
  100% { transform: rotate(360deg); }
229
  }
230
 
 
 
 
 
 
231
  @media (max-width: 768px) {
232
+ body {
233
+ padding: 10px;
234
+ }
235
+
236
+ header {
237
  padding: 1.5rem;
238
  }
239
 
240
  h1 {
241
+ font-size: 1.8rem;
242
+ }
243
+
244
+ .content {
245
+ padding: 1.5rem;
246
  }
247
 
248
+ .radio-group, .checkbox-group {
249
  flex-direction: column;
250
+ gap: 0.8rem;
251
  }
252
  }
253
  </style>
 
256
  <div class="container">
257
  <header>
258
  <h1>AI Video Dubbing</h1>
259
+ <p class="subtitle">Transform your videos with AI-powered Tamil dubbing</p>
260
  </header>
261
 
262
+ <div class="content">
263
+ {% with messages = get_flashed_messages(with_categories=true) %}
264
+ {% if messages %}
265
+ {% for category, message in messages %}
266
+ <div class="alert alert-{{ category }}">
267
+ <i class="fas {% if category == 'success' %}fa-check-circle{% else %}fa-exclamation-circle{% endif %}"></i>
268
+ {{ message }}
269
+ </div>
270
+ {% endfor %}
271
+ {% endif %}
272
+ {% endwith %}
273
+
274
+ <form id="dubbing-form" action="/process" method="POST" enctype="multipart/form-data">
275
+ <div class="upload-area" id="upload-area">
276
+ <div class="upload-icon">
277
+ <i class="fas fa-cloud-upload-alt"></i>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  </div>
279
+ <h3>Drag & Drop Video File</h3>
280
+ <p>or click to browse (MP4, MOV, WEBM, AVI)</p>
281
+ <div id="file-info" class="file-info">No file selected</div>
282
+ <input type="file" id="video" name="video" class="file-input" accept="video/*">
283
  </div>
284
 
285
+ <div class="options">
286
+ <div class="option-group">
287
+ <div class="option-title">
288
+ <i class="fas fa-microphone"></i>
289
+ Voice Style
290
+ </div>
291
+ <div class="radio-group">
292
+ {% for voice, value in voices.items() %}
293
+ <label class="radio-option">
294
+ <input type="radio" name="voice" value="{{ value }}" {% if loop.first %}checked{% endif %}>
295
+ {{ voice }}
296
+ </label>
297
+ {% endfor %}
298
+ </div>
299
  </div>
 
 
300
 
301
+ <div class="option-group">
302
+ <div class="option-title">
303
+ <i class="fas fa-adjust"></i>
304
+ Tone Options
305
+ </div>
306
+ <div class="checkbox-group">
307
+ <label class="checkbox-option">
308
+ <input type="checkbox" name="tone">
309
+ Cheerful Tone
310
+ </label>
311
+ </div>
312
+ </div>
313
+ </div>
314
 
315
+ <button type="submit" class="btn">
316
+ <i class="fas fa-magic"></i>
317
+ Generate Dubbed Video
318
+ </button>
319
+ </form>
320
 
321
+ <div class="loader" id="loader">
322
+ <div class="spinner"></div>
323
+ <p class="loading-text">Processing your video. Please wait...</p>
 
 
 
 
 
324
  </div>
 
 
 
325
  </div>
 
326
  </div>
327
 
328
  <script>
329
+ const form = document.getElementById('dubbing-form');
330
  const loader = document.getElementById('loader');
331
+ const uploadArea = document.getElementById('upload-area');
332
  const fileInput = document.getElementById('video');
333
+ const fileInfo = document.getElementById('file-info');
334
 
335
  // Handle file selection
336
  fileInput.addEventListener('change', function() {
337
  if (this.files.length > 0) {
338
+ fileInfo.textContent = this.files[0].name;
339
+ uploadArea.style.borderColor = '#4361ee';
340
+ uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.05)';
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  }
342
  });
343
 
344
  // Drag and drop functionality
345
+ uploadArea.addEventListener('dragover', (e) => {
346
  e.preventDefault();
347
+ uploadArea.style.borderColor = '#4361ee';
348
+ uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.1)';
349
  });
350
 
351
+ uploadArea.addEventListener('dragleave', () => {
352
+ uploadArea.style.borderColor = fileInput.files.length > 0 ? '#4361ee' : '#4895ef';
353
+ uploadArea.style.backgroundColor = fileInput.files.length > 0 ? 'rgba(67, 97, 238, 0.05)' : 'transparent';
354
  });
355
 
356
+ uploadArea.addEventListener('drop', (e) => {
357
  e.preventDefault();
358
+ uploadArea.style.borderColor = '#4361ee';
359
+ uploadArea.style.backgroundColor = 'rgba(67, 97, 238, 0.05)';
360
 
361
  if (e.dataTransfer.files.length) {
362
  fileInput.files = e.dataTransfer.files;
363
+ fileInfo.textContent = e.dataTransfer.files[0].name;
364
+ }
365
+ });
366
+
367
+ // Form submission
368
+ form.addEventListener('submit', function(e) {
369
+ if (!fileInput.files.length) {
370
+ e.preventDefault();
371
+ alert('Please select a video file first.');
372
+ } else {
373
+ form.style.display = 'none';
374
+ loader.style.display = 'block';
375
  }
376
  });
377
  </script>