diff --git a/public/index.html b/public/index.html index 4149c3d..6c05f65 100644 --- a/public/index.html +++ b/public/index.html @@ -26,10 +26,14 @@ Available Videos - + + - + + + + 编码方式: diff --git a/public/js/main.js b/public/js/main.js index 75b2941..4b9f4df 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -2,6 +2,7 @@ document.addEventListener('DOMContentLoaded', () => { const videoListEl = document.getElementById('video-list'); const loadingSpinner = document.getElementById('loading-spinner'); const refreshBtn = document.getElementById('refresh-btn'); + const resetCacheBtn = document.getElementById('reset-cache-btn'); const codecSelect = document.getElementById('codec-select'); const encoderSelect = document.getElementById('encoder-select'); const playerOverlay = document.getElementById('player-overlay'); @@ -89,6 +90,45 @@ document.addEventListener('DOMContentLoaded', () => { progressFill.style.width = '0%'; }; + const resetCache = async () => { + if (!resetCacheBtn) return; + resetCacheBtn.disabled = true; + resetCacheBtn.title = 'Resetting cache...'; + + stopPolling(); + selectedKey = null; + currentVideoKey = null; + subscribedKey = null; + if (transcodeBtn) { + transcodeBtn.classList.add('hidden'); + } + if (playBtn) { + playBtn.classList.add('hidden'); + } + if (playerOverlay) { + playerOverlay.classList.remove('hidden'); + } + if (nowPlaying) { + nowPlaying.classList.add('hidden'); + } + resetProgress(); + + try { + const res = await fetch('/api/reset-cache', { method: 'POST' }); + if (!res.ok) { + const data = await res.json().catch(() => ({})); + throw new Error(data.error || 'Reset failed'); + } + await fetchVideos(); + } catch (err) { + console.error('Reset cache failed:', err); + alert(`Reset cache failed: ${err.message}`); + } finally { + resetCacheBtn.disabled = false; + resetCacheBtn.title = 'Reset Download Cache'; + } + }; + if (transcodeBtn) { transcodeBtn.addEventListener('click', () => { startTranscode(); diff --git a/server.js b/server.js index a57a641..65c30f2 100644 --- a/server.js +++ b/server.js @@ -113,6 +113,20 @@ wss.on('connection', (ws) => { ws.on('close', () => removeWsClient(ws)); }); +const clearMp4Cache = () => { + const mp4Dir = path.join(__dirname, 'public', 'mp4'); + if (!fs.existsSync(mp4Dir)) return; + try { + fs.rmSync(mp4Dir, { recursive: true, force: true }); + } catch (err) { + if (typeof fs.rmdirSync === 'function') { + fs.rmdirSync(mp4Dir, { recursive: true }); + } else { + throw err; + } + } +}; + // Endpoint to list videos in the bucket app.get('/api/videos', async (req, res) => { try { @@ -154,6 +168,17 @@ app.get('/api/videos', async (req, res) => { } }); +app.post('/api/reset-cache', (req, res) => { + try { + clearMp4Cache(); + Object.keys(progressMap).forEach((key) => delete progressMap[key]); + res.json({ message: 'Cache reset' }); + } catch (error) { + console.error('Error resetting cache:', error); + res.status(500).json({ error: 'Failed to reset cache', detail: error.message }); + } +}); + // Endpoint to transcode S3 video streaming to MP4 app.post('/api/transcode', async (req, res) => { const { key, codec, encoder } = req.body;