Brunwo commited on
Commit
0e9d836
1 Parent(s): f4ce0ef

add caching and history playback

Browse files
Files changed (3) hide show
  1. index.html +7 -0
  2. script.js +138 -26
  3. styles.css +74 -0
index.html CHANGED
@@ -48,6 +48,13 @@
48
  </div>
49
  <div id="loadingIndicator" style="display: none;">Loading audio...</div>
50
 
 
 
 
 
 
 
 
51
  <script type="module" src="script.js"></script>
52
  <!-- <script src="/script.js"></script> -->
53
  </body>
 
48
  </div>
49
  <div id="loadingIndicator" style="display: none;">Loading audio...</div>
50
 
51
+ <!-- Add history section -->
52
+ <div id="historySection">
53
+ <h2>History</h2>
54
+ <ul id="historyList"></ul>
55
+ <button id="clearHistory">Clear History</button>
56
+ </div>
57
+
58
  <script type="module" src="script.js"></script>
59
  <!-- <script src="/script.js"></script> -->
60
  </body>
script.js CHANGED
@@ -1,6 +1,10 @@
1
  import { Client } from "@gradio/client";
2
 
3
- document.addEventListener("DOMContentLoaded", function() {
 
 
 
 
4
  const audioPlayer = document.getElementById('player');
5
  const playButton = document.getElementById('playButton');
6
  const skipBackwardButton = document.getElementById('skipBackward');
@@ -91,6 +95,15 @@ document.addEventListener("DOMContentLoaded", function() {
91
 
92
  saveSettingsBtn.onclick = saveSettings;
93
 
 
 
 
 
 
 
 
 
 
94
  // Function to fetch MP3 from API endpoint when a link is shared
95
  async function fetchMp3(link) {
96
  console.log('Starting fetchMp3 function with link:', link);
@@ -104,6 +117,13 @@ document.addEventListener("DOMContentLoaded", function() {
104
  if (transcriptionContainer) transcriptionContainer.style.display = 'none';
105
 
106
  try {
 
 
 
 
 
 
 
107
  const apiKey = localStorage.getItem('openaiApiKey');
108
  const apiServer = localStorage.getItem('apiServer');
109
  console.log('Retrieved API key and server from localStorage');
@@ -166,31 +186,16 @@ document.addEventListener("DOMContentLoaded", function() {
166
  throw new Error(`Invalid audio file URL received: ${audioFileUrl}`);
167
  }
168
 
169
- // Set the audio player source
170
- if (audioPlayer) {
171
- audioPlayer.src = audioFileUrl;
172
- } else {
173
- throw new Error('Audio player element not found');
174
- }
 
 
175
 
176
- // Show play button
177
- if (playButton) {
178
- playButton.style.display = 'block';
179
- playButton.onclick = () => audioPlayer.play();
180
- } else {
181
- console.warn('Play button not found, audio controls will be used instead');
182
- }
183
-
184
- // Display the transcription
185
- if (transcriptionElement && transcriptionContainer) {
186
- const transcription = result.data[1];
187
- transcriptionElement.textContent = transcription;
188
- transcriptionContainer.style.display = 'block';
189
- } else {
190
- console.warn('Transcription elements not found');
191
- }
192
-
193
- console.log('Audio ready for playback and transcription displayed');
194
 
195
  } catch (error) {
196
  console.error('Error in fetchMp3:', error);
@@ -207,6 +212,113 @@ document.addEventListener("DOMContentLoaded", function() {
207
  }
208
  }
209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  // Get the link from the shared URL
211
  const queryParams = new URLSearchParams(window.location.search);
212
  const sharedLink = queryParams.get('url');
@@ -251,4 +363,4 @@ if ('mediaSession' in navigator) {
251
  navigator.mediaSession.setActionHandler('seekforward', function() {
252
  audioPlayer.currentTime = Math.min(audioPlayer.currentTime + 10, audioPlayer.duration);
253
  });
254
- }
 
1
  import { Client } from "@gradio/client";
2
 
3
+ // Add these variables at the top of the file
4
+ let audioCache = {};
5
+ let currentTrack = null;
6
+
7
+ document.addEventListener("DOMContentLoaded", async function() {
8
  const audioPlayer = document.getElementById('player');
9
  const playButton = document.getElementById('playButton');
10
  const skipBackwardButton = document.getElementById('skipBackward');
 
95
 
96
  saveSettingsBtn.onclick = saveSettings;
97
 
98
+ const historyList = document.getElementById('historyList');
99
+ const clearHistoryBtn = document.getElementById('clearHistory');
100
+
101
+ // Load audio cache from localStorage and Cache API
102
+ await loadAudioCache();
103
+
104
+ // Update history list
105
+ updateHistoryList();
106
+
107
  // Function to fetch MP3 from API endpoint when a link is shared
108
  async function fetchMp3(link) {
109
  console.log('Starting fetchMp3 function with link:', link);
 
117
  if (transcriptionContainer) transcriptionContainer.style.display = 'none';
118
 
119
  try {
120
+ // Check if the link is already in the cache
121
+ if (audioCache[link]) {
122
+ console.log('Loading audio from cache');
123
+ await loadAudioFromCache(link);
124
+ return;
125
+ }
126
+
127
  const apiKey = localStorage.getItem('openaiApiKey');
128
  const apiServer = localStorage.getItem('apiServer');
129
  console.log('Retrieved API key and server from localStorage');
 
186
  throw new Error(`Invalid audio file URL received: ${audioFileUrl}`);
187
  }
188
 
189
+ // After successful API call, add to cache
190
+ audioCache[link] = {
191
+ audioUrl: audioFileUrl,
192
+ transcription: result.data[1],
193
+ lastPosition: 0
194
+ };
195
+ await saveAudioCache(link, audioFileUrl);
196
+ updateHistoryList();
197
 
198
+ await loadAudioFromCache(link);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
  } catch (error) {
201
  console.error('Error in fetchMp3:', error);
 
212
  }
213
  }
214
 
215
+ async function loadAudioFromCache(link) {
216
+ const cachedAudio = audioCache[link];
217
+ if (!cachedAudio) return;
218
+
219
+ const audioPlayer = document.getElementById('player');
220
+ const playButton = document.getElementById('playButton');
221
+ const transcriptionContainer = document.getElementById('transcriptionContainer');
222
+ const transcriptionElement = document.getElementById('transcription');
223
+
224
+ // Fetch the audio file from the Cache API
225
+ const cache = await caches.open('audio-cache');
226
+ const response = await cache.match(cachedAudio.audioUrl);
227
+ if (response) {
228
+ const blob = await response.blob();
229
+ audioPlayer.src = URL.createObjectURL(blob);
230
+ } else {
231
+ audioPlayer.src = cachedAudio.audioUrl;
232
+ }
233
+
234
+ audioPlayer.currentTime = cachedAudio.lastPosition;
235
+ currentTrack = link;
236
+
237
+ if (playButton) {
238
+ playButton.style.display = 'block';
239
+ playButton.onclick = () => audioPlayer.play();
240
+ }
241
+
242
+ if (transcriptionElement && transcriptionContainer) {
243
+ transcriptionElement.textContent = cachedAudio.transcription;
244
+ transcriptionContainer.style.display = 'block';
245
+ }
246
+
247
+ console.log('Audio loaded from cache and ready for playback');
248
+ }
249
+
250
+ async function saveAudioCache(link, audioUrl) {
251
+ // Save metadata to localStorage
252
+ localStorage.setItem('audioCache', JSON.stringify(audioCache));
253
+
254
+ // Save audio file to Cache API
255
+ const cache = await caches.open('audio-cache');
256
+ await cache.add(audioUrl);
257
+ }
258
+
259
+ async function loadAudioCache() {
260
+ const savedCache = localStorage.getItem('audioCache');
261
+ if (savedCache) {
262
+ audioCache = JSON.parse(savedCache);
263
+ }
264
+
265
+ // Verify that all cached audio files are still in the Cache API
266
+ const cache = await caches.open('audio-cache');
267
+ for (const link in audioCache) {
268
+ const response = await cache.match(audioCache[link].audioUrl);
269
+ if (!response) {
270
+ console.log(`Audio file for ${link} not found in cache, removing entry`);
271
+ delete audioCache[link];
272
+ }
273
+ }
274
+
275
+ // Save the cleaned-up cache back to localStorage
276
+ localStorage.setItem('audioCache', JSON.stringify(audioCache));
277
+ }
278
+
279
+ async function updateHistoryList() {
280
+ historyList.innerHTML = '';
281
+ Object.keys(audioCache).forEach(link => {
282
+ const li = document.createElement('li');
283
+ const playBtn = document.createElement('button');
284
+ playBtn.textContent = 'Play';
285
+ playBtn.onclick = () => loadAudioFromCache(link);
286
+ const removeBtn = document.createElement('button');
287
+ removeBtn.textContent = 'Remove';
288
+ removeBtn.onclick = () => removeFromCache(link);
289
+ li.appendChild(document.createTextNode(link + ' '));
290
+ li.appendChild(playBtn);
291
+ li.appendChild(removeBtn);
292
+ historyList.appendChild(li);
293
+ });
294
+ }
295
+
296
+ async function removeFromCache(link) {
297
+ const cache = await caches.open('audio-cache');
298
+ await cache.delete(audioCache[link].audioUrl);
299
+ delete audioCache[link];
300
+ localStorage.setItem('audioCache', JSON.stringify(audioCache));
301
+ updateHistoryList();
302
+ }
303
+
304
+ clearHistoryBtn.onclick = async function() {
305
+ const cache = await caches.open('audio-cache');
306
+ for (const link in audioCache) {
307
+ await cache.delete(audioCache[link].audioUrl);
308
+ }
309
+ audioCache = {};
310
+ localStorage.setItem('audioCache', JSON.stringify(audioCache));
311
+ updateHistoryList();
312
+ };
313
+
314
+ // Save current position every 5 seconds
315
+ setInterval(() => {
316
+ if (currentTrack && audioPlayer.currentTime > 0) {
317
+ audioCache[currentTrack].lastPosition = audioPlayer.currentTime;
318
+ localStorage.setItem('audioCache', JSON.stringify(audioCache));
319
+ }
320
+ }, 5000);
321
+
322
  // Get the link from the shared URL
323
  const queryParams = new URLSearchParams(window.location.search);
324
  const sharedLink = queryParams.get('url');
 
363
  navigator.mediaSession.setActionHandler('seekforward', function() {
364
  audioPlayer.currentTime = Math.min(audioPlayer.currentTime + 10, audioPlayer.duration);
365
  });
366
+ }
styles.css CHANGED
@@ -91,3 +91,77 @@ body {
91
  padding: 5px;
92
  margin: 10px 0;
93
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  padding: 5px;
92
  margin: 10px 0;
93
  }
94
+
95
+ /* ... existing styles ... */
96
+
97
+ #audioControls {
98
+ width: 100%;
99
+ max-width: 500px;
100
+ margin: 20px auto;
101
+ }
102
+
103
+ #progressBarContainer {
104
+ width: 100%;
105
+ height: 10px;
106
+ background-color: #ddd;
107
+ cursor: pointer;
108
+ margin-bottom: 10px;
109
+ }
110
+
111
+ #progressBar {
112
+ height: 100%;
113
+ background-color: #4CAF50;
114
+ width: 0;
115
+ }
116
+
117
+ #timeDisplay {
118
+ text-align: right;
119
+ margin-bottom: 10px;
120
+ }
121
+
122
+ #controlButtons {
123
+ display: flex;
124
+ justify-content: space-between;
125
+ margin-bottom: 10px;
126
+ }
127
+
128
+ #controlButtons button {
129
+ padding: 5px 10px;
130
+ cursor: pointer;
131
+ }
132
+
133
+ #volumeControl {
134
+ width: 100%;
135
+ }
136
+
137
+ #volumeSlider {
138
+ width: 100%;
139
+ }
140
+
141
+ /* ... (existing styles) ... */
142
+
143
+ #historySection {
144
+ margin-top: 20px;
145
+ text-align: left;
146
+ }
147
+
148
+ #historyList {
149
+ list-style-type: none;
150
+ padding: 0;
151
+ }
152
+
153
+ #historyList li {
154
+ margin-bottom: 10px;
155
+ }
156
+
157
+ #historyList button {
158
+ margin-left: 10px;
159
+ padding: 2px 5px;
160
+ cursor: pointer;
161
+ }
162
+
163
+ #clearHistory {
164
+ margin-top: 10px;
165
+ padding: 5px 10px;
166
+ cursor: pointer;
167
+ }