mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-16 13:01:14 +00:00
Merge branch 'main' into refactor-config-webui
This commit is contained in:
commit
046afc0c23
@ -49,9 +49,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^5.0.0",
|
"express": "^5.0.0",
|
||||||
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
|
"qrcode-terminal": "^0.12.0",
|
||||||
"silk-wasm": "^3.6.1",
|
"silk-wasm": "^3.6.1",
|
||||||
"ws": "^8.18.0",
|
"ws": "^8.18.0",
|
||||||
"qrcode-terminal": "^0.12.0",
|
"piscina": "^4.7.0"
|
||||||
"fluent-ffmpeg": "^2.1.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
src/common/audio-worker.ts
Normal file
9
src/common/audio-worker.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { encode } from "silk-wasm";
|
||||||
|
|
||||||
|
export interface EncodeArgs {
|
||||||
|
input: ArrayBufferView | ArrayBuffer
|
||||||
|
sampleRate: number
|
||||||
|
}
|
||||||
|
export default async ({ input, sampleRate }: EncodeArgs) => {
|
||||||
|
return await encode(input, sampleRate);
|
||||||
|
};
|
@ -1,13 +1,19 @@
|
|||||||
|
import Piscina from 'piscina';
|
||||||
import fsPromise from 'fs/promises';
|
import fsPromise from 'fs/promises';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
import { spawn } from 'node:child_process';
|
import { spawn } from 'node:child_process';
|
||||||
import { encode, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
|
import { EncodeResult, getDuration, getWavFileInfo, isSilk, isWav } from 'silk-wasm';
|
||||||
import { LogWrapper } from './log';
|
import { LogWrapper } from './log';
|
||||||
|
import { EncodeArgs } from "@/common/audio-worker";
|
||||||
|
|
||||||
const ALLOW_SAMPLE_RATE = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
|
const ALLOW_SAMPLE_RATE = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
|
||||||
const EXIT_CODES = [0, 255];
|
const EXIT_CODES = [0, 255];
|
||||||
const FFMPEG_PATH = process.env.FFMPEG_PATH || 'ffmpeg';
|
const FFMPEG_PATH = process.env.FFMPEG_PATH ?? 'ffmpeg';
|
||||||
|
|
||||||
|
const piscina = new Piscina<EncodeArgs, EncodeResult>({
|
||||||
|
filename: new URL('./audio-worker.mjs', import.meta.url).href,
|
||||||
|
});
|
||||||
|
|
||||||
async function guessDuration(pttPath: string, logger: LogWrapper) {
|
async function guessDuration(pttPath: string, logger: LogWrapper) {
|
||||||
const pttFileInfo = await fsPromise.stat(pttPath);
|
const pttFileInfo = await fsPromise.stat(pttPath);
|
||||||
@ -41,8 +47,11 @@ async function convert(filePath: string, pcmPath: string, logger: LogWrapper): P
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleWavFile(
|
async function handleWavFile(
|
||||||
file: Buffer, filePath: string, pcmPath: string, logger: LogWrapper
|
file: Buffer,
|
||||||
): Promise<{input: Buffer, sampleRate: number}> {
|
filePath: string,
|
||||||
|
pcmPath: string,
|
||||||
|
logger: LogWrapper
|
||||||
|
): 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 convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
return { input: await convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
||||||
@ -60,8 +69,8 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
|||||||
const { input, sampleRate } = isWav(file)
|
const { input, sampleRate } = isWav(file)
|
||||||
? (await handleWavFile(file, filePath, pcmPath, logger))
|
? (await handleWavFile(file, filePath, pcmPath, logger))
|
||||||
: { input: await convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
: { input: await convert(filePath, pcmPath, logger), sampleRate: 24000 };
|
||||||
const silk = await encode(input, sampleRate);
|
const silk = await piscina.run({ input: input, sampleRate: sampleRate });
|
||||||
await fsPromise.writeFile(pttPath, silk.data);
|
await fsPromise.writeFile(pttPath, Buffer.from(silk.data));
|
||||||
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
logger.log(`语音文件${filePath}转换成功!`, pttPath, '时长:', silk.duration);
|
||||||
return {
|
return {
|
||||||
converted: true,
|
converted: true,
|
||||||
@ -86,4 +95,4 @@ export async function encodeSilk(filePath: string, TEMP_DIR: string, logger: Log
|
|||||||
logger.logError.bind(logger)('convert silk failed', error.stack);
|
logger.logError.bind(logger)('convert silk failed', error.stack);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,14 @@ import { defineConfig, PluginOption, UserConfig } from 'vite';
|
|||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
import nodeResolve from '@rollup/plugin-node-resolve';
|
import nodeResolve from '@rollup/plugin-node-resolve';
|
||||||
import { builtinModules } from 'module';
|
import { builtinModules } from 'module';
|
||||||
//依赖排除
|
|
||||||
const external = ['silk-wasm', 'ws', 'express', 'qrcode-terminal', 'fluent-ffmpeg'];
|
const external = ['silk-wasm', 'ws', 'express', 'qrcode-terminal', 'fluent-ffmpeg', 'piscina'];
|
||||||
const nodeModules = [...builtinModules, builtinModules.map((m) => `node:${m}`)].flat();
|
const nodeModules = [...builtinModules, builtinModules.map(m => `node:${m}`)].flat();
|
||||||
|
|
||||||
function genCpModule(module: string) {
|
function genCpModule(module: string) {
|
||||||
return { src: `./node_modules/${module}`, dest: `dist/node_modules/${module}`, flatten: false };
|
return { src: `./node_modules/${module}`, dest: `dist/node_modules/${module}`, flatten: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
let startScripts: string[] | undefined = undefined;
|
let startScripts: string[] | undefined = undefined;
|
||||||
if (process.env.NAPCAT_BUILDSYS == 'linux') {
|
if (process.env.NAPCAT_BUILDSYS == 'linux') {
|
||||||
startScripts = [];
|
startScripts = [];
|
||||||
@ -17,6 +19,7 @@ if (process.env.NAPCAT_BUILDSYS == 'linux') {
|
|||||||
} else {
|
} else {
|
||||||
startScripts = ['./script/KillQQ.bat'];
|
startScripts = ['./script/KillQQ.bat'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const FrameworkBaseConfigPlugin: PluginOption[] = [
|
const FrameworkBaseConfigPlugin: PluginOption[] = [
|
||||||
cp({
|
cp({
|
||||||
targets: [
|
targets: [
|
||||||
@ -60,18 +63,18 @@ const ShellBaseConfig = () =>
|
|||||||
'./lib-cov/fluent-ffmpeg': './lib/fluent-ffmpeg',
|
'./lib-cov/fluent-ffmpeg': './lib/fluent-ffmpeg',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
build: {
|
},
|
||||||
sourcemap: false,
|
build: {
|
||||||
target: 'esnext',
|
sourcemap: false,
|
||||||
minify: false,
|
target: 'esnext',
|
||||||
lib: {
|
minify: false,
|
||||||
entry: 'src/shell/napcat.ts',
|
lib: {
|
||||||
formats: ['es'],
|
entry: {
|
||||||
fileName: () => 'napcat.mjs',
|
'napcat': 'src/shell/napcat.ts',
|
||||||
},
|
'audio-worker': 'src/common/audio-worker.ts',
|
||||||
rollupOptions: {
|
|
||||||
external: [...nodeModules, ...external],
|
|
||||||
},
|
},
|
||||||
|
formats: ['es'],
|
||||||
|
fileName: (_, entryName) => `${entryName}.mjs`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -85,18 +88,18 @@ const FrameworkBaseConfig = () =>
|
|||||||
'./lib-cov/fluent-ffmpeg': './lib/fluent-ffmpeg',
|
'./lib-cov/fluent-ffmpeg': './lib/fluent-ffmpeg',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
build: {
|
},
|
||||||
sourcemap: false,
|
build: {
|
||||||
target: 'esnext',
|
sourcemap: false,
|
||||||
minify: false,
|
target: 'esnext',
|
||||||
lib: {
|
minify: false,
|
||||||
entry: 'src/framework/napcat.ts',
|
lib: {
|
||||||
formats: ['es'],
|
entry: {
|
||||||
fileName: () => 'napcat.mjs',
|
'napcat': 'src/framework/napcat.ts',
|
||||||
},
|
'audio-worker': 'src/common/audio-worker.ts',
|
||||||
rollupOptions: {
|
|
||||||
external: [...nodeModules, ...external],
|
|
||||||
},
|
},
|
||||||
|
formats: ['es'],
|
||||||
|
fileName: (_, entryName) => `${entryName}.mjs`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user