优化页面布局,修复故障视频拉动进度条的故障
This commit is contained in:
97
server.js
97
server.js
@@ -7,7 +7,7 @@ const path = require('path');
|
||||
const http = require('http');
|
||||
const WebSocket = require('ws');
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const { S3Client, ListBucketsCommand, ListObjectsV2Command, GetObjectCommand } = require('@aws-sdk/client-s3');
|
||||
const { S3Client, ListBucketsCommand, ListObjectsV2Command, GetObjectCommand, HeadObjectCommand } = require('@aws-sdk/client-s3');
|
||||
const crypto = require('crypto');
|
||||
const Redis = require('ioredis');
|
||||
|
||||
@@ -396,16 +396,36 @@ const ensureS3Downloaded = async (s3Client, bucket, key, tmpInputPath, progressK
|
||||
}
|
||||
}
|
||||
|
||||
let shouldDownload = true;
|
||||
let s3Metadata = null;
|
||||
|
||||
if (fs.existsSync(tmpInputPath)) {
|
||||
const stats = fs.statSync(tmpInputPath);
|
||||
const totalBytes = stats.size;
|
||||
const localSize = stats.size;
|
||||
|
||||
try {
|
||||
const headCommand = new HeadObjectCommand({ Bucket: bucket, Key: key });
|
||||
s3Metadata = await s3Client.send(headCommand);
|
||||
|
||||
if (s3Metadata.ContentLength === localSize) {
|
||||
shouldDownload = false;
|
||||
console.log(`[Cache] Verified ${key}: Local size matches S3 (${localSize} bytes).`);
|
||||
} else {
|
||||
console.log(`[Cache] Mismatch for ${key}: Local ${localSize} vs S3 ${s3Metadata.ContentLength}. Re-downloading.`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[Cache] Failed to verify S3 metadata for ${key}:`, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldDownload) {
|
||||
progressMap[progressKey] = {
|
||||
status: 'downloaded',
|
||||
percent: 100,
|
||||
downloadedBytes: totalBytes,
|
||||
totalBytes,
|
||||
downloadedBytes: s3Metadata.ContentLength,
|
||||
totalBytes: s3Metadata.ContentLength,
|
||||
streamSessionId,
|
||||
details: 'Source already downloaded locally...',
|
||||
details: 'Source cached locally and verified against S3...',
|
||||
mp4Url: null
|
||||
};
|
||||
broadcastWs(progressKey, { type: 'progress', key, progress: progressMap[progressKey] });
|
||||
@@ -489,39 +509,7 @@ const ensureS3Downloaded = async (s3Client, bucket, key, tmpInputPath, progressK
|
||||
}
|
||||
};
|
||||
|
||||
const clearDownloadCache = () => {
|
||||
const tmpDir = CACHE_DIR;
|
||||
try {
|
||||
if (!fs.existsSync(tmpDir)) return;
|
||||
const files = fs.readdirSync(tmpDir);
|
||||
for (const file of files) {
|
||||
if (file.startsWith('s3-input-') && (file.endsWith('.tmp') || file.endsWith('.downloading'))) {
|
||||
const filePath = path.join(tmpDir, file);
|
||||
fs.rmSync(filePath, { force: true });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to clear download cache:', err);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
const clearTranscodeCache = () => {
|
||||
const tmpDir = CACHE_DIR;
|
||||
try {
|
||||
if (!fs.existsSync(tmpDir)) return;
|
||||
const files = fs.readdirSync(tmpDir);
|
||||
for (const file of files) {
|
||||
if (file.startsWith('hls-')) {
|
||||
const filePath = path.join(tmpDir, file);
|
||||
fs.rmSync(filePath, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to clear transcode cache:', err);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
app.get('/api/buckets', async (req, res) => {
|
||||
@@ -573,6 +561,15 @@ app.get('/api/videos', async (req, res) => {
|
||||
if (!key) return false;
|
||||
const lowerKey = key.toLowerCase();
|
||||
return videoExtensions.some(ext => lowerKey.endsWith(ext));
|
||||
})
|
||||
.map(key => {
|
||||
const safeBucket = bucket.replace(/[^a-z0-9]/gi, '_');
|
||||
const safeKeySegments = key.split('/').map(segment => segment.replace(/[^a-z0-9]/gi, '_'));
|
||||
const hlsDir = path.join(CACHE_DIR, `hls-${safeBucket}-${safeKeySegments.join('-')}`);
|
||||
return {
|
||||
key: key,
|
||||
hasTranscodeCache: fs.existsSync(hlsDir)
|
||||
};
|
||||
});
|
||||
|
||||
res.json({ videos });
|
||||
@@ -622,22 +619,22 @@ app.get('/api/config', (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/clear-download-cache', (req, res) => {
|
||||
app.post('/api/clear-video-transcode-cache', async (req, res) => {
|
||||
try {
|
||||
clearDownloadCache();
|
||||
res.json({ message: 'Download cache cleared' });
|
||||
} catch (error) {
|
||||
console.error('Error clearing download cache:', error);
|
||||
res.status(500).json({ error: 'Failed to clear download cache', detail: error.message });
|
||||
}
|
||||
});
|
||||
const { bucket, key } = req.body;
|
||||
if (!bucket || !key) {
|
||||
return res.status(400).json({ error: 'Bucket and key are required' });
|
||||
}
|
||||
const safeBucket = bucket.replace(/[^a-z0-9]/gi, '_');
|
||||
const safeKeySegments = key.split('/').map(segment => segment.replace(/[^a-z0-9]/gi, '_'));
|
||||
const hlsDir = path.join(CACHE_DIR, `hls-${safeBucket}-${safeKeySegments.join('-')}`);
|
||||
|
||||
app.post('/api/clear-transcode-cache', (req, res) => {
|
||||
try {
|
||||
clearTranscodeCache();
|
||||
res.json({ message: 'Transcode cache cleared' });
|
||||
if (fs.existsSync(hlsDir)) {
|
||||
fs.rmSync(hlsDir, { recursive: true, force: true });
|
||||
}
|
||||
res.json({ message: 'Transcode cache cleared for video' });
|
||||
} catch (error) {
|
||||
console.error('Error clearing transcode cache:', error);
|
||||
console.error('Error clearing video transcode cache:', error);
|
||||
res.status(500).json({ error: 'Failed to clear transcode cache', detail: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user