feat: Add backfill script for image brightness stats and display them in the UI.
This commit is contained in:
49
server.js
49
server.js
@@ -116,14 +116,43 @@ app.post('/upload', authenticate, upload.single('image'), async (req, res) => {
|
||||
|
||||
// Generate thumbnail
|
||||
try {
|
||||
const image = sharp(req.file.path);
|
||||
const metadata = await image.metadata(); // Get metadata first
|
||||
const stats = await image.stats(); // Get stats (includes mean for channels)
|
||||
|
||||
// Calculate Average Brightness
|
||||
// Simple average of R, G, B mean values (0-255)
|
||||
const brightness = Math.round((stats.channels[0].mean + stats.channels[1].mean + stats.channels[2].mean) / 3);
|
||||
|
||||
const thumbnailFilename = req.file.filename.replace(path.extname(req.file.filename), '_thumb.avif');
|
||||
const thumbnailPath = path.join(path.dirname(req.file.path), thumbnailFilename);
|
||||
const dirPath = path.dirname(req.file.path);
|
||||
|
||||
await sharp(req.file.path)
|
||||
await image
|
||||
.resize(320) // Resize to 320px width, auto height
|
||||
.toFormat('avif')
|
||||
.toFile(thumbnailPath);
|
||||
|
||||
// Update daily stats.json
|
||||
const statsFile = path.join(dirPath, 'stats.json');
|
||||
let dailyStats = [];
|
||||
try {
|
||||
if (fs.existsSync(statsFile)) {
|
||||
dailyStats = JSON.parse(fs.readFileSync(statsFile, 'utf8'));
|
||||
}
|
||||
} catch (e) { console.error('Error reading stats.json', e); }
|
||||
|
||||
dailyStats.push({
|
||||
timestamp: new Date().toISOString(),
|
||||
filename: req.file.filename,
|
||||
brightness
|
||||
});
|
||||
|
||||
// Write back stats
|
||||
try {
|
||||
fs.writeFileSync(statsFile, JSON.stringify(dailyStats, null, 2));
|
||||
} catch (e) { console.error('Error writing stats.json', e); }
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
cameraId,
|
||||
@@ -132,17 +161,18 @@ app.post('/upload', authenticate, upload.single('image'), async (req, res) => {
|
||||
thumbnail: thumbnailFilename,
|
||||
thumbnailPath: thumbnailPath,
|
||||
size: req.file.size,
|
||||
brightness,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Thumbnail generation failed:', error);
|
||||
// Still return success for the upload even if thumbnail fails
|
||||
console.error('Processing failed:', error);
|
||||
// Still return success for the upload even if processing fails
|
||||
res.json({
|
||||
success: true,
|
||||
cameraId,
|
||||
filename: req.file.filename,
|
||||
path: req.file.path,
|
||||
thumbnailError: error.message,
|
||||
error: error.message,
|
||||
size: req.file.size,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
@@ -378,7 +408,16 @@ app.get('/cameras/:cameraId/:year/:month/:day', async (req, res) => {
|
||||
// Sort by filename (timestamp) descending
|
||||
images.sort((a, b) => b.filename.localeCompare(a.filename));
|
||||
|
||||
res.json({ images });
|
||||
// Load stats if available
|
||||
let stats = [];
|
||||
try {
|
||||
const statsFile = path.join(datePath, 'stats.json');
|
||||
if (fs.existsSync(statsFile)) {
|
||||
stats = JSON.parse(fs.readFileSync(statsFile, 'utf8'));
|
||||
}
|
||||
} catch (e) { console.error('Error reading stats.json', e); }
|
||||
|
||||
res.json({ images, stats });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to list images', details: error.message });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user