openfree commited on
Commit
827b52d
·
verified ·
1 Parent(s): f2b8c2a

Upload index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +308 -19
index.html CHANGED
@@ -1,19 +1,308 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>English Practice with TTS</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
13
+ }
14
+
15
+ body {
16
+ min-height: 100vh;
17
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
18
+ display: flex;
19
+ justify-content: center;
20
+ align-items: center;
21
+ padding: 20px;
22
+ }
23
+
24
+ .container {
25
+ background: white;
26
+ padding: 30px;
27
+ border-radius: 15px;
28
+ box-shadow: 0 10px 20px rgba(0,0,0,0.1);
29
+ width: 90%;
30
+ max-width: 600px;
31
+ }
32
+
33
+ .title {
34
+ text-align: center;
35
+ color: #2c3e50;
36
+ margin-bottom: 30px;
37
+ }
38
+
39
+ .input-area {
40
+ margin-bottom: 20px;
41
+ }
42
+
43
+ textarea {
44
+ width: 100%;
45
+ padding: 15px;
46
+ border: 2px solid #e0e0e0;
47
+ border-radius: 8px;
48
+ height: 100px;
49
+ resize: none;
50
+ font-size: 16px;
51
+ transition: border-color 0.3s ease;
52
+ }
53
+
54
+ textarea:focus {
55
+ outline: none;
56
+ border-color: #3498db;
57
+ }
58
+
59
+ .btn {
60
+ background: #3498db;
61
+ color: white;
62
+ border: none;
63
+ padding: 12px 25px;
64
+ border-radius: 8px;
65
+ cursor: pointer;
66
+ font-size: 16px;
67
+ transition: background 0.3s ease;
68
+ width: 100%;
69
+ margin-bottom: 15px;
70
+ }
71
+
72
+ .btn:hover {
73
+ background: #2980b9;
74
+ }
75
+
76
+ .practice-area {
77
+ margin-top: 30px;
78
+ display: none;
79
+ }
80
+
81
+ .sentence-display {
82
+ font-size: 20px;
83
+ color: #2c3e50;
84
+ margin-bottom: 20px;
85
+ padding: 15px;
86
+ background: #f8f9fa;
87
+ border-radius: 8px;
88
+ text-align: center;
89
+ cursor: pointer;
90
+ transition: background-color 0.3s ease;
91
+ }
92
+
93
+ .sentence-display:hover {
94
+ background: #e9ecef;
95
+ }
96
+
97
+ .controls {
98
+ display: flex;
99
+ gap: 10px;
100
+ margin-bottom: 20px;
101
+ flex-wrap: wrap;
102
+ }
103
+
104
+ .controls button {
105
+ flex: 1;
106
+ min-width: 120px;
107
+ }
108
+
109
+ .stats {
110
+ text-align: center;
111
+ color: #7f8c8d;
112
+ font-size: 14px;
113
+ margin-top: 15px;
114
+ }
115
+
116
+ .voice-controls {
117
+ margin: 15px 0;
118
+ display: flex;
119
+ gap: 10px;
120
+ align-items: center;
121
+ }
122
+
123
+ select {
124
+ padding: 8px;
125
+ border-radius: 5px;
126
+ border: 1px solid #ddd;
127
+ flex: 1;
128
+ }
129
+
130
+ .speed-control {
131
+ display: flex;
132
+ align-items: center;
133
+ gap: 10px;
134
+ margin: 10px 0;
135
+ }
136
+
137
+ .speed-control input {
138
+ flex: 1;
139
+ }
140
+
141
+ @media (max-width: 480px) {
142
+ .container {
143
+ padding: 20px;
144
+ }
145
+
146
+ .controls {
147
+ flex-direction: column;
148
+ }
149
+ }
150
+ </style>
151
+ </head>
152
+ <body>
153
+ <div class="container">
154
+ <h1 class="title">English Practice with TTS</h1>
155
+
156
+ <div class="input-area">
157
+ <textarea id="sentenceInput" placeholder="Enter your English sentences here (one per line)"></textarea>
158
+ <button class="btn" onclick="startPractice()">Start Practice</button>
159
+ </div>
160
+
161
+ <div class="practice-area" id="practiceArea">
162
+ <div class="voice-controls">
163
+ <select id="voiceSelect"></select>
164
+ </div>
165
+ <div class="speed-control">
166
+ <span>Speed:</span>
167
+ <input type="range" id="speedControl" min="0.5" max="2" step="0.1" value="1">
168
+ <span id="speedValue">1.0x</span>
169
+ </div>
170
+ <div class="sentence-display" id="sentenceDisplay" onclick="speakCurrentSentence()"></div>
171
+ <div class="controls">
172
+ <button class="btn" onclick="prevSentence()">Previous</button>
173
+ <button class="btn" onclick="toggleAutoPlay()">Auto Play</button>
174
+ <button class="btn" onclick="nextSentence()">Next</button>
175
+ </div>
176
+ <div class="stats" id="stats"></div>
177
+ </div>
178
+ </div>
179
+
180
+ <script>
181
+ let sentences = [];
182
+ let currentIndex = 0;
183
+ let autoPlayInterval;
184
+ let isAutoPlaying = false;
185
+ let speechSynth = window.speechSynthesis;
186
+ let voices = [];
187
+
188
+ // Initialize voice selection
189
+ function initVoices() {
190
+ voices = speechSynth.getVoices();
191
+ const voiceSelect = document.getElementById('voiceSelect');
192
+ voiceSelect.innerHTML = '';
193
+
194
+ voices.forEach((voice, index) => {
195
+ if (voice.lang.includes('en')) {
196
+ const option = document.createElement('option');
197
+ option.value = index;
198
+ option.textContent = `${voice.name} (${voice.lang})`;
199
+ voiceSelect.appendChild(option);
200
+ }
201
+ });
202
+ }
203
+
204
+ speechSynth.onvoiceschanged = initVoices;
205
+
206
+ // Speed control
207
+ document.getElementById('speedControl').addEventListener('input', function(e) {
208
+ document.getElementById('speedValue').textContent = `${e.target.value}x`;
209
+ });
210
+
211
+ function speakText(text) {
212
+ if (speechSynth.speaking) {
213
+ speechSynth.cancel();
214
+ }
215
+
216
+ const utterance = new SpeechSynthesisUtterance(text);
217
+ const voiceSelect = document.getElementById('voiceSelect');
218
+ const speedControl = document.getElementById('speedControl');
219
+
220
+ utterance.voice = voices[voiceSelect.value];
221
+ utterance.rate = speedControl.value;
222
+ utterance.pitch = 1;
223
+
224
+ speechSynth.speak(utterance);
225
+ }
226
+
227
+ function speakCurrentSentence() {
228
+ speakText(sentences[currentIndex]);
229
+ }
230
+
231
+ function startPractice() {
232
+ const input = document.getElementById('sentenceInput').value.trim();
233
+ if (!input) {
234
+ alert('Please enter at least one sentence');
235
+ return;
236
+ }
237
+
238
+ sentences = input.split('\n').filter(sentence => sentence.trim());
239
+ if (sentences.length === 0) {
240
+ alert('Please enter valid sentences');
241
+ return;
242
+ }
243
+
244
+ currentIndex = 0;
245
+ document.getElementById('practiceArea').style.display = 'block';
246
+ updateDisplay();
247
+ speakCurrentSentence();
248
+ }
249
+
250
+ function updateDisplay() {
251
+ document.getElementById('sentenceDisplay').textContent = sentences[currentIndex];
252
+ document.getElementById('stats').textContent =
253
+ `Sentence ${currentIndex + 1} of ${sentences.length}`;
254
+ }
255
+
256
+ function nextSentence() {
257
+ if (currentIndex < sentences.length - 1) {
258
+ currentIndex++;
259
+ updateDisplay();
260
+ speakCurrentSentence();
261
+ }
262
+ }
263
+
264
+ function prevSentence() {
265
+ if (currentIndex > 0) {
266
+ currentIndex--;
267
+ updateDisplay();
268
+ speakCurrentSentence();
269
+ }
270
+ }
271
+
272
+ function toggleAutoPlay() {
273
+ if (isAutoPlaying) {
274
+ clearInterval(autoPlayInterval);
275
+ isAutoPlaying = false;
276
+ } else {
277
+ autoPlayInterval = setInterval(() => {
278
+ if (currentIndex < sentences.length - 1) {
279
+ nextSentence();
280
+ } else {
281
+ currentIndex = 0;
282
+ updateDisplay();
283
+ speakCurrentSentence();
284
+ }
285
+ }, 5000); // 5 seconds interval
286
+ isAutoPlaying = true;
287
+ speakCurrentSentence();
288
+ }
289
+ }
290
+
291
+ document.addEventListener('keydown', (e) => {
292
+ if (e.key === 'ArrowRight') {
293
+ nextSentence();
294
+ } else if (e.key === 'ArrowLeft') {
295
+ prevSentence();
296
+ } else if (e.key === ' ') {
297
+ e.preventDefault();
298
+ toggleAutoPlay();
299
+ }
300
+ });
301
+
302
+ // Initialize voices if they're already loaded
303
+ if (speechSynth.getVoices().length > 0) {
304
+ initVoices();
305
+ }
306
+ </script>
307
+ </body>
308
+ </html>