From 21843f591efe291224640671480d2b282979f79c Mon Sep 17 00:00:00 2001
From: Joel Mathew Thomas <90510078+joelmathewthomas@users.noreply.github.com>
Date: Tue, 18 Mar 2025 19:21:26 +0530
Subject: [PATCH] generate spectrogram at backend and send as response to
client
---
api/api/tasks.py | 13 +++++++++++--
api/api/views.py | 16 ++++++++++------
client/package.json | 1 +
client/src/Pages/PreviewPage.tsx | 9 +++++----
client/src/Pages/UploadPage.tsx | 4 ++++
client/src/contexts/MediaContext.tsx | 6 ++++--
6 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/api/api/tasks.py b/api/api/tasks.py
index 716bbec..0c023c0 100644
--- a/api/api/tasks.py
+++ b/api/api/tasks.py
@@ -1,5 +1,7 @@
import os
import shutil
+import json
+import numpy as np
from pathlib import Path
from celery import shared_task
from freqsplit.input.file_reader import read_audio
@@ -10,6 +12,7 @@ from freqsplit.preprocessing.resample import resample
from freqsplit.postprocessing.audio_writer import export_audio
from freqsplit.separation.demucs_wrapper import separate_audio_with_demucs
from freqsplit.refinement.deepfilternet_wrapper import noisereduce
+from freqsplit.spectrogram.generator import generate_spectrogram
@shared_task
@@ -24,8 +27,14 @@ def save_and_classify(file_path, file_content):
# Classify the audio
audio_class = classify_audio(waveform, sr)
-
- return audio_class, org_sr
+
+ # Generate spectrogram
+ spec_db, plot_data = generate_spectrogram(file_path)
+ # Convert numpy array to JSON-safe list
+ spec_db = np.nan_to_num(spec_db, nan=-80.0, posinf=-80.0, neginf=-80.0)
+ spec_data_json = json.dumps(spec_db.tolist())
+
+ return audio_class, org_sr, spec_data_json, plot_data['sr']
@shared_task
def normalize_audio_task(file_path):
diff --git a/api/api/views.py b/api/api/views.py
index 4f3cc4f..cecfd43 100644
--- a/api/api/views.py
+++ b/api/api/views.py
@@ -47,17 +47,21 @@ def upload_audio(request):
# Save the uploaded file
task = save_and_classify.apply(args=(file_path, audio_file.read()))
- if task.successful():
- audio_class = task.result[0]
+ if task.ready() and task.successful():
+ result = task.result
return Response(
{
"Status": "File uploaded successfully",
"file_uuid": file_uuid,
- "audio_class": audio_class,
- "sr": task.result[1]
- },
+ "audio_class": result[0],
+ "sr": result[1],
+ "spectrogram": result[2],
+ "spec_sr": result[3]
+ },
status=status.HTTP_201_CREATED,
- )
+ )
+ else:
+ return Response({"error": "Processing failed"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
# Endpoint to normalize audio
@api_view(['POST'])
diff --git a/client/package.json b/client/package.json
index c521b62..2e8c182 100644
--- a/client/package.json
+++ b/client/package.json
@@ -18,6 +18,7 @@
"axios": "^1.8.3",
"jszip": "^3.10.1",
"react": "^18.2.0",
+ "react-audio-spectrogram-player": "^2.0.1",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.1"
},
diff --git a/client/src/Pages/PreviewPage.tsx b/client/src/Pages/PreviewPage.tsx
index b8d976b..1fd218e 100644
--- a/client/src/Pages/PreviewPage.tsx
+++ b/client/src/Pages/PreviewPage.tsx
@@ -11,6 +11,8 @@ import {
import { VolumeUp as VolumeUpIcon, ErrorOutline as ErrorIcon } from '@mui/icons-material';
import StepperComponent from '../components/StepperComponent';
import { useMediaContext } from '../contexts/MediaContext';
+// @ts-ignore
+import SpectrogramPlayer from "react-audio-spectrogram-player"
function PreviewPage() {
const navigate = useNavigate();
@@ -84,11 +86,10 @@ function PreviewPage() {
{mediaFile.name}
Audio Classification: {audioClass || "No data received"}
diff --git a/client/src/Pages/UploadPage.tsx b/client/src/Pages/UploadPage.tsx index 7359519..bbbe1f4 100644 --- a/client/src/Pages/UploadPage.tsx +++ b/client/src/Pages/UploadPage.tsx @@ -91,6 +91,8 @@ function UploadPage() { file_uuid: string; sr: number; audio_class: string; + spectrogram: string; + spec_sr: number; }>("/api/upload", formData, { headers: { "Content-Type": "multipart/form-data", @@ -104,6 +106,8 @@ function UploadPage() { audio_class: res.data.audio_class, file_uuid: res.data.file_uuid, sr: res.data.sr, + spectrogram: res.data.spectrogram, + spec_sr: res.data.spec_sr })); setUpload(true); } diff --git a/client/src/contexts/MediaContext.tsx b/client/src/contexts/MediaContext.tsx index 985d5e4..c42ac1a 100644 --- a/client/src/contexts/MediaContext.tsx +++ b/client/src/contexts/MediaContext.tsx @@ -3,8 +3,8 @@ import React, { createContext, useState, useContext } from 'react'; interface MediaContextType { mediaFile: { name: string; url: string; type: string } | null; setMediaFile: (file: { name: string; url: string; type: string }) => void; - response: { file_uuid: string; sr: number; audio_class: string }; - setResponse: (response: { file_uuid: string; sr: number; audio_class: string }) => void; + response: { file_uuid: string; sr: number; audio_class: string, spectrogram: string, spec_sr: number }; + setResponse: (response: { file_uuid: string; sr: number; audio_class: string, spectrogram: string, spec_sr: number }) => void; extractedFiles: { name: string; url: string }[]; setExtractedFiles: (files: {name: string; url: string }[]) => void; downloadedFileURL: string; @@ -20,6 +20,8 @@ export const MediaProvider: React.FC<{ children: React.ReactNode }> = ({ childre audio_class: "", file_uuid: "", sr: 0, + spectrogram: "", + spec_sr: 0 }); const [extractedFiles, setExtractedFiles] = useState