Format
+ {result.file_type && (
+
+ Type:
+ {result.file_type}
+
+ )}
Sample Rate:
{(result.sample_rate / 1000).toFixed(1)} kHz
@@ -133,11 +147,43 @@ export function AudioAnalysis({ result, analyzing, onAnalyze, showAnalyzeButton
Total Samples:
- {result.total_samples.toLocaleString()}
+ {totalSamplesText}
+ {hasCodecMeta && (
+
+
MP3 Meta
+
+ {result.codec_mode && (
+
+ Mode:
+ {result.codec_mode}
+
+ )}
+ {typeof result.bitrate_kbps === "number" && (
+
+ Bitrate:
+ {result.bitrate_kbps} kbps
+
+ )}
+ {typeof result.total_frames === "number" && result.total_frames > 0 && (
+
+ Frames:
+ {result.total_frames.toLocaleString()}
+
+ )}
+ {result.codec_version && (
+
+ Version:
+ {result.codec_version}
+
+ )}
+
+
+ )}
+
{result.spectrum && (() => {
const frames = result.spectrum.time_slices.length;
const fftSize = (result.spectrum.freq_bins - 1) * 2;
@@ -156,7 +202,7 @@ export function AudioAnalysis({ result, analyzing, onAnalyze, showAnalyzeButton
{fftSize.toLocaleString()}
- Freq Resolution:
+ {freqResolutionLabel}
{freqRes.toFixed(2)} Hz/bin
diff --git a/frontend/src/components/AudioAnalysisPage.tsx b/frontend/src/components/AudioAnalysisPage.tsx
index fd28169..752e970 100644
--- a/frontend/src/components/AudioAnalysisPage.tsx
+++ b/frontend/src/components/AudioAnalysisPage.tsx
@@ -13,16 +13,41 @@ interface AudioAnalysisPageProps {
onBack?: () => void;
}
-function isFlacPath(filePath: string): boolean {
- return filePath.toLowerCase().endsWith(".flac");
+const SUPPORTED_AUDIO_EXTENSIONS = [".flac", ".mp3", ".m4a", ".aac"];
+const SUPPORTED_AUDIO_ACCEPT = [
+ ".flac",
+ ".mp3",
+ ".m4a",
+ ".aac",
+ "audio/flac",
+ "audio/x-flac",
+ "audio/mpeg",
+ "audio/mp3",
+ "audio/mp4",
+ "audio/x-m4a",
+ "audio/aac",
+ "audio/aacp",
+].join(",");
+const SUPPORTED_AUDIO_LABEL = "FLAC, MP3, M4A, or AAC";
+
+function isSupportedAudioPath(filePath: string): boolean {
+ const normalized = filePath.toLowerCase();
+ return SUPPORTED_AUDIO_EXTENSIONS.some((ext) => normalized.endsWith(ext));
}
-function isFlacFile(file: File): boolean {
- const name = file.name.toLowerCase();
+function isSupportedAudioFile(file: File): boolean {
+ const normalizedName = file.name.toLowerCase();
+ const normalizedType = file.type.toLowerCase();
return (
- name.endsWith(".flac") ||
- file.type === "audio/flac" ||
- file.type === "audio/x-flac"
+ SUPPORTED_AUDIO_EXTENSIONS.some((ext) => normalizedName.endsWith(ext)) ||
+ normalizedType === "audio/flac" ||
+ normalizedType === "audio/x-flac" ||
+ normalizedType === "audio/mpeg" ||
+ normalizedType === "audio/mp3" ||
+ normalizedType === "audio/mp4" ||
+ normalizedType === "audio/x-m4a" ||
+ normalizedType === "audio/aac" ||
+ normalizedType === "audio/aacp"
);
}
@@ -55,9 +80,9 @@ export function AudioAnalysisPage({ onBack }: AudioAnalysisPageProps) {
const spectrumRef = useRef<{ getCanvasDataURL: () => string | null; }>(null);
const analyzeSelectedPath = useCallback(async (filePath: string) => {
- if (!isFlacPath(filePath)) {
+ if (!isSupportedAudioPath(filePath)) {
toast.error("Invalid File Type", {
- description: "Please select a FLAC file for analysis",
+ description: `Please select a ${SUPPORTED_AUDIO_LABEL} file for analysis`,
});
return;
}
@@ -65,9 +90,9 @@ export function AudioAnalysisPage({ onBack }: AudioAnalysisPageProps) {
}, [analyzeFilePath]);
const analyzeSelectedFile = useCallback(async (file: File) => {
- if (!isFlacFile(file)) {
+ if (!isSupportedAudioFile(file)) {
toast.error("Invalid File Type", {
- description: "Please select a FLAC file for analysis",
+ description: `Please select a ${SUPPORTED_AUDIO_LABEL} file for analysis`,
});
return;
}
@@ -165,7 +190,7 @@ export function AudioAnalysisPage({ onBack }: AudioAnalysisPageProps) {
@@ -221,13 +246,16 @@ export function AudioAnalysisPage({ onBack }: AudioAnalysisPageProps) {
{isDragging
- ? "Drop your FLAC file here"
- : "Drag and drop a FLAC file here, or click the button below to select"}
+ ? "Drop your audio file here"
+ : "Drag and drop an audio file here, or click the button below to select"}
+ Supported formats: FLAC, MP3, M4A, AAC
+