eubottura commited on
Commit
0d800b6
·
verified ·
1 Parent(s): a257bfc

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +141 -136
index.html CHANGED
@@ -4,7 +4,7 @@
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Douyin V3 Video Downloader Pro</title>
8
  <style>
9
  * {
10
  margin: 0;
@@ -13,78 +13,72 @@
13
  }
14
 
15
  :root {
16
- --primary: #007AFF;
17
- --primary-hover: #0056CC;
18
- --secondary: #F2F2F7;
19
  --background: #FFFFFF;
20
  --surface: #FFFFFF;
21
- --text-primary: #1D1D1F;
22
- --text-secondary: #6E6E73;
23
- --text-tertiary: #98989D;
24
- --border: rgba(0, 0, 0, 0.08);
25
- --border-hover: rgba(0, 0, 0, 0.12);
26
- --success: #30D158;
27
- --warning: #FF9F0A;
28
- --error: #FF3B30;
29
- --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.04);
30
- --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.06);
31
- --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.08);
32
- --radius: 12px;
33
- --radius-lg: 16px;
34
  }
35
 
36
  body {
37
- font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', sans-serif;
38
  background: var(--background);
39
  min-height: 100vh;
40
  color: var(--text-primary);
41
- line-height: 1.6;
42
  -webkit-font-smoothing: antialiased;
43
  -moz-osx-font-smoothing: grayscale;
44
  }
45
 
46
  .container {
47
- max-width: 960px;
48
  margin: 0 auto;
49
- padding: 3rem 2rem;
50
  }
51
 
52
  header {
53
  text-align: center;
54
- margin-bottom: 4rem;
55
  }
56
 
57
  h1 {
58
- font-size: 2.75rem;
59
- font-weight: 700;
60
- letter-spacing: -0.02em;
61
- margin-bottom: 0.75rem;
62
- background: linear-gradient(135deg, #000 0%, #666 100%);
63
- -webkit-background-clip: text;
64
- -webkit-text-fill-color: transparent;
65
- background-clip: text;
66
  }
67
 
68
  .subtitle {
69
  color: var(--text-secondary);
70
- font-size: 1.125rem;
71
  font-weight: 400;
72
  }
73
 
74
  .credit {
75
- margin-top: 1.5rem;
76
- font-size: 0.875rem;
77
  color: var(--text-tertiary);
78
  }
79
 
80
  .credit a {
81
- color: var(--primary);
82
  text-decoration: none;
83
  transition: color 0.2s ease;
84
  }
85
 
86
  .credit a:hover {
87
- color: var(--primary-hover);
88
  text-decoration: underline;
89
  }
90
 
@@ -92,13 +86,12 @@
92
  background: var(--surface);
93
  border-radius: var(--radius-lg);
94
  border: 1px solid var(--border);
95
- box-shadow: var(--shadow-md);
96
- padding: 3rem;
97
- margin-bottom: 2rem;
98
  }
99
 
100
  .notice {
101
- padding: 1rem 1.25rem;
102
  border-radius: var(--radius);
103
  font-size: 0.875rem;
104
  margin-bottom: 1.5rem;
@@ -108,22 +101,22 @@
108
  }
109
 
110
  .cors-notice {
111
- background: rgba(255, 159, 10, 0.08);
112
- border: 1px solid rgba(255, 159, 10, 0.2);
113
- color: var(--warning);
114
  }
115
 
116
  .success-notice {
117
- background: rgba(48, 209, 88, 0.08);
118
- border: 1px solid rgba(48, 209, 88, 0.2);
119
- color: var(--success);
120
  display: none;
121
  }
122
 
123
  .info-box {
124
- background: rgba(0, 122, 255, 0.06);
125
- border: 1px solid rgba(0, 122, 255, 0.12);
126
- color: var(--primary);
127
  }
128
 
129
  .input-section {
@@ -132,21 +125,21 @@
132
 
133
  label {
134
  display: block;
135
- margin-bottom: 0.75rem;
136
  font-weight: 500;
137
- font-size: 0.9375rem;
138
  color: var(--text-primary);
139
  }
140
 
141
  textarea {
142
  width: 100%;
143
- min-height: 160px;
144
- padding: 1rem 1.25rem;
145
  background: var(--secondary);
146
  border: 1px solid var(--border);
147
  border-radius: var(--radius);
148
  color: var(--text-primary);
149
- font-size: 0.9375rem;
150
  font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
151
  resize: vertical;
152
  transition: all 0.2s ease;
@@ -155,9 +148,9 @@
155
 
156
  textarea:focus {
157
  outline: none;
158
- border-color: var(--primary);
159
  background: var(--surface);
160
- box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1);
161
  }
162
 
163
  textarea::placeholder {
@@ -166,33 +159,25 @@
166
 
167
  .button-group {
168
  display: flex;
169
- gap: 0.75rem;
170
- margin-top: 1.5rem;
171
  flex-wrap: wrap;
172
  }
173
 
174
  button {
175
- padding: 0.75rem 1.5rem;
176
  background: var(--primary);
177
  color: white;
178
  border: none;
179
  border-radius: var(--radius);
180
- font-size: 0.9375rem;
181
  font-weight: 500;
182
  cursor: pointer;
183
  transition: all 0.2s ease;
184
- position: relative;
185
- overflow: hidden;
186
  }
187
 
188
  button:hover {
189
  background: var(--primary-hover);
190
- transform: translateY(-1px);
191
- box-shadow: var(--shadow-sm);
192
- }
193
-
194
- button:active {
195
- transform: translateY(0);
196
  }
197
 
198
  button.secondary {
@@ -209,7 +194,7 @@
209
  .loading {
210
  display: none;
211
  text-align: center;
212
- padding: 3rem;
213
  }
214
 
215
  .loading.show {
@@ -217,48 +202,50 @@
217
  }
218
 
219
  .spinner {
220
- width: 40px;
221
- height: 40px;
222
- border: 3px solid var(--border);
223
- border-top-color: var(--primary);
224
  border-radius: 50%;
225
  margin: 0 auto 1rem;
226
  animation: spin 1s linear infinite;
227
  }
228
 
229
  @keyframes spin {
230
- to { transform: rotate(360deg); }
 
 
231
  }
232
 
233
  .message {
234
- padding: 1rem 1.25rem;
235
  border-radius: var(--radius);
236
- font-size: 0.9375rem;
237
  margin-top: 1rem;
238
  display: none;
239
  }
240
 
241
  .error-message {
242
- background: rgba(255, 59, 48, 0.08);
243
- border: 1px solid rgba(255, 59, 48, 0.2);
244
- color: var(--error);
245
  }
246
 
247
  .info-message {
248
- background: rgba(0, 122, 255, 0.08);
249
- border: 1px solid rgba(0, 122, 255, 0.2);
250
- color: var(--primary);
251
  }
252
 
253
  .log-box {
254
  background: var(--secondary);
255
  border: 1px solid var(--border);
256
  border-radius: var(--radius);
257
- padding: 1rem;
258
  margin: 1rem 0;
259
  font-family: 'SF Mono', 'Monaco', monospace;
260
- font-size: 0.8125rem;
261
- max-height: 200px;
262
  overflow-y: auto;
263
  display: none;
264
  }
@@ -268,9 +255,17 @@
268
  color: var(--text-secondary);
269
  }
270
 
271
- .log-entry.success { color: var(--success); }
272
- .log-entry.error { color: var(--error); }
273
- .log-entry.info { color: var(--primary); }
 
 
 
 
 
 
 
 
274
 
275
  .results-section {
276
  margin-top: 2rem;
@@ -288,13 +283,13 @@
288
  display: flex;
289
  justify-content: space-between;
290
  align-items: center;
291
- margin-bottom: 1.5rem;
292
- padding-bottom: 1rem;
293
  border-bottom: 1px solid var(--border);
294
  }
295
 
296
  .results-title {
297
- font-size: 1.25rem;
298
  font-weight: 600;
299
  color: var(--text-primary);
300
  display: flex;
@@ -304,7 +299,7 @@
304
 
305
  .copy-all-btn {
306
  padding: 0.5rem 1rem;
307
- font-size: 0.875rem;
308
  }
309
 
310
  .url-list {
@@ -312,14 +307,14 @@
312
  }
313
 
314
  .url-item {
315
- padding: 1.25rem;
316
- margin-bottom: 0.75rem;
317
  background: var(--surface);
318
  border: 1px solid var(--border);
319
  border-radius: var(--radius);
320
  display: flex;
321
  align-items: center;
322
- gap: 1rem;
323
  transition: all 0.2s ease;
324
  animation: slideIn 0.3s ease forwards;
325
  opacity: 0;
@@ -330,6 +325,7 @@
330
  opacity: 0;
331
  transform: translateX(-10px);
332
  }
 
333
  to {
334
  opacity: 1;
335
  transform: translateX(0);
@@ -345,18 +341,18 @@
345
  flex: 1;
346
  word-break: break-all;
347
  font-family: 'SF Mono', 'Monaco', monospace;
348
- font-size: 0.875rem;
349
  color: var(--text-secondary);
350
  }
351
 
352
  .url-content.v3-link {
353
- color: var(--success);
354
  font-weight: 500;
355
  }
356
 
357
  .copy-btn {
358
- padding: 0.5rem 0.875rem;
359
- font-size: 0.8125rem;
360
  background: var(--secondary);
361
  color: var(--text-primary);
362
  border: 1px solid var(--border);
@@ -364,56 +360,64 @@
364
  }
365
 
366
  .copy-btn.copied {
367
- background: var(--success);
368
  color: white;
369
- border-color: var(--success);
370
  }
371
 
372
  .status-indicator {
373
- width: 6px;
374
- height: 6px;
375
  border-radius: 50%;
376
  margin-left: 0.5rem;
377
  }
378
 
379
- .status-indicator.success { background: var(--success); }
380
- .status-indicator.fallback { background: var(--error); }
381
- .status-indicator.processing { background: var(--warning); }
 
 
 
 
 
 
 
 
382
 
383
  .quality-badge {
384
- padding: 0.25rem 0.625rem;
385
- border-radius: 20px;
386
- font-size: 0.75rem;
387
  font-weight: 500;
388
  margin-left: 0.5rem;
389
  }
390
 
391
  .quality-badge {
392
- background: rgba(48, 209, 88, 0.1);
393
- color: var(--success);
394
  }
395
 
396
  .quality-badge.fallback {
397
- background: rgba(255, 59, 48, 0.1);
398
- color: var(--error);
399
  }
400
 
401
  .quality-badge.processing {
402
- background: rgba(255, 159, 10, 0.1);
403
- color: var(--warning);
404
  }
405
 
406
- @media (max-width: 768px) {
407
  .container {
408
  padding: 2rem 1rem;
409
  }
410
 
411
  h1 {
412
- font-size: 2rem;
413
  }
414
 
415
  .main-card {
416
- padding: 2rem 1.5rem;
417
  }
418
 
419
  .button-group {
@@ -426,7 +430,7 @@
426
 
427
  .results-header {
428
  flex-direction: column;
429
- gap: 1rem;
430
  align-items: stretch;
431
  }
432
  }
@@ -436,33 +440,34 @@
436
  <body>
437
  <div class="container">
438
  <header>
439
- <h1>Douyin V3 Video Downloader</h1>
440
- <p class="subtitle">Extract highest-quality V3 direct download links</p>
441
- <p class="credit">Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a></p>
 
442
  </header>
443
 
444
  <main class="main-card">
445
  <div class="notice cors-notice">
446
- <strong>Enhanced Processing:</strong> Uses multiple API endpoints and advanced extraction techniques.
447
  </div>
448
 
449
  <div class="notice success-notice" id="successNotice">
450
- <strong>Success!</strong> V3 links extracted successfully.
451
  </div>
452
 
453
  <div class="notice info-box">
454
- 📌 <strong>Processing Strategy:</strong>
455
- <br>1. Extract video ID from URL
456
  <br>2. Try multiple API endpoints
457
- <br>3. Parse response for V3 links
458
- <br>4. Sort by quality (highest first)
459
  </div>
460
 
461
  <section class="input-section">
462
- <label for="urlInput">Enter Douyin Video URLs (one per line):</label>
463
  <textarea
464
  id="urlInput"
465
- placeholder="https://www.douyin.com/video/7123456789012345678?modal_id=7123456789012345678&#10;https://v.douyin.com/ABCDEFG123456/&#10;https://www.douyin.com/user/987654321?modal_id=7123456789012345678"
466
  ></textarea>
467
  <div class="button-group">
468
  <button onclick="processUrls()">Process URLs</button>
@@ -474,7 +479,7 @@
474
 
475
  <div class="loading" id="loading">
476
  <div class="spinner"></div>
477
- <p>Extracting V3 links...</p>
478
  </div>
479
 
480
  <div class="message error-message" id="errorMessage"></div>
@@ -485,7 +490,7 @@
485
  <section class="results-section" id="resultsSection">
486
  <div class="results-header">
487
  <h2 class="results-title">
488
- V3 Download Links
489
  <span class="status-indicator success"></span>
490
  </h2>
491
  <button class="copy-all-btn" onclick="copyAllUrls()">Copy All</button>
@@ -822,7 +827,7 @@
822
  if (successCount > 0) {
823
  document.getElementById('successNotice').classList.add('show');
824
  document.getElementById('successNotice').style.display = 'flex';
825
- showInfo(`Successfully extracted ${successCount} V3 link(s) out of ${urls.length} URLs`);
826
  }
827
  }
828
 
@@ -833,7 +838,7 @@
833
  results.forEach((result, index) => {
834
  const li = document.createElement('li');
835
  li.className = 'url-item';
836
- li.style.animationDelay = `${index * 0.05}s`;
837
 
838
  const isFallback = result.isFallback;
839
  const isV3 = !isFallback && (result.url.includes('v3') || result.quality === 'V3');
@@ -852,7 +857,7 @@
852
 
853
  let sourceInfo = '';
854
  if (result.source) {
855
- sourceInfo = `<small style="color: var(--text-tertiary); font-size: 0.75rem;">[${result.source}]</small>`;
856
  }
857
 
858
  const urlContentClass = isV3 ? 'url-content v3-link' : 'url-content';
@@ -892,7 +897,7 @@
892
  const button = document.querySelector('.copy-all-btn');
893
  const originalText = button.textContent;
894
  button.textContent = '✓ Copied All!';
895
- button.style.background = 'var(--success)';
896
  button.style.color = 'white';
897
  setTimeout(() => {
898
  button.textContent = originalText;
@@ -957,7 +962,7 @@ https://www.douyin.com/user/MS4wLjABAAAA5rOKyL98?modal_id=7300000034567890123`;
957
  }
958
  });
959
 
960
- console.log('🚀 Douyin V3 Video Downloader Ready');
961
  </script>
962
  </body>
963
 
 
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Douyin Video Downloader</title>
8
  <style>
9
  * {
10
  margin: 0;
 
13
  }
14
 
15
  :root {
16
+ --primary: #000000;
17
+ --primary-hover: #333333;
18
+ --secondary: #F8F8F8;
19
  --background: #FFFFFF;
20
  --surface: #FFFFFF;
21
+ --text-primary: #000000;
22
+ --text-secondary: #666666;
23
+ --text-tertiary: #999999;
24
+ --border: #E5E5E5;
25
+ --border-hover: #CCCCCC;
26
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
27
+ --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.06);
28
+ --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.08);
29
+ --radius: 8px;
30
+ --radius-lg: 12px;
 
 
 
31
  }
32
 
33
  body {
34
+ font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', 'Inter', sans-serif;
35
  background: var(--background);
36
  min-height: 100vh;
37
  color: var(--text-primary);
38
+ line-height: 1.5;
39
  -webkit-font-smoothing: antialiased;
40
  -moz-osx-font-smoothing: grayscale;
41
  }
42
 
43
  .container {
44
+ max-width: 800px;
45
  margin: 0 auto;
46
+ padding: 4rem 2rem;
47
  }
48
 
49
  header {
50
  text-align: center;
51
+ margin-bottom: 3rem;
52
  }
53
 
54
  h1 {
55
+ font-size: 2rem;
56
+ font-weight: 600;
57
+ letter-spacing: -0.01em;
58
+ margin-bottom: 0.5rem;
59
+ color: var(--text-primary);
 
 
 
60
  }
61
 
62
  .subtitle {
63
  color: var(--text-secondary);
64
+ font-size: 0.95rem;
65
  font-weight: 400;
66
  }
67
 
68
  .credit {
69
+ margin-top: 2rem;
70
+ font-size: 0.8rem;
71
  color: var(--text-tertiary);
72
  }
73
 
74
  .credit a {
75
+ color: var(--text-secondary);
76
  text-decoration: none;
77
  transition: color 0.2s ease;
78
  }
79
 
80
  .credit a:hover {
81
+ color: var(--text-primary);
82
  text-decoration: underline;
83
  }
84
 
 
86
  background: var(--surface);
87
  border-radius: var(--radius-lg);
88
  border: 1px solid var(--border);
89
+ box-shadow: var(--shadow-sm);
90
+ padding: 2.5rem;
 
91
  }
92
 
93
  .notice {
94
+ padding: 1rem;
95
  border-radius: var(--radius);
96
  font-size: 0.875rem;
97
  margin-bottom: 1.5rem;
 
101
  }
102
 
103
  .cors-notice {
104
+ background: #F8F8F8;
105
+ border: 1px solid var(--border);
106
+ color: var(--text-secondary);
107
  }
108
 
109
  .success-notice {
110
+ background: #F0F9F0;
111
+ border: 1px solid #D0E7D0;
112
+ color: #2D5A2D;
113
  display: none;
114
  }
115
 
116
  .info-box {
117
+ background: #F8F9FA;
118
+ border: 1px solid var(--border);
119
+ color: var(--text-secondary);
120
  }
121
 
122
  .input-section {
 
125
 
126
  label {
127
  display: block;
128
+ margin-bottom: 0.5rem;
129
  font-weight: 500;
130
+ font-size: 0.9rem;
131
  color: var(--text-primary);
132
  }
133
 
134
  textarea {
135
  width: 100%;
136
+ min-height: 140px;
137
+ padding: 0.875rem;
138
  background: var(--secondary);
139
  border: 1px solid var(--border);
140
  border-radius: var(--radius);
141
  color: var(--text-primary);
142
+ font-size: 0.875rem;
143
  font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace;
144
  resize: vertical;
145
  transition: all 0.2s ease;
 
148
 
149
  textarea:focus {
150
  outline: none;
151
+ border-color: var(--text-primary);
152
  background: var(--surface);
153
+ box-shadow: 0 0 0 1px var(--text-primary);
154
  }
155
 
156
  textarea::placeholder {
 
159
 
160
  .button-group {
161
  display: flex;
162
+ gap: 0.5rem;
163
+ margin-top: 1rem;
164
  flex-wrap: wrap;
165
  }
166
 
167
  button {
168
+ padding: 0.625rem 1.25rem;
169
  background: var(--primary);
170
  color: white;
171
  border: none;
172
  border-radius: var(--radius);
173
+ font-size: 0.875rem;
174
  font-weight: 500;
175
  cursor: pointer;
176
  transition: all 0.2s ease;
 
 
177
  }
178
 
179
  button:hover {
180
  background: var(--primary-hover);
 
 
 
 
 
 
181
  }
182
 
183
  button.secondary {
 
194
  .loading {
195
  display: none;
196
  text-align: center;
197
+ padding: 2rem;
198
  }
199
 
200
  .loading.show {
 
202
  }
203
 
204
  .spinner {
205
+ width: 32px;
206
+ height: 32px;
207
+ border: 2px solid var(--border);
208
+ border-top-color: var(--text-primary);
209
  border-radius: 50%;
210
  margin: 0 auto 1rem;
211
  animation: spin 1s linear infinite;
212
  }
213
 
214
  @keyframes spin {
215
+ to {
216
+ transform: rotate(360deg);
217
+ }
218
  }
219
 
220
  .message {
221
+ padding: 0.875rem;
222
  border-radius: var(--radius);
223
+ font-size: 0.875rem;
224
  margin-top: 1rem;
225
  display: none;
226
  }
227
 
228
  .error-message {
229
+ background: #FFF5F5;
230
+ border: 1px solid #FED7D7;
231
+ color: #742A2A;
232
  }
233
 
234
  .info-message {
235
+ background: #F0F7FF;
236
+ border: 1px solid #BEE3F8;
237
+ color: #2A4365;
238
  }
239
 
240
  .log-box {
241
  background: var(--secondary);
242
  border: 1px solid var(--border);
243
  border-radius: var(--radius);
244
+ padding: 0.875rem;
245
  margin: 1rem 0;
246
  font-family: 'SF Mono', 'Monaco', monospace;
247
+ font-size: 0.75rem;
248
+ max-height: 180px;
249
  overflow-y: auto;
250
  display: none;
251
  }
 
255
  color: var(--text-secondary);
256
  }
257
 
258
+ .log-entry.success {
259
+ color: #2D5A2D;
260
+ }
261
+
262
+ .log-entry.error {
263
+ color: #742A2A;
264
+ }
265
+
266
+ .log-entry.info {
267
+ color: #2A4365;
268
+ }
269
 
270
  .results-section {
271
  margin-top: 2rem;
 
283
  display: flex;
284
  justify-content: space-between;
285
  align-items: center;
286
+ margin-bottom: 1rem;
287
+ padding-bottom: 0.75rem;
288
  border-bottom: 1px solid var(--border);
289
  }
290
 
291
  .results-title {
292
+ font-size: 1.125rem;
293
  font-weight: 600;
294
  color: var(--text-primary);
295
  display: flex;
 
299
 
300
  .copy-all-btn {
301
  padding: 0.5rem 1rem;
302
+ font-size: 0.8rem;
303
  }
304
 
305
  .url-list {
 
307
  }
308
 
309
  .url-item {
310
+ padding: 1rem;
311
+ margin-bottom: 0.5rem;
312
  background: var(--surface);
313
  border: 1px solid var(--border);
314
  border-radius: var(--radius);
315
  display: flex;
316
  align-items: center;
317
+ gap: 0.75rem;
318
  transition: all 0.2s ease;
319
  animation: slideIn 0.3s ease forwards;
320
  opacity: 0;
 
325
  opacity: 0;
326
  transform: translateX(-10px);
327
  }
328
+
329
  to {
330
  opacity: 1;
331
  transform: translateX(0);
 
341
  flex: 1;
342
  word-break: break-all;
343
  font-family: 'SF Mono', 'Monaco', monospace;
344
+ font-size: 0.8rem;
345
  color: var(--text-secondary);
346
  }
347
 
348
  .url-content.v3-link {
349
+ color: var(--text-primary);
350
  font-weight: 500;
351
  }
352
 
353
  .copy-btn {
354
+ padding: 0.375rem 0.75rem;
355
+ font-size: 0.75rem;
356
  background: var(--secondary);
357
  color: var(--text-primary);
358
  border: 1px solid var(--border);
 
360
  }
361
 
362
  .copy-btn.copied {
363
+ background: #2D5A2D;
364
  color: white;
365
+ border-color: #2D5A2D;
366
  }
367
 
368
  .status-indicator {
369
+ width: 5px;
370
+ height: 5px;
371
  border-radius: 50%;
372
  margin-left: 0.5rem;
373
  }
374
 
375
+ .status-indicator.success {
376
+ background: #2D5A2D;
377
+ }
378
+
379
+ .status-indicator.fallback {
380
+ background: #742A2A;
381
+ }
382
+
383
+ .status-indicator.processing {
384
+ background: #744210;
385
+ }
386
 
387
  .quality-badge {
388
+ padding: 0.25rem 0.5rem;
389
+ border-radius: 4px;
390
+ font-size: 0.7rem;
391
  font-weight: 500;
392
  margin-left: 0.5rem;
393
  }
394
 
395
  .quality-badge {
396
+ background: #F0F9F0;
397
+ color: #2D5A2D;
398
  }
399
 
400
  .quality-badge.fallback {
401
+ background: #FFF5F5;
402
+ color: #742A2A;
403
  }
404
 
405
  .quality-badge.processing {
406
+ background: #FFFBF0;
407
+ color: #744210;
408
  }
409
 
410
+ @media (max-width: 640px) {
411
  .container {
412
  padding: 2rem 1rem;
413
  }
414
 
415
  h1 {
416
+ font-size: 1.75rem;
417
  }
418
 
419
  .main-card {
420
+ padding: 1.5rem;
421
  }
422
 
423
  .button-group {
 
430
 
431
  .results-header {
432
  flex-direction: column;
433
+ gap: 0.75rem;
434
  align-items: stretch;
435
  }
436
  }
 
440
  <body>
441
  <div class="container">
442
  <header>
443
+ <h1>Video Downloader</h1>
444
+ <p class="subtitle">Extract direct download links</p>
445
+ <p class="credit">Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
446
+ </p>
447
  </header>
448
 
449
  <main class="main-card">
450
  <div class="notice cors-notice">
451
+ <strong>Enhanced Processing:</strong> Multiple extraction methods applied.
452
  </div>
453
 
454
  <div class="notice success-notice" id="successNotice">
455
+ <strong>Success!</strong> Links extracted successfully.
456
  </div>
457
 
458
  <div class="notice info-box">
459
+ <strong>Processing Strategy:</strong>
460
+ <br>1. Extract video ID
461
  <br>2. Try multiple API endpoints
462
+ <br>3. Parse for download links
463
+ <br>4. Sort by quality
464
  </div>
465
 
466
  <section class="input-section">
467
+ <label for="urlInput">Enter Video URLs (one per line):</label>
468
  <textarea
469
  id="urlInput"
470
+ placeholder="https://www.douyin.com/video/7123456789012345678&#10;https://v.douyin.com/ABCDEFG123456/&#10;https://www.douyin.com/user/987654321?modal_id=7123456789012345678"
471
  ></textarea>
472
  <div class="button-group">
473
  <button onclick="processUrls()">Process URLs</button>
 
479
 
480
  <div class="loading" id="loading">
481
  <div class="spinner"></div>
482
+ <p>Extracting links...</p>
483
  </div>
484
 
485
  <div class="message error-message" id="errorMessage"></div>
 
490
  <section class="results-section" id="resultsSection">
491
  <div class="results-header">
492
  <h2 class="results-title">
493
+ Download Links
494
  <span class="status-indicator success"></span>
495
  </h2>
496
  <button class="copy-all-btn" onclick="copyAllUrls()">Copy All</button>
 
827
  if (successCount > 0) {
828
  document.getElementById('successNotice').classList.add('show');
829
  document.getElementById('successNotice').style.display = 'flex';
830
+ showInfo(`Successfully extracted ${successCount} link(s) out of ${urls.length} URLs`);
831
  }
832
  }
833
 
 
838
  results.forEach((result, index) => {
839
  const li = document.createElement('li');
840
  li.className = 'url-item';
841
+ li.style.animationDelay = `${index * 0.05}s}`;
842
 
843
  const isFallback = result.isFallback;
844
  const isV3 = !isFallback && (result.url.includes('v3') || result.quality === 'V3');
 
857
 
858
  let sourceInfo = '';
859
  if (result.source) {
860
+ sourceInfo = `<small style="color: var(--text-tertiary); font-size: 0.7rem;">[${result.source}]</small>`;
861
  }
862
 
863
  const urlContentClass = isV3 ? 'url-content v3-link' : 'url-content';
 
897
  const button = document.querySelector('.copy-all-btn');
898
  const originalText = button.textContent;
899
  button.textContent = '✓ Copied All!';
900
+ button.style.background = '#2D5A2D';
901
  button.style.color = 'white';
902
  setTimeout(() => {
903
  button.textContent = originalText;
 
962
  }
963
  });
964
 
965
+ console.log('Video Downloader Ready');
966
  </script>
967
  </body>
968