diff --git a/server.js b/server.js index 84f52de..edc7eb0 100644 --- a/server.js +++ b/server.js @@ -480,21 +480,83 @@ app.get('/api/hls/playlist.m3u8', async (req, res) => { const auth = extractS3Credentials(req); const s3Client = createS3Client(auth); let totalBytes = 0; + const progressKey = getProgressKey(key); + const streamSessionId = createStreamSessionId(); + let downloadedBytes = 0; if (!fs.existsSync(tmpInputPath)) { try { const command = new GetObjectCommand({ Bucket: bucket, Key: key }); const response = await s3Client.send(command); totalBytes = response.ContentLength; + const s3Stream = response.Body; + + progressMap[progressKey] = { + status: 'downloading', + percent: 0, + downloadedBytes: 0, + totalBytes, + streamSessionId, + details: 'Downloading full source before streaming...', + mp4Url: null + }; + broadcastWs(progressKey, { type: 'progress', key, progress: progressMap[progressKey] }); + await new Promise((resolve, reject) => { const writeStream = fs.createWriteStream(tmpInputPath); - response.Body.pipe(writeStream); + + s3Stream.on('data', (chunk) => { + downloadedBytes += chunk.length; + const percent = totalBytes ? Math.min(100, Math.round((downloadedBytes / totalBytes) * 100)) : 0; + + const downloadState = { + status: 'downloading', + percent, + downloadedBytes, + totalBytes, + streamSessionId, + details: totalBytes ? `Downloading source ${percent}%` : 'Downloading source...', + mp4Url: null + }; + progressMap[progressKey] = downloadState; + broadcastWs(progressKey, { type: 'progress', key, progress: downloadState }); + }); + + s3Stream.on('error', reject); writeStream.on('error', reject); writeStream.on('finish', resolve); + s3Stream.pipe(writeStream); }); + + progressMap[progressKey] = { + status: 'downloaded', + percent: 100, + downloadedBytes, + totalBytes, + streamSessionId, + details: 'Source download complete, parsing for HLS...', + mp4Url: null + }; + broadcastWs(progressKey, { type: 'progress', key, progress: progressMap[progressKey] }); + } catch(err) { + console.error('S3 Download Failed:', err); return res.status(500).send('S3 Download Failed'); } + } else { + const stats = fs.statSync(tmpInputPath); + totalBytes = stats.size; + downloadedBytes = totalBytes; + progressMap[progressKey] = { + status: 'downloaded', + percent: 100, + downloadedBytes, + totalBytes, + streamSessionId, + details: 'Source already downloaded locally, parsing for HLS...', + mp4Url: null + }; + broadcastWs(progressKey, { type: 'progress', key, progress: progressMap[progressKey] }); } let duration = 0;