From 8fc9081487d4bef20b41cb1262a4b1c91a38c723 Mon Sep 17 00:00:00 2001 From: Srivarshan-T Date: Sun, 20 Jul 2025 00:19:13 +0530 Subject: [PATCH] feat: add AAC to MP3 audio converter tool --- public/locales/en/audio.json | 6 ++ .../audio/AAC-MP3/AAC-MP3.service.test.ts | 44 ++++++++++++++ src/pages/tools/audio/AAC-MP3/index.tsx | 59 +++++++++++++++++++ src/pages/tools/audio/AAC-MP3/meta.ts | 15 +++++ src/pages/tools/audio/AAC-MP3/service.ts | 35 +++++++++++ src/pages/tools/audio/index.ts | 4 +- 6 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 src/pages/tools/audio/AAC-MP3/AAC-MP3.service.test.ts create mode 100644 src/pages/tools/audio/AAC-MP3/index.tsx create mode 100644 src/pages/tools/audio/AAC-MP3/meta.ts create mode 100644 src/pages/tools/audio/AAC-MP3/service.ts diff --git a/public/locales/en/audio.json b/public/locales/en/audio.json index 5184efe..9a95626 100644 --- a/public/locales/en/audio.json +++ b/public/locales/en/audio.json @@ -57,5 +57,11 @@ "title": "What is {{title}}?" }, "trimmingAudio": "Trimming Audio" + }, + "AACMP3": { + "title": "AAC to MP3", + "description": "convert AAC audio files to MP3 format.Which is a common audio format used for music and other audio files.", + "shortDescription": "convert AAC audio files to MP3 format.", + "longDescription": "convert AAC audio files to MP3 format. MP3 is a widely used audio format that provides good sound quality and is compatible with most devices and platforms. This tool allows you to convert your AAC files to MP3 easily, making it convenient for playback on various devices." } } diff --git a/src/pages/tools/audio/AAC-MP3/AAC-MP3.service.test.ts b/src/pages/tools/audio/AAC-MP3/AAC-MP3.service.test.ts new file mode 100644 index 0000000..07ae026 --- /dev/null +++ b/src/pages/tools/audio/AAC-MP3/AAC-MP3.service.test.ts @@ -0,0 +1,44 @@ +import { describe, it, expect, vi } from 'vitest'; + +// Mock FFmpeg and fetchFile +vi.mock('@ffmpeg/ffmpeg', () => ({ + FFmpeg: vi.fn().mockImplementation(() => ({ + load: vi.fn().mockResolvedValue(undefined), + writeFile: vi.fn().mockResolvedValue(undefined), + exec: vi.fn().mockResolvedValue(undefined), + readFile: vi.fn().mockReturnValue(new Uint8Array([1, 2, 3, 4, 5])), + unlink: vi.fn().mockResolvedValue(undefined) + })) +})); + +vi.mock('@ffmpeg/util', () => ({ + fetchFile: vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3, 4, 5])) +})); + +// Import service +import { AACtoMp3 } from './service'; + +describe('convertAACtoMP3', () => { + it('should return a new MP3 File when given a valid AAC file', async () => { + const mockAACData = new Uint8Array([0, 1, 2, 3, 4, 5]); + const mockFile = new File([mockAACData], 'sample.aac', { + type: 'audio/aac' + }); + + const result = await AACtoMp3(mockFile); + + expect(result).toBeInstanceOf(File); + expect(result.name).toBe('sample.mp3'); + expect(result.type).toBe('audio/mpeg'); + }); + + it('should throw error if file type is not AAC', async () => { + const mockFile = new File(['dummy'], 'song.wav', { + type: 'audio/wav' + }); + + await expect(() => AACtoMp3(mockFile)).rejects.toThrowError( + 'Only .aac files are allowed.' // FIXED to match actual error + ); + }); +}); diff --git a/src/pages/tools/audio/AAC-MP3/index.tsx b/src/pages/tools/audio/AAC-MP3/index.tsx new file mode 100644 index 0000000..bab58cc --- /dev/null +++ b/src/pages/tools/audio/AAC-MP3/index.tsx @@ -0,0 +1,59 @@ +import React, { useState } from 'react'; +import ToolContent from '@components/ToolContent'; +import { ToolComponentProps } from '@tools/defineTool'; +import ToolAudioInput from '@components/input/ToolAudioInput'; +import ToolFileResult from '@components/result/ToolFileResult'; + +import { AACtoMp3 } from './service'; + +export default function AACMP3({ title, longDescription }: ToolComponentProps) { + const [input, setInput] = useState(null); + const [result, setResult] = useState(null); + const [loading, setLoading] = useState(false); + + const compute = async ( + _optionsValues: {}, + input: File | null + ): Promise => { + if (!input) return; + + try { + if (!input.name.toLowerCase().endsWith('.aac')) { + setInput(null); + alert('please upload .aac files are allowed.'); + setResult(null); + + return; + } + setLoading(true); + const resultFile = await AACtoMp3(input); + setResult(resultFile); + } catch (error) { + console.error('Conversion failed:', error); + setResult(null); + } + setLoading(false); + }; + + return ( + + } + resultComponent={ + + } + initialValues={{}} + getGroups={null} + setInput={setInput} + compute={compute} + toolInfo={{ title: `What is a ${title}?`, description: longDescription }} + /> + ); +} diff --git a/src/pages/tools/audio/AAC-MP3/meta.ts b/src/pages/tools/audio/AAC-MP3/meta.ts new file mode 100644 index 0000000..5252bda --- /dev/null +++ b/src/pages/tools/audio/AAC-MP3/meta.ts @@ -0,0 +1,15 @@ +import { defineTool } from '@tools/defineTool'; +import { lazy } from 'react'; + +export const tool = defineTool('audio', { + i18n: { + name: 'audio:AACMP3.title', + description: 'audio:AACMP3.description', + shortDescription: 'audio:AACMP3.shortDescription', + longDescription: 'audio:AACMP3.longDescription' + }, + path: 'AAC-MP3', + icon: 'bi:filetype-mp3', + keywords: ['AAC', 'MP3', 'convert', 'audio', 'file conversion'], + component: lazy(() => import('./index')) +}); diff --git a/src/pages/tools/audio/AAC-MP3/service.ts b/src/pages/tools/audio/AAC-MP3/service.ts new file mode 100644 index 0000000..f3d37d6 --- /dev/null +++ b/src/pages/tools/audio/AAC-MP3/service.ts @@ -0,0 +1,35 @@ +import { FFmpeg } from '@ffmpeg/ffmpeg'; +import { fetchFile } from '@ffmpeg/util'; + +const ffmpeg = new FFmpeg(); +let isLoaded = false; + +export async function AACtoMp3(input: File): Promise { + if (!isLoaded) { + await ffmpeg.load(); + isLoaded = true; + } + + const inName = 'input.aac'; + const outName = 'output.mp3'; + + await ffmpeg.writeFile(inName, await fetchFile(input)); + + await ffmpeg.exec([ + '-i', + inName, + '-c:a', + 'libmp3lame', + '-b:a', + '192k', + outName + ]); + + const data = await ffmpeg.readFile(outName); + + const mp3 = new File([data], input.name.replace(/\.aac$/i, '.mp3'), { + type: 'audio/mpeg' + }); + + return mp3; +} diff --git a/src/pages/tools/audio/index.ts b/src/pages/tools/audio/index.ts index 3596a1c..12341b4 100644 --- a/src/pages/tools/audio/index.ts +++ b/src/pages/tools/audio/index.ts @@ -1,3 +1,4 @@ +import { tool as audioAACMP3 } from './AAC-MP3/meta'; import { tool as audioMergeAudio } from './merge-audio/meta'; import { tool as audioTrim } from './trim/meta'; import { tool as audioChangeSpeed } from './change-speed/meta'; @@ -7,5 +8,6 @@ export const audioTools = [ audioExtractAudio, audioChangeSpeed, audioTrim, - audioMergeAudio + audioMergeAudio, + audioAACMP3 ];