diff --git a/src/common/ffmpeg-addon-adapter.ts b/src/common/ffmpeg-addon-adapter.ts index b2b71f86..e4e454b6 100644 --- a/src/common/ffmpeg-addon-adapter.ts +++ b/src/common/ffmpeg-addon-adapter.ts @@ -68,11 +68,13 @@ export class FFmpegAddonAdapter implements IFFmpegAdapter { const addon = this.ensureAddon(); const info = await addon.getVideoInfo(videoPath, 'bmp24'); + let format = info.format.includes(',') ? info.format.split(',')[0] ?? info.format : info.format; + console.log('[FFmpegAddonAdapter] Detected format:', format); return { width: info.width, height: info.height, duration: info.duration, - format: info.format, + format: format, thumbnail: info.image, }; } @@ -88,7 +90,7 @@ export class FFmpegAddonAdapter implements IFFmpegAdapter { /** * 转换为 PCM */ - async convertToPCM (filePath: string, pcmPath: string): Promise<{ result: boolean, sampleRate: number }> { + async convertToPCM (filePath: string, pcmPath: string): Promise<{ result: boolean, sampleRate: number; }> { const addon = this.ensureAddon(); const result = await addon.decodeAudioToPCM(filePath, pcmPath, 24000); @@ -100,13 +102,8 @@ export class FFmpegAddonAdapter implements IFFmpegAdapter { */ async convertFile (inputFile: string, outputFile: string, format: string): Promise { const addon = this.ensureAddon(); - - if (format === 'silk' || format === 'ntsilk') { - // 使用 Addon 的 NTSILK 转换 - await addon.convertToNTSilkTct(inputFile, outputFile); - } else { - throw new Error(`Format '${format}' is not supported by FFmpeg Addon`); - } + console.log('[FFmpegAddonAdapter] Converting file:', inputFile, 'to', outputFile, 'as', format); + await addon.decodeAudioToFmt(inputFile, outputFile, format); } /** diff --git a/src/common/ffmpeg-addon.ts b/src/common/ffmpeg-addon.ts index 0c068ff5..3ad82bd3 100644 --- a/src/common/ffmpeg-addon.ts +++ b/src/common/ffmpeg-addon.ts @@ -49,23 +49,25 @@ export interface AudioPCMResult { * FFmpeg interface providing all audio/video processing methods */ export interface FFmpeg { + convertFile (inputFile: string, outputFile: string, format: string): Promise<{ success: boolean; }>; /** * Get video information including resolution, duration, format, codec and first frame thumbnail */ - getVideoInfo(filePath: string, format?: 'bmp' | 'bmp24'): Promise; + getVideoInfo (filePath: string, format?: 'bmp' | 'bmp24'): Promise; /** * Get duration of audio or video file in seconds */ - getDuration(filePath: string): Promise; + getDuration (filePath: string): Promise; /** * Convert audio file to NTSILK format (WeChat voice message format) */ - convertToNTSilkTct(inputPath: string, outputPath: string): Promise; + convertToNTSilkTct (inputPath: string, outputPath: string): Promise; /** * Decode audio file to raw PCM data */ - decodeAudioToPCM(filePath: string, pcmPath: string, sampleRate?: number): Promise<{ result: boolean, sampleRate: number }>; + decodeAudioToPCM (filePath: string, pcmPath: string, sampleRate?: number): Promise<{ result: boolean, sampleRate: number; }>; + decodeAudioToFmt (filePath: string, pcmPath: string, format: string): Promise<{ channels: number; sampleRate: number; format: string; }>; } diff --git a/src/common/ffmpeg.ts b/src/common/ffmpeg.ts index 43cd120c..fd7ada0a 100644 --- a/src/common/ffmpeg.ts +++ b/src/common/ffmpeg.ts @@ -48,6 +48,14 @@ export class FFmpegService { this.initialized = true; } + public static getAdapterName (): string { + if (!this.adapter) { + throw new Error('FFmpeg service not initialized. Please call FFmpegService.init() first.'); + } + return this.adapter.name; + + } + /** * 获取 FFmpeg 适配器 */ diff --git a/src/native/ffmpeg/ffmpegAddon.darwin.arm64.node b/src/native/ffmpeg/ffmpegAddon.darwin.arm64.node index b7d779d2..89d85c2a 100644 Binary files a/src/native/ffmpeg/ffmpegAddon.darwin.arm64.node and b/src/native/ffmpeg/ffmpegAddon.darwin.arm64.node differ diff --git a/src/native/ffmpeg/ffmpegAddon.linux.arm64.node b/src/native/ffmpeg/ffmpegAddon.linux.arm64.node index 14355e39..765c93be 100644 Binary files a/src/native/ffmpeg/ffmpegAddon.linux.arm64.node and b/src/native/ffmpeg/ffmpegAddon.linux.arm64.node differ diff --git a/src/native/ffmpeg/ffmpegAddon.linux.x64.node b/src/native/ffmpeg/ffmpegAddon.linux.x64.node index 44d8dd5a..aa504139 100644 Binary files a/src/native/ffmpeg/ffmpegAddon.linux.x64.node and b/src/native/ffmpeg/ffmpegAddon.linux.x64.node differ diff --git a/src/native/ffmpeg/ffmpegAddon.win32.x64.node b/src/native/ffmpeg/ffmpegAddon.win32.x64.node index ba107ef6..17906bab 100644 Binary files a/src/native/ffmpeg/ffmpegAddon.win32.x64.node and b/src/native/ffmpeg/ffmpegAddon.win32.x64.node differ diff --git a/src/native/napi2native/napi2native.darwin.arm64.node b/src/native/napi2native/napi2native.darwin.arm64.node index 0000f553..4807861d 100644 Binary files a/src/native/napi2native/napi2native.darwin.arm64.node and b/src/native/napi2native/napi2native.darwin.arm64.node differ diff --git a/src/native/napi2native/napi2native.linux.x64.node b/src/native/napi2native/napi2native.linux.x64.node index ee81e32b..0e383193 100644 Binary files a/src/native/napi2native/napi2native.linux.x64.node and b/src/native/napi2native/napi2native.linux.x64.node differ diff --git a/src/native/napi2native/napi2native.win32.x64.node b/src/native/napi2native/napi2native.win32.x64.node index 03f2c3f2..47aa330c 100644 Binary files a/src/native/napi2native/napi2native.win32.x64.node and b/src/native/napi2native/napi2native.win32.x64.node differ diff --git a/src/onebot/action/file/GetRecord.ts b/src/onebot/action/file/GetRecord.ts index 7950b1cf..1deedb91 100644 --- a/src/onebot/action/file/GetRecord.ts +++ b/src/onebot/action/file/GetRecord.ts @@ -7,7 +7,7 @@ import { FFmpegService } from '@/common/ffmpeg'; const out_format = ['mp3', 'amr', 'wma', 'm4a', 'spx', 'ogg', 'wav', 'flac']; type Payload = { - out_format: string + out_format: string; } & GetFilePayload; export default class GetRecord extends GetFileBase { @@ -28,8 +28,12 @@ export default class GetRecord extends GetFileBase { try { await fs.access(outputFile); } catch { - await this.decodeFile(inputFile, pcmFile); - await FFmpegService.convertFile(pcmFile, outputFile, payload.out_format); + if (FFmpegService.getAdapterName() === 'FFmpegAddon') { + await FFmpegService.convertFile(inputFile, outputFile, payload.out_format); + } else { + await this.decodeFile(inputFile, pcmFile); + await FFmpegService.convertFile(pcmFile, outputFile, payload.out_format); + } } const base64Data = await fs.readFile(outputFile, { encoding: 'base64' }); res.file = outputFile; diff --git a/src/onebot/action/stream/DownloadFileRecordStream.ts b/src/onebot/action/stream/DownloadFileRecordStream.ts index 4d30481d..d7568f9e 100644 --- a/src/onebot/action/stream/DownloadFileRecordStream.ts +++ b/src/onebot/action/stream/DownloadFileRecordStream.ts @@ -47,8 +47,12 @@ export class DownloadFileRecordStream extends BaseDownloadStream