From f71d30732f92708f04f8d0ace1296450648de5e5 Mon Sep 17 00:00:00 2001 From: Joel Mathew Thomas <90510078+joelmathewthomas@users.noreply.github.com> Date: Wed, 26 Feb 2025 01:59:33 +0530 Subject: [PATCH] endpoint: /api/trim - Define new api endpoint /api/trim, params: file_uuid, overwrites exisiting file on server with trimmed audio. - Remove print messages in freqsplit/postprocessing/audio_writer.export_audio() - Add new file api/utils.py for commonly used functions --- api/api/tasks.py | 13 ++++++- api/api/utils.py | 9 +++++ api/api/views.py | 40 ++++++++++++++------ api/backend/urls.py | 4 +- src/freqsplit/postprocessing/audio_writer.py | 7 ---- 5 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 api/api/utils.py diff --git a/api/api/tasks.py b/api/api/tasks.py index bdf50c7..639f497 100644 --- a/api/api/tasks.py +++ b/api/api/tasks.py @@ -2,6 +2,7 @@ from celery import shared_task from freqsplit.input.file_reader import read_audio from freqsplit.preprocessing.classify import classify_audio from freqsplit.preprocessing.normalize import normalize_audio +from freqsplit.preprocessing.trim import trim_audio from freqsplit.postprocessing.audio_writer import export_audio @shared_task @@ -28,4 +29,14 @@ def normalize_audio_task(file_path): return True except Exception as e: return False - \ No newline at end of file + +@shared_task +def trim_audio_task(file_path): + """Celery task to trim audio synchronously""" + try: + audio, sr = read_audio(file_path) + trimmed_audio = trim_audio(audio, sr) + export_audio(trimmed_audio, file_path, sr) + return True + except Exception as e: + return False \ No newline at end of file diff --git a/api/api/utils.py b/api/api/utils.py new file mode 100644 index 0000000..361720f --- /dev/null +++ b/api/api/utils.py @@ -0,0 +1,9 @@ +# api/utils.py +import os + +def get_audio_file_path(file_uuid, base_dir): + """Returns the full path to the audio file inside the given UUID folder.""" + dir_path = os.path.join(base_dir, file_uuid) + if not os.path.exists(dir_path) or not os.listdir(dir_path): + return False + return os.path.join(dir_path, os.listdir(dir_path)[0]) # Assumes only one file exists \ No newline at end of file diff --git a/api/api/views.py b/api/api/views.py index ebbb78f..a11063d 100644 --- a/api/api/views.py +++ b/api/api/views.py @@ -3,8 +3,10 @@ import uuid from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import status +from .utils import get_audio_file_path from .tasks import save_and_classify from .tasks import normalize_audio_task +from .tasks import trim_audio_task from freqsplit.input.format_checker import is_supported_format UPLOAD_DIR = "/tmp/freqsplit" @@ -12,6 +14,8 @@ UPLOAD_DIR = "/tmp/freqsplit" # Ensure the temp directory exists os.makedirs(UPLOAD_DIR, exist_ok=True) +# + # Endpoint to upload audio and classify it to audio_class @api_view(['POST']) def upload_audio(request): @@ -57,23 +61,35 @@ def normalize_audio(request): if not file_uuid: return Response({"error": "Missing file_uuid"}, status=status.HTTP_400_BAD_REQUEST) - audio_dir = os.path.join(UPLOAD_DIR, file_uuid) - - if not os.path.exists(audio_dir) or not os.path.isdir(audio_dir): - return Response({"error": "File directory not found"}, status=status.HTTP_400_BAD_REQUEST) - - # Get the actual file name (since there's only one file) - files = os.listdir(audio_dir) - if not files: - return Response({"error": "No file found in directory"}, status=status.HTTP_400_BAD_REQUEST) - - file_name = files[0] - file_path = os.path.join(audio_dir, file_name) + file_path = get_audio_file_path(file_uuid, UPLOAD_DIR) + if file_path == False: + return Response({"error": "No files found"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) # Call Celery task synchronously task = normalize_audio_task.apply(args=(file_path,)) if task.get(): return Response({"message": "Audio normalized successfully"}, status=status.HTTP_200_OK) + else: + return Response({"error": "Failed to normalize audio"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + +# Endpoint to trim audio +@api_view(['POST']) +def trim_audio(request): + """Handles trimming of leading and trailing silence from an audio clip""" + file_uuid = request.data.get("file_uuid") + + if not file_uuid: + return Response({"error": "Missing file_uuid"}, status=status.HTTP_400_BAD_REQUEST) + + file_path = get_audio_file_path(file_uuid, UPLOAD_DIR) + if file_path == False: + return Response({"error": "No files found"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + # Call Celery task synchronously + task = trim_audio_task.apply(args=(file_path,)) + + if task.get(): + return Response({"message": "Audio trimmed successfulyl"}, status=status.HTTP_200_OK) else: return Response({"error": "Failed to normalize audio"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) \ No newline at end of file diff --git a/api/backend/urls.py b/api/backend/urls.py index 50085f8..24eef56 100644 --- a/api/backend/urls.py +++ b/api/backend/urls.py @@ -18,9 +18,11 @@ from django.contrib import admin from django.urls import path from api.views import upload_audio from api.views import normalize_audio +from api.views import trim_audio urlpatterns = [ path('admin/', admin.site.urls), path('api/upload', upload_audio, name='upload_audio'), - path('api/normalize', normalize_audio, name="normalize_audio") + path('api/normalize', normalize_audio, name="normalize_audio"), + path('api/trim', trim_audio, name='trim_audio') ] diff --git a/src/freqsplit/postprocessing/audio_writer.py b/src/freqsplit/postprocessing/audio_writer.py index c069f57..4f944df 100644 --- a/src/freqsplit/postprocessing/audio_writer.py +++ b/src/freqsplit/postprocessing/audio_writer.py @@ -12,9 +12,6 @@ def export_audio(audio, output_path, sr): """ try: - - print(f"Initial audio shape: {audio.shape}, dtype: {audio.dtype}, max: {np.max(audio)}, min: {np.min(audio)}") - if audio.ndim == 2 and audio.shape[0] == 2: # Transpose stereo audio to match the expected shape audio = audio.T # From (2, num_samples) to (num_samples, 2) @@ -26,10 +23,6 @@ def export_audio(audio, output_path, sr): if np.max(np.abs(audio)) > 0: # Avoid divide by zero audio = audio / np.max(np.abs(audio)) - # Verify final format - print(f"Final audio shape: {audio.shape}, dtype: {audio.dtype}, max: {np.max(audio)}, min: {np.min(audio)}") - - sf.write(output_path, audio, sr, format='wav') print(f"Audio saved to {output_path}") except Exception as e: