Introduce `normalizeToMp3` utility to convert wav/ogg audio buffers from TTS providers to mp3, ensuring consistent mp3-only handling in cache and pipelines. Add logic to detect and adapt to OpenAI-compatible servers that do not support explicit `response_format`, falling back to default output and normalizing as needed. Refactor voice resolution to probe multiple common endpoints and robustly extract voice/style names from various payload shapes, improving compatibility with custom OpenAI-compatible servers. - Add `audio-format.ts` for audio normalization utilities - Add tests for audio format normalization - Update TTS provider request logic to apply normalization and handle response format negotiation - Enhance voice endpoint probing and extraction logic for custom servers
48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { sniffAudioFormat } from '@/lib/server/tts/audio-format';
|
|
|
|
function bytes(...values: number[]): Buffer {
|
|
return Buffer.from(values);
|
|
}
|
|
|
|
describe('sniffAudioFormat', () => {
|
|
it('detects wav from RIFF/WAVE header', () => {
|
|
const wav = Buffer.concat([
|
|
Buffer.from('RIFF'),
|
|
bytes(0x24, 0x00, 0x00, 0x00),
|
|
Buffer.from('WAVE'),
|
|
]);
|
|
expect(sniffAudioFormat(wav)).toBe('wav');
|
|
});
|
|
|
|
it('detects ogg', () => {
|
|
expect(sniffAudioFormat(Buffer.from('OggS....'))).toBe('ogg');
|
|
});
|
|
|
|
it('detects flac', () => {
|
|
expect(sniffAudioFormat(Buffer.from('fLaC....'))).toBe('flac');
|
|
});
|
|
|
|
it('detects ID3-tagged mp3', () => {
|
|
expect(sniffAudioFormat(Buffer.concat([Buffer.from('ID3'), bytes(0x03, 0x00)]))).toBe('mp3');
|
|
});
|
|
|
|
it('detects mp3 frame sync (MPEG-1 Layer III)', () => {
|
|
expect(sniffAudioFormat(bytes(0xff, 0xfb, 0x90, 0x00))).toBe('mp3');
|
|
});
|
|
|
|
it('detects mp3 frame sync (MPEG-2 Layer III)', () => {
|
|
expect(sniffAudioFormat(bytes(0xff, 0xf3, 0x00, 0x00))).toBe('mp3');
|
|
});
|
|
|
|
it('distinguishes ADTS aac from mp3 via the layer bits', () => {
|
|
expect(sniffAudioFormat(bytes(0xff, 0xf1, 0x00, 0x00))).toBe('aac');
|
|
expect(sniffAudioFormat(bytes(0xff, 0xf9, 0x00, 0x00))).toBe('aac');
|
|
});
|
|
|
|
it('returns unknown for unrecognized or short buffers', () => {
|
|
expect(sniffAudioFormat(bytes(0x00, 0x01, 0x02, 0x03))).toBe('unknown');
|
|
expect(sniffAudioFormat(bytes(0x00))).toBe('unknown');
|
|
expect(sniffAudioFormat(Buffer.alloc(0))).toBe('unknown');
|
|
});
|
|
});
|