feat: add AAC to MP3 audio converter tool

This commit is contained in:
Srivarshan-T 2025-07-20 00:19:13 +05:30
parent fc18dc0dc0
commit 8fc9081487
6 changed files with 162 additions and 1 deletions

View File

@ -57,5 +57,11 @@
"title": "What is {{title}}?" "title": "What is {{title}}?"
}, },
"trimmingAudio": "Trimming Audio" "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."
} }
} }

View File

@ -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
);
});
});

View File

@ -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<File | null>(null);
const [result, setResult] = useState<File | null>(null);
const [loading, setLoading] = useState(false);
const compute = async (
_optionsValues: {},
input: File | null
): Promise<void> => {
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 (
<ToolContent
title={title}
input={input}
inputComponent={
<ToolAudioInput
value={input}
onChange={setInput}
title={'Upload Your AAC File'}
/>
}
resultComponent={
<ToolFileResult value={result} title={'Mp3 Output'} loading={loading} />
}
initialValues={{}}
getGroups={null}
setInput={setInput}
compute={compute}
toolInfo={{ title: `What is a ${title}?`, description: longDescription }}
/>
);
}

View File

@ -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'))
});

View File

@ -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<File> {
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;
}

View File

@ -1,3 +1,4 @@
import { tool as audioAACMP3 } from './AAC-MP3/meta';
import { tool as audioMergeAudio } from './merge-audio/meta'; import { tool as audioMergeAudio } from './merge-audio/meta';
import { tool as audioTrim } from './trim/meta'; import { tool as audioTrim } from './trim/meta';
import { tool as audioChangeSpeed } from './change-speed/meta'; import { tool as audioChangeSpeed } from './change-speed/meta';
@ -7,5 +8,6 @@ export const audioTools = [
audioExtractAudio, audioExtractAudio,
audioChangeSpeed, audioChangeSpeed,
audioTrim, audioTrim,
audioMergeAudio audioMergeAudio,
audioAACMP3
]; ];