mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-12-19 05:05:44 +08:00
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:
parent
28ce5d3cb4
commit
caaf8be3b2
@ -30,7 +30,8 @@ async function handleWavFile(
|
|||||||
): Promise<{ input: Buffer; sampleRate: number }> {
|
): Promise<{ input: Buffer; sampleRate: number }> {
|
||||||
const { fmt } = getWavFileInfo(file);
|
const { fmt } = getWavFileInfo(file);
|
||||||
if (!ALLOW_SAMPLE_RATE.includes(fmt.sampleRate)) {
|
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 };
|
return { input: file, sampleRate: fmt.sampleRate };
|
||||||
}
|
}
|
||||||
@ -42,9 +43,18 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
|||||||
if (!isSilk(file)) {
|
if (!isSilk(file)) {
|
||||||
logger.log(`语音文件${filePath}需要转换成silk`);
|
logger.log(`语音文件${filePath}需要转换成silk`);
|
||||||
const pcmPath = `${pttPath}.pcm`;
|
const pcmPath = `${pttPath}.pcm`;
|
||||||
const { input, sampleRate } = isWav(file)
|
// 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 };
|
||||||
? await handleWavFile(file, filePath, pcmPath)
|
let input: Buffer;
|
||||||
: { input: await FFmpegService.convert(filePath, pcmPath), sampleRate: 24000 };
|
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 });
|
const silk = await runTask<EncodeArgs, EncodeResult>(getWorkerPath(), { input: input, sampleRate: sampleRate });
|
||||||
fsPromise.unlink(pcmPath).catch((e) => logger.logError('删除临时文件失败', pcmPath, e));
|
fsPromise.unlink(pcmPath).catch((e) => logger.logError('删除临时文件失败', pcmPath, e));
|
||||||
await fsPromise.writeFile(pttPath, Buffer.from(silk.data));
|
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) {
|
} catch (error: unknown) {
|
||||||
logger.logError('convert silk failed', (error as Error).stack);
|
logger.logError('convert silk failed', error);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,7 @@ export interface IFFmpegAdapter {
|
|||||||
* @param pcmPath 输出 PCM 文件路径
|
* @param pcmPath 输出 PCM 文件路径
|
||||||
* @returns PCM 数据 Buffer
|
* @returns PCM 数据 Buffer
|
||||||
*/
|
*/
|
||||||
convertToPCM(filePath: string, pcmPath: string): Promise<Buffer>;
|
convertToPCM(filePath: string, pcmPath: string): Promise<{ result: boolean, sampleRate: number }>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换音频文件
|
* 转换音频文件
|
||||||
|
|||||||
@ -88,14 +88,11 @@ export class FFmpegAddonAdapter implements IFFmpegAdapter {
|
|||||||
/**
|
/**
|
||||||
* 转换为 PCM
|
* 转换为 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 addon = this.ensureAddon();
|
||||||
const result = await addon.decodeAudioToPCM(filePath);
|
const result = await addon.decodeAudioToPCM(filePath, pcmPath, 24000);
|
||||||
|
|
||||||
// 写入文件
|
return result;
|
||||||
await writeFile(pcmPath, result.pcm);
|
|
||||||
|
|
||||||
return result.pcm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -67,5 +67,5 @@ export interface FFmpeg {
|
|||||||
/**
|
/**
|
||||||
* Decode audio file to raw PCM data
|
* Decode audio file to raw PCM data
|
||||||
*/
|
*/
|
||||||
decodeAudioToPCM(filePath: string): Promise<AudioPCMResult>;
|
decodeAudioToPCM(filePath: string, pcmPath: string, sampleRate?: number): Promise<{ result: boolean, sampleRate: number }>;
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ export class FFmpegExecAdapter implements IFFmpegAdapter {
|
|||||||
/**
|
/**
|
||||||
* 转换为 PCM
|
* 转换为 PCM
|
||||||
*/
|
*/
|
||||||
async convertToPCM(filePath: string, pcmPath: string): Promise<Buffer> {
|
async convertToPCM(filePath: string, pcmPath: string): Promise<{ result: boolean, sampleRate: number }> {
|
||||||
try {
|
try {
|
||||||
ensureDirExists(pcmPath);
|
ensureDirExists(pcmPath);
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ export class FFmpegExecAdapter implements IFFmpegAdapter {
|
|||||||
throw new Error('转换PCM失败,输出文件不存在');
|
throw new Error('转换PCM失败,输出文件不存在');
|
||||||
}
|
}
|
||||||
|
|
||||||
return readFileSync(pcmPath);
|
return { result: true, sampleRate: 24000 };
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw new Error(`FFmpeg处理转换出错: ${error.message}`);
|
throw new Error(`FFmpeg处理转换出错: ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,7 +93,7 @@ export class FFmpegService {
|
|||||||
/**
|
/**
|
||||||
* 转换为 PCM 格式
|
* 转换为 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();
|
const adapter = await this.getAdapter();
|
||||||
return adapter.convertToPCM(filePath, pcmPath);
|
return adapter.convertToPCM(filePath, pcmPath);
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user