sk16er commited on
Commit
03fba47
·
verified ·
1 Parent(s): 3cecf69

Update static/index.html

Browse files
Files changed (1) hide show
  1. static/index.html +230 -0
static/index.html CHANGED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>YouTube Transcriber</title>
7
+ <!-- Tailwind CSS CDN -->
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <!-- Google Fonts: Poppins -->
10
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
11
+ <!-- Font Awesome for Icons -->
12
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
13
+ <style>
14
+ body {
15
+ font-family: 'Poppins', sans-serif;
16
+ background: linear-gradient(135deg, #f5f5f5, #e0e0e0);
17
+ position: relative;
18
+ overflow: hidden;
19
+ }
20
+ .card {
21
+ position: relative;
22
+ overflow: hidden;
23
+ backdrop-filter: blur(10px);
24
+ background: rgba(255, 255, 255, 0.95);
25
+ border: 1px solid rgba(255, 0, 0, 0.2);
26
+ }
27
+ .card::before {
28
+ content: '';
29
+ position: absolute;
30
+ bottom: -20px;
31
+ left: 0;
32
+ right: 0;
33
+ height: 20px;
34
+ background: linear-gradient(180deg, transparent, rgba(255, 0, 0, 0.4));
35
+ filter: blur(12px);
36
+ z-index: -1;
37
+ }
38
+ .card::after {
39
+ content: '';
40
+ position: absolute;
41
+ top: 0;
42
+ left: 0;
43
+ right: 0;
44
+ bottom: 0;
45
+ box-shadow: 0 0 25px rgba(255, 0, 0, 0.6), inset 0 0 10px rgba(255, 255, 255, 0.5);
46
+ z-index: -1;
47
+ }
48
+ @keyframes fadeIn {
49
+ from { opacity: 0; transform: translateY(10px); }
50
+ to { opacity: 1; transform: translateY(0); }
51
+ }
52
+ @keyframes pulseGlow {
53
+ 0% { box-shadow: 0 0 10px rgba(255, 0, 0, 0.3); }
54
+ 50% { box-shadow: 0 0 20px rgba(255, 0, 0, 0.7); }
55
+ 100% { box-shadow: 0 0 10px rgba(255, 0, 0, 0.3); }
56
+ }
57
+ @keyframes scalePop {
58
+ from { transform: scale(0.8); opacity: 0; }
59
+ to { transform: scale(1); opacity: 1; }
60
+ }
61
+ @keyframes logoGlow {
62
+ 0% { filter: drop-shadow(0 0 5px rgba(255, 0, 0, 0.3)); }
63
+ 50% { filter: drop-shadow(0 0 15px rgba(255, 0, 0, 0.8)); }
64
+ 100% { filter: drop-shadow(0 0 5px rgba(255, 0, 0, 0.3)); }
65
+ }
66
+ .fade-in {
67
+ animation: fadeIn 0.6s ease-out;
68
+ }
69
+ .pulse-glow {
70
+ animation: pulseGlow 2s infinite;
71
+ }
72
+ .pop-in {
73
+ animation: scalePop 0.3s ease-out;
74
+ }
75
+ .logo-glow {
76
+ animation: logoGlow 1.5s infinite;
77
+ }
78
+ @keyframes spin {
79
+ to { transform: rotate(360deg); }
80
+ }
81
+ .spinner {
82
+ border: 4px solid rgba(255, 0, 0, 0.2);
83
+ border-left-color: #ff0000;
84
+ border-radius: 50%;
85
+ width: 28px;
86
+ height: 28px;
87
+ animation: spin 0.8s linear infinite;
88
+ display: none;
89
+ }
90
+ .btn-red {
91
+ background: #ff0000;
92
+ transition: all 0.3s ease;
93
+ }
94
+ .btn-red:hover {
95
+ background: #cc0000;
96
+ transform: scale(1.05);
97
+ box-shadow: 0 4px 12px rgba(255, 0, 0, 0.5);
98
+ }
99
+ .typewriter {
100
+ overflow: hidden;
101
+ white-space: pre-wrap;
102
+ animation: typing 2s steps(40, end);
103
+ }
104
+ @keyframes typing {
105
+ from { width: 0; }
106
+ to { width: 100%; }
107
+ }
108
+ .youtube-logo {
109
+ width: 40px;
110
+ height: 40px;
111
+ }
112
+ </style>
113
+ </head>
114
+ <body class="min-h-screen flex items-center justify-center p-4">
115
+ <div class="max-w-4xl w-full card rounded-xl p-10">
116
+ <h1 class="text-5xl font-bold text-center text-red-600 mb-8 flex items-center justify-center gap-3">
117
+ <img src="https://www.youtube.com/favicon.ico" alt="YouTube Logo" class="youtube-logo logo-glow">
118
+ YouTube Transcriber
119
+ </h1>
120
+
121
+ <!-- Input and Buttons -->
122
+ <div class="flex flex-col sm:flex-row gap-4 mb-8">
123
+ <div class="relative flex-1">
124
+ <input
125
+ type="text"
126
+ id="youtubeUrl"
127
+ placeholder="Enter YouTube URL"
128
+ class="w-full p-4 pr-12 border border-red-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500 bg-white text-gray-800 text-lg"
129
+ >
130
+ <button
131
+ onclick="pasteUrl()"
132
+ class="absolute right-3 top-1/2 -translate-y-1/2 text-red-600 hover:text-red-800"
133
+ title="Paste URL"
134
+ >
135
+ <i class="fas fa-paste text-xl"></i>
136
+ </button>
137
+ </div>
138
+ <button
139
+ onclick="transcribe()"
140
+ class="btn-red text-white px-8 py-4 rounded-lg font-semibold text-lg"
141
+ >
142
+ Transcribe
143
+ </button>
144
+ </div>
145
+
146
+ <!-- Error Message -->
147
+ <div id="error" class="hidden bg-red-100 text-red-800 p-5 rounded-lg mb-8 font-medium text-lg"></div>
148
+
149
+ <!-- Transcription Area -->
150
+ <div class="relative">
151
+ <div id="spinner" class="spinner absolute top-4 right-4"></div>
152
+ <div
153
+ id="transcription"
154
+ class="bg-white p-6 rounded-lg border border-red-200 min-h-[200px] whitespace-pre-wrap text-gray-800 shadow-inner text-lg"
155
+ >
156
+ Transcription will appear here...
157
+ </div>
158
+ </div>
159
+
160
+ <!-- Copy Button -->
161
+ <button
162
+ id="copyButton"
163
+ class="hidden mt-8 btn-red text-white px-6 py-3 rounded-lg font-semibold w-full sm:w-auto pop-in text-lg"
164
+ onclick="copyTranscription()"
165
+ >
166
+ <i class="fas fa-copy mr-2"></i> Copy Transcription
167
+ </button>
168
+ </div>
169
+
170
+ <script>
171
+ async function transcribe() {
172
+ const url = document.getElementById('youtubeUrl').value;
173
+ const transcriptionDiv = document.getElementById('transcription');
174
+ const errorDiv = document.getElementById('error');
175
+ const spinner = document.getElementById('spinner');
176
+ const copyButton = document.getElementById('copyButton');
177
+
178
+ transcriptionDiv.textContent = 'Processing...';
179
+ transcriptionDiv.classList.remove('typewriter', 'pulse-glow', 'fade-in');
180
+ errorDiv.classList.add('hidden');
181
+ spinner.style.display = 'block';
182
+ copyButton.classList.add('hidden');
183
+
184
+ try {
185
+ const response = await fetch('http://127.0.0.1:8000/transcribe', {
186
+ method: 'POST',
187
+ headers: {
188
+ 'Content-Type': 'application/json',
189
+ },
190
+ body: JSON.stringify({ url: url }),
191
+ });
192
+
193
+ const data = await response.json();
194
+
195
+ if (response.ok) {
196
+ transcriptionDiv.textContent = data.transcription;
197
+ transcriptionDiv.classList.add('typewriter', 'pulse-glow', 'fade-in');
198
+ copyButton.classList.remove('hidden');
199
+ } else {
200
+ throw new Error(data.detail || 'Failed to transcribe');
201
+ }
202
+ } catch (error) {
203
+ errorDiv.textContent = `Error: ${error.message}`;
204
+ errorDiv.classList.remove('hidden');
205
+ transcriptionDiv.textContent = 'Transcription failed.';
206
+ } finally {
207
+ spinner.style.display = 'none';
208
+ }
209
+ }
210
+
211
+ async function pasteUrl() {
212
+ try {
213
+ const url = await navigator.clipboard.readText();
214
+ document.getElementById('youtubeUrl').value = url;
215
+ } catch (error) {
216
+ alert('Failed to paste URL.');
217
+ }
218
+ }
219
+
220
+ function copyTranscription() {
221
+ const transcription = document.getElementById('transcription').textContent;
222
+ navigator.clipboard.writeText(transcription).then(() => {
223
+ alert('Transcription copied to clipboard!');
224
+ }).catch(() => {
225
+ alert('Failed to copy transcription.');
226
+ });
227
+ }
228
+ </script>
229
+ </body>
230
+ </html>