Refactor PCM conversion to return result and sample rate

Updated the FFmpeg adapter interfaces and implementations so that PCM conversion methods now return an object containing the conversion result and sample rate, instead of a Buffer. Adjusted audio processing logic to accommodate this change and improved error logging. Updated native ffmpeg addon binaries.
This commit is contained in:
手瓜一十雪 2025-11-01 23:23:15 +08:00
parent 28ce5d3cb4
commit caaf8be3b2
10 changed files with 23 additions and 16 deletions

View File

@ -30,7 +30,8 @@ async function handleWavFile(
): Promise<{ input: Buffer; sampleRate: number }> {
const { fmt } = getWavFileInfo(file);
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
return { input: await FFmpegService.convert(filePath, pcmPath), sampleRate: 24000 };
const result = await FFmpegService.convert(filePath, pcmPath);
return { input: await fsPromise.readFile(pcmPath), sampleRate: result.sampleRate };
}
return { input: file, sampleRate: fmt.sampleRate };
}
@ -42,9 +43,18 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
if (!isSilk(file)) {
logger.log(`语音文件${filePath}需要转换成silk`);
const pcmPath = `${pttPath}.pcm`;
const { input, sampleRate } = isWav(file)
? await handleWavFile(file, filePath, pcmPath)
: { input: await FFmpegService.convert(filePath, pcmPath), sampleRate: 24000 };
// const { input, sampleRate } = isWav(file) ? await handleWavFile(file, filePath, pcmPath): { input: await FFmpegService.convert(filePath, pcmPath) ? await fsPromise.readFile(pcmPath) : Buffer.alloc(0), sampleRate: 24000 };
let input: Buffer;
let sampleRate: number;
if (isWav(file)) {
const result = await handleWavFile(file, filePath, pcmPath);
input = result.input;
sampleRate = result.sampleRate;
} else {
const result = await FFmpegService.convert(filePath, pcmPath);
input = await fsPromise.readFile(pcmPath);
sampleRate = result.sampleRate;
}
const silk = await runTask<EncodeArgs, EncodeResult>(getWorkerPath(), { input: input, sampleRate: sampleRate });
fsPromise.unlink(pcmPath).catch((e) => logger.logError('删除临时文件失败', pcmPath, e));
await fsPromise.writeFile(pttPath, Buffer.from(silk.data));
@ -69,7 +79,7 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
};
}
} catch (error: unknown) {
logger.logError('convert silk failed', (error as Error).stack);
logger.logError('convert silk failed', error);
return {};
}
}

View File

@ -49,7 +49,7 @@ export interface IFFmpegAdapter {
* @param pcmPath PCM
* @returns PCM Buffer
*/
convertToPCM(filePath: string, pcmPath: string): Promise<Buffer>;
convertToPCM(filePath: string, pcmPath: string): Promise<{ result: boolean, sampleRate: number }>;
/**
*

View File

@ -88,14 +88,11 @@ export class FFmpegAddonAdapter implements IFFmpegAdapter {
/**
* PCM
*/
async convertToPCM(filePath: string, pcmPath: string): Promise<Buffer> {
async convertToPCM(filePath: string, pcmPath: string): Promise<{ result: boolean, sampleRate: number }> {
const addon = this.ensureAddon();
const result = await addon.decodeAudioToPCM(filePath);
const result = await addon.decodeAudioToPCM(filePath, pcmPath, 24000);
// 写入文件
await writeFile(pcmPath, result.pcm);
return result.pcm;
return result;
}
/**

View File

@ -67,5 +67,5 @@ export interface FFmpeg {
/**
* Decode audio file to raw PCM data
*/
decodeAudioToPCM(filePath: string): Promise<AudioPCMResult>;
decodeAudioToPCM(filePath: string, pcmPath: string, sampleRate?: number): Promise<{ result: boolean, sampleRate: number }>;
}

View File

@ -157,7 +157,7 @@ export class FFmpegExecAdapter implements IFFmpegAdapter {
/**
* PCM
*/
async convertToPCM(filePath: string, pcmPath: string): Promise<Buffer> {
async convertToPCM(filePath: string, pcmPath: string): Promise<{ result: boolean, sampleRate: number }> {
try {
ensureDirExists(pcmPath);
@ -174,7 +174,7 @@ export class FFmpegExecAdapter implements IFFmpegAdapter {
throw new Error('转换PCM失败输出文件不存在');
}
return readFileSync(pcmPath);
return { result: true, sampleRate: 24000 };
} catch (error: any) {
throw new Error(`FFmpeg处理转换出错: ${error.message}`);
}

View File

@ -93,7 +93,7 @@ export class FFmpegService {
/**
* PCM
*/
public static async convert(filePath: string, pcmPath: string): Promise<Buffer> {
public static async convert(filePath: string, pcmPath: string): Promise<{ result: boolean, sampleRate: number }> {
const adapter = await this.getAdapter();
return adapter.convertToPCM(filePath, pcmPath);
}