temp
This commit is contained in:
commit
8bc5ba1892
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
|
||||||
|
videos
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "packages/video-tools"]
|
||||||
|
path = packages/video-tools
|
||||||
|
url = git@git.xiongxiao.me:kevisual/video-tools.git
|
23
package.json
Normal file
23
package.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "@kevisual/batch-asr",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
||||||
|
"license": "MIT",
|
||||||
|
"packageManager": "pnpm@10.12.1",
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@kevisual/types": "^0.0.10",
|
||||||
|
"@kevisual/video-tools": "workspace:*",
|
||||||
|
"@types/node": "^24.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"eventemitter3": "^5.0.1",
|
||||||
|
"natural": "^8.1.0"
|
||||||
|
}
|
||||||
|
}
|
1
packages/video-tools
Submodule
1
packages/video-tools
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 767e436eb8ba3d38bd68e90e18203b039662dce1
|
5512
pnpm-lock.yaml
generated
Normal file
5512
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
pnpm-workspace.yaml
Normal file
6
pnpm-workspace.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
packages:
|
||||||
|
- packages/*
|
||||||
|
|
||||||
|
onlyBuiltDependencies:
|
||||||
|
- esbuild
|
||||||
|
- msw
|
130
src/asr.ts
Normal file
130
src/asr.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { VideoWS, VideoWsResult } from '@kevisual/video-tools/src/asr/provider/funasr/ws.ts';
|
||||||
|
import net from 'node:net';
|
||||||
|
import path from 'node:path';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import natural from 'natural';
|
||||||
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
const videoTestPath = path.join(process.cwd(), 'videos/my_speech_text.wav');
|
||||||
|
const audioTestPath = path.join(process.cwd(), 'videos/test.mp3');
|
||||||
|
const name = 'output-1746007775571.mp3';
|
||||||
|
const videoTestPath2 = path.join(process.cwd(), 'build', name);
|
||||||
|
|
||||||
|
const emitter = new EventEmitter();
|
||||||
|
const url = 'https://funasr.xiongxiao.me';
|
||||||
|
const local = 'wss://192.168.31.220:10095';
|
||||||
|
const ws = new VideoWS({
|
||||||
|
url: url,
|
||||||
|
mode: '2pass',
|
||||||
|
wsOptions: {
|
||||||
|
rejectUnauthorized: false,
|
||||||
|
},
|
||||||
|
emitter,
|
||||||
|
wav_format: 'wav',
|
||||||
|
onConnect: async () => {
|
||||||
|
console.log('WebSocket connected');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
type BatchSenderOptions = {
|
||||||
|
vws: VideoWS;
|
||||||
|
files: string[];
|
||||||
|
matchText?: string;
|
||||||
|
emitter?: EventEmitter;
|
||||||
|
};
|
||||||
|
class BatchSenderFiles {
|
||||||
|
files: string[];
|
||||||
|
vws: VideoWS;
|
||||||
|
emitter: EventEmitter;
|
||||||
|
constructor({ vws, files, matchText, emitter }: BatchSenderOptions) {
|
||||||
|
this.files = files;
|
||||||
|
this.vws = vws;
|
||||||
|
this.emitter = emitter || vws.emitter;
|
||||||
|
}
|
||||||
|
async init() {
|
||||||
|
const isConnected = await this.vws.isConnected();
|
||||||
|
if (!isConnected) {
|
||||||
|
console.error('链接失败:', isConnected);
|
||||||
|
}
|
||||||
|
this.send();
|
||||||
|
}
|
||||||
|
waitOne() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.vws.emitter.once('result', (data) => {
|
||||||
|
resolve(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async checkAudioFile(file: string) {
|
||||||
|
const stats = fs.statSync(file);
|
||||||
|
if (!stats.isFile()) {
|
||||||
|
throw new Error(`File not found: ${file}`);
|
||||||
|
}
|
||||||
|
const ext = path.extname(file).toLowerCase();
|
||||||
|
const validExtensions = ['.wav', '.mp3', '.flac', '.ogg', '.aac'];
|
||||||
|
if (!validExtensions.includes(ext)) {
|
||||||
|
throw new Error(`Invalid file type: ${ext}. Supported types are: ${validExtensions.join(', ')}`);
|
||||||
|
}
|
||||||
|
const fileSize = stats.size;
|
||||||
|
if (fileSize === 0) {
|
||||||
|
throw new Error(`File is empty: ${file}`);
|
||||||
|
}
|
||||||
|
const maxSize = 100 * 1024 * 1024; // 100 MB
|
||||||
|
if (fileSize > maxSize) {
|
||||||
|
throw new Error(`File size exceeds limit: ${fileSize} bytes. Maximum allowed size is ${maxSize} bytes.`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
file,
|
||||||
|
ext,
|
||||||
|
size: fileSize,
|
||||||
|
isValid: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
async send() {
|
||||||
|
const textList: { file: string; text: string }[] = [];
|
||||||
|
for (const file of this.files) {
|
||||||
|
let wav_format = 'wav';
|
||||||
|
try {
|
||||||
|
const ck = await this.checkAudioFile(file);
|
||||||
|
if (ck.ext !== '.wav') {
|
||||||
|
wav_format = ck.ext.replace('.', '');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking file:', error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const data = fs.readFileSync(file);
|
||||||
|
const wait = this.waitOne();
|
||||||
|
await this.vws.sendBuffer(data, { wav_format });
|
||||||
|
await sleep(1000);
|
||||||
|
console.log('File sent:', file);
|
||||||
|
const result: VideoWsResult = (await wait) as any;
|
||||||
|
console.log('Result:', result.text);
|
||||||
|
textList.push({ file, text: result.text });
|
||||||
|
console.log('----------------------');
|
||||||
|
}
|
||||||
|
this.emitter.emit('send-done', textList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const batchSender = new BatchSenderFiles({
|
||||||
|
vws: ws,
|
||||||
|
// files: [audioTestPath],
|
||||||
|
files: [videoTestPath, audioTestPath],
|
||||||
|
});
|
||||||
|
batchSender.init();
|
||||||
|
batchSender.emitter.on('send-done', (data) => {
|
||||||
|
const matchText = '在一无所知中,梦里的一天结束了一个新的轮回,便会开始。';
|
||||||
|
const textList = data as { file: string; text: string }[];
|
||||||
|
for (const item of textList) {
|
||||||
|
const getText = item.text || '';
|
||||||
|
const distance = natural.JaroWinklerDistance(getText, matchText);
|
||||||
|
console.log(`File: ${item.file}, \nText: ${item.text}\nDistance: ${distance}`);
|
||||||
|
}
|
||||||
|
// console.log('Batch processing done:', data);
|
||||||
|
});
|
||||||
|
|
||||||
|
const server = net.createServer((socket) => {
|
||||||
|
socket.on('data', (data) => {
|
||||||
|
console.log('data', data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
server.listen(10096);
|
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": "@kevisual/types/json/backend.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"typeRoots": [
|
||||||
|
"./node_modules/@types",
|
||||||
|
"./node_modules/@kevisual"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*",
|
||||||
|
],
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user