Athspi commited on
Commit
2f3393b
·
verified ·
1 Parent(s): a30e87b

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +315 -87
templates/index.html CHANGED
@@ -1,140 +1,368 @@
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>AI Video Narrator</title>
 
7
  <style>
8
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
9
-
10
  :root {
11
- --primary-color: #0d6efd;
12
- --secondary-color: #6c757d;
13
- --background-color: #f4f7f9;
14
- --card-background: #ffffff;
15
- --heading-color: #212529;
16
- --border-color: #e9ecef;
17
- --shadow: 0 10px 40px rgba(0,0,0,0.07);
 
 
 
 
 
 
 
 
 
 
18
  }
19
 
20
- *, *::before, *::after { box-sizing: border-box; }
21
  body {
22
- font-family: 'Inter', sans-serif; margin: 0; background-color: var(--background-color);
23
- display: flex; justify-content: center; align-items: flex-start; padding: 2rem; min-height: 100vh;
 
 
24
  }
 
25
  .container {
26
- background-color: var(--card-background); padding: 2.5rem 3rem; border-radius: 24px;
27
- border: 1px solid var(--border-color); box-shadow: var(--shadow); width: 100%; max-width: 700px;
28
- }
29
- header { text-align: center; margin-bottom: 2.5rem; }
30
- h1 { color: var(--heading-color); font-weight: 700; margin-bottom: 0.5rem; }
31
- p.subtitle { color: var(--secondary-color); font-size: 1.1rem; }
32
-
33
- .form-content { display: block; animation: fadeIn 0.5s ease; }
34
- @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
35
-
36
- .form-step { margin-bottom: 1.5rem; padding: 1.5rem; border: 1px solid var(--border-color); border-radius: 12px; }
37
- .form-step legend { font-size: 1.1rem; font-weight: 600; color: var(--primary-color); padding: 0 0.5rem; margin-left: 0.5rem; }
38
-
39
- .file-upload-label { width: 100%; border: 2px dashed var(--border-color); padding: 2rem; border-radius: 8px; text-align: center; cursor: pointer; transition: background-color 0.2s, border-color 0.2s; }
40
- .file-upload-label:hover { background-color: #f8f9fa; border-color: var(--primary-color); }
41
- input[type="file"] { display: none; }
42
- #file-name { margin-top: 1rem; font-style: italic; color: var(--secondary-color); font-size: 0.9rem; }
43
-
44
- .submit-btn {
45
- width: 100%; background: var(--primary-color);
46
- color: white; border: none; padding: 1rem; border-radius: 12px;
47
- font-size: 1.2rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease;
48
- box-shadow: 0 4px 15px rgba(13, 110, 253, 0.2); margin-top: 1rem;
49
- }
50
- .submit-btn:hover { transform: translateY(-3px); box-shadow: 0 7px 20px rgba(13, 110, 253, 0.3); }
51
-
52
- .result-section, .flash-message, #loader { margin-top: 2.5rem; text-align: center; }
53
- h2 { border-bottom: 3px solid var(--primary-color); padding-bottom: 0.5rem; display: inline-block; margin-bottom: 1.5rem; }
54
- video { width: 100%; border-radius: 12px; box-shadow: var(--shadow); aspect-ratio: 16 / 9; background-color: #000; }
55
- .script-box { background-color: #212529; color: #f8f9fa; padding: 1.5rem; border-radius: 8px; text-align: left; white-space: pre-wrap; word-wrap: break-word; font-family: "SF Mono", monospace; line-height: 1.7; margin-top: 1rem; max-height: 250px; overflow-y: auto; }
56
- .flash-message { padding: 1rem; border-radius: 8px; font-weight: 500; }
57
- .flash-message.error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
58
- .flash-message.success { background-color: #d1e7dd; color: #0f5132; border: 1px solid #badbcc; }
59
-
60
- #loader { display: none; }
61
- #loader p { font-size: 1.2rem; font-weight: 600; color: var(--primary-color); }
62
- .spinner { width: 50px; height: 50px; border: 5px solid #f3f3f3; border-top: 5px solid var(--primary-color); border-radius: 50%; animation: spin 1s linear infinite; margin: 0 auto 1rem; }
63
- @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  </style>
65
  </head>
66
  <body>
67
  <div class="container">
68
  <header>
69
- <h1>AI Video Narrator</h1>
70
- <p class="subtitle">Upload your video to generate a dubbed version</p>
71
  </header>
72
 
73
  {% with messages = get_flashed_messages(with_categories=true) %}
74
  {% if messages %}
75
  {% for category, message in messages %}
76
- <div class="flash-message {{ category }}">{{ message }}</div>
77
  {% endfor %}
78
  {% endif %}
79
  {% endwith %}
80
 
81
- <form id="dubbing-form" action="/process" method="POST" enctype="multipart/form-data">
82
- <div class="form-content">
83
- <label for="video" class="file-upload-label">
84
- <span>Click to select a video file</span>
85
- <div id="file-name">No file chosen</div>
86
- </label>
87
- <input type="file" id="video" name="video" accept="video/mp4,video/mov,video/webm">
88
- </div>
 
 
 
 
 
 
89
 
90
- <fieldset class="form-step" style="padding-top: 0.5rem;">
91
- <legend>Configure Voice</legend>
92
- <div class="radio-group">
93
- <label><input type="radio" name="voice_choice" value="Male (Charon)" checked> Male Voice</label>
94
- <label><input type="radio" name="voice_choice" value="Female (Zephyr)"> Female Voice</label>
 
 
 
 
 
 
95
  </div>
96
- <div class="checkbox-group" style="margin-top: 1rem;">
97
- <label><input type="checkbox" name="cheerful"> Use a more cheerful tone</label>
 
 
 
 
 
 
 
98
  </div>
99
- </fieldset>
100
-
101
- <button type="submit" class="submit-btn">Generate Dubbed Video</button>
102
  </form>
103
 
104
- <div id="loader">
105
  <div class="spinner"></div>
106
- <p>Processing your video... This may take a few minutes.</p>
107
  </div>
108
 
109
  {% if result_video %}
110
- <div class="result-section">
111
- <h2>Your Dubbed Video</h2>
112
- <video controls src="{{ result_video }}"></video>
113
- <h2>Generated Script</h2>
114
- <div class="script-box">{{ script }}</div>
 
 
 
 
 
 
115
  </div>
116
  {% endif %}
117
  </div>
118
 
119
  <script>
120
- const form = document.getElementById('dubbing-form');
121
  const loader = document.getElementById('loader');
122
- const videoInput = document.getElementById('video');
123
- const fileNameDisplay = document.getElementById('file-name');
 
124
 
125
- videoInput.addEventListener('change', function() {
126
- fileNameDisplay.textContent = this.files.length > 0 ? this.files[0].name : 'No file chosen';
 
 
 
 
 
 
 
127
  });
128
 
129
- form.addEventListener('submit', function(event) {
130
- if (!videoInput.value) {
131
- event.preventDefault();
 
132
  alert('Please select a video file to upload.');
133
  } else {
134
  form.style.display = 'none';
135
  loader.style.display = 'block';
136
  }
137
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  </script>
139
  </body>
140
  </html>
 
1
+ <!-- templates/index.html -->
2
  <!DOCTYPE html>
3
  <html lang="en">
4
  <head>
5
  <meta charset="UTF-8">
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;
12
+ --primary-light: #4895ef;
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;
22
+ }
23
+
24
+ * {
25
+ margin: 0;
26
+ padding: 0;
27
+ box-sizing: border-box;
28
  }
29
 
 
30
  body {
31
+ font-family: 'Poppins', sans-serif;
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 {
63
+ border: 2px dashed var(--primary-light);
64
+ border-radius: var(--border-radius);
65
+ padding: 3rem 2rem;
66
+ text-align: center;
67
+ margin-bottom: 2rem;
68
+ transition: var(--transition);
69
+ cursor: pointer;
70
+ }
71
+
72
+ .upload-area:hover {
73
+ border-color: var(--primary);
74
+ background: rgba(67, 97, 238, 0.05);
75
+ }
76
+
77
+ .upload-icon {
78
+ font-size: 3rem;
79
+ color: var(--primary-light);
80
+ margin-bottom: 1rem;
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 {
94
+ background: #f8f9fe;
95
+ padding: 1.5rem;
96
+ border-radius: var(--border-radius);
97
+ margin-bottom: 2rem;
98
+ }
99
+
100
+ .option-group {
101
+ margin-bottom: 1.5rem;
102
+ }
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 {
135
+ background: var(--secondary);
136
+ transform: translateY(-2px);
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 {
176
+ display: none;
177
+ text-align: center;
178
+ padding: 2rem;
179
+ }
180
+
181
+ .spinner {
182
+ width: 50px;
183
+ height: 50px;
184
+ border: 5px solid rgba(67, 97, 238, 0.2);
185
+ border-top: 5px solid var(--primary);
186
+ border-radius: 50%;
187
+ animation: spin 1s linear infinite;
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 {
211
+ 0% { transform: rotate(0deg); }
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>
236
  </head>
237
  <body>
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>
367
  </body>
368
  </html>