diff --git a/app/admin/page.tsx b/app/admin/page.tsx
index c5c2157..685e6bc 100644
--- a/app/admin/page.tsx
+++ b/app/admin/page.tsx
@@ -84,7 +84,25 @@ export default function AdminPage() {
});
if (res.ok) {
- setMessage('Song uploaded successfully!');
+ const data = await res.json();
+ const validation = data.validation;
+
+ let statusMessage = 'ā
Song uploaded successfully!\n\n';
+ statusMessage += `š Audio Info:\n`;
+ statusMessage += `⢠Format: ${validation.codec || 'unknown'}\n`;
+ statusMessage += `⢠Bitrate: ${Math.round(validation.bitrate / 1000)} kbps\n`;
+ statusMessage += `⢠Sample Rate: ${validation.sampleRate} Hz\n`;
+ statusMessage += `⢠Duration: ${Math.round(validation.duration)} seconds\n`;
+ statusMessage += `⢠Cover Art: ${validation.hasCover ? 'ā
Yes' : 'ā No'}\n`;
+
+ if (validation.warnings.length > 0) {
+ statusMessage += `\nā ļø Warnings:\n`;
+ validation.warnings.forEach((warning: string) => {
+ statusMessage += `⢠${warning}\n`;
+ });
+ }
+
+ setMessage(statusMessage);
setFile(null);
fetchSongs();
} else {
@@ -247,7 +265,20 @@ export default function AdminPage() {
- {message &&
{message}
}
+ {message && (
+
+ {message}
+
+ )}
diff --git a/app/api/songs/route.ts b/app/api/songs/route.ts
index 0a9dad9..3aae87e 100644
--- a/app/api/songs/route.ts
+++ b/app/api/songs/route.ts
@@ -41,17 +41,62 @@ export async function POST(request: Request) {
const buffer = Buffer.from(await file.arrayBuffer());
- // Extract metadata from file
+ // Validate and extract metadata from file
+ let metadata;
+ let validationInfo = {
+ isValid: true,
+ hasCover: false,
+ format: '',
+ bitrate: 0,
+ sampleRate: 0,
+ duration: 0,
+ codec: '',
+ warnings: [] as string[],
+ };
+
try {
- const metadata = await parseBuffer(buffer, file.type);
+ metadata = await parseBuffer(buffer, file.type);
+
+ // Extract basic metadata
if (metadata.common.title) {
title = metadata.common.title;
}
if (metadata.common.artist) {
artist = metadata.common.artist;
}
+
+ // Validation info
+ validationInfo.hasCover = !!metadata.common.picture?.[0];
+ validationInfo.format = metadata.format.container || 'unknown';
+ validationInfo.bitrate = metadata.format.bitrate || 0;
+ validationInfo.sampleRate = metadata.format.sampleRate || 0;
+ validationInfo.duration = metadata.format.duration || 0;
+ validationInfo.codec = metadata.format.codec || 'unknown';
+
+ // Validate format
+ if (metadata.format.container !== 'MPEG') {
+ validationInfo.warnings.push('File may not be a standard MP3 (MPEG container expected)');
+ }
+
+ // Check bitrate
+ if (validationInfo.bitrate && validationInfo.bitrate < 96000) {
+ validationInfo.warnings.push(`Low bitrate detected: ${Math.round(validationInfo.bitrate / 1000)} kbps`);
+ }
+
+ // Check sample rate
+ if (validationInfo.sampleRate && ![44100, 48000].includes(validationInfo.sampleRate)) {
+ validationInfo.warnings.push(`Non-standard sample rate: ${validationInfo.sampleRate} Hz (recommended: 44100 or 48000 Hz)`);
+ }
+
+ // Check duration
+ if (!validationInfo.duration || validationInfo.duration < 30) {
+ validationInfo.warnings.push('Audio file is very short (less than 30 seconds)');
+ }
+
} catch (e) {
console.error('Failed to parse metadata:', e);
+ validationInfo.isValid = false;
+ validationInfo.warnings.push('Failed to parse audio metadata - file may be corrupted');
}
// Fallback if still missing
@@ -66,8 +111,7 @@ export async function POST(request: Request) {
// Handle cover image
let coverImage = null;
try {
- const metadata = await parseBuffer(buffer, file.type);
- const picture = metadata.common.picture?.[0];
+ const picture = metadata?.common.picture?.[0];
if (picture) {
const extension = picture.format.split('/')[1] || 'jpg';
@@ -90,7 +134,10 @@ export async function POST(request: Request) {
},
});
- return NextResponse.json(song);
+ return NextResponse.json({
+ song,
+ validation: validationInfo,
+ });
} catch (error) {
console.error('Error uploading song:', error);
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });