Files
sgxt_web/public/textVideo/textVideo.js
2025-07-16 18:34:49 +08:00

276 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright FunASR (https://github.com/alibaba-damo-academy/FunASR). All Rights
* Reserved. MIT License (https://opensource.org/licenses/MIT)
*/
/* 2022-2023 by zhaoming,mali aihealthx.com */
// 连接; 定义socket连接类对象与语音对象
var wsconnecter = new WebSocketConnectMethod({ msgHandle: getJsonMessage, stateHandle: getConnState });
var audioBlob;
var isfilemode = true; // if it is in file mode
// 录音; 定义录音对象,wav格式
var rec = Recorder({
type: "pcm",
bitRate: 16,
sampleRate: 16000,
onProcess: recProcess
});
var sampleBuf = new Int16Array();
var rec_text = ""; // for online rec asr result
var offline_text = ""; // for offline rec asr result
var file_ext = "";
var file_sample_rate = 16000; //for wav file sample rate
var file_data_array; // array to save file data
var totalsend = 0;
addresschange();
function addresschange() {
var Uri = 'ws://192.168.0.232:10095';
Uri = Uri.replace(/wss/g, "https");
window.open(Uri, '_blank');
}
var readWavInfo = function (bytes) {
//读取wav文件头统一成44字节的头
if (bytes.byteLength < 44) {
return null;
};
var wavView = bytes;
var eq = function (p, s) {
for (var i = 0; i < s.length; i++) {
if (wavView[p + i] != s.charCodeAt(i)) {
return false;
};
};
return true;
};
if (eq(0, "RIFF") && eq(8, "WAVEfmt ")) {
var numCh = wavView[22];
if (wavView[20] == 1 && (numCh == 1 || numCh == 2)) {//raw pcm 单或双声道
var sampleRate = wavView[24] + (wavView[25] << 8) + (wavView[26] << 16) + (wavView[27] << 24);
var bitRate = wavView[34] + (wavView[35] << 8);
var heads = [wavView.subarray(0, 12)], headSize = 12;//head只保留必要的块
//搜索data块的位置
var dataPos = 0; // 44 或有更多块
for (var i = 12, iL = wavView.length - 8; i < iL;) {
if (wavView[i] == 100 && wavView[i + 1] == 97 && wavView[i + 2] == 116 && wavView[i + 3] == 97) {//eq(i,"data")
heads.push(wavView.subarray(i, i + 8));
headSize += 8;
dataPos = i + 8; break;
}
var i0 = i;
i += 4;
i += 4 + wavView[i] + (wavView[i + 1] << 8) + (wavView[i + 2] << 16) + (wavView[i + 3] << 24);
if (i0 == 12) {//fmt
heads.push(wavView.subarray(i0, i));
headSize += i - i0;
}
}
if (dataPos) {
var wavHead = new Uint8Array(headSize);
for (var i = 0, n = 0; i < heads.length; i++) {
wavHead.set(heads[i], n); n += heads[i].length;
}
return {
sampleRate: sampleRate
, bitRate: bitRate
, numChannels: numCh
, wavHead44: wavHead
, dataPos: dataPos
};
};
};
};
return null;
};
function upfileOnchange(files) {
this.files = [files];
var len = this.files.length;
for (let i = 0; i < len; i++) {
let fileAudio = new FileReader();
fileAudio.readAsArrayBuffer(this.files[i]);
file_ext = this.files[i].name.split('.').pop().toLowerCase();
var audioblob;
fileAudio.onload = function () {
audioblob = fileAudio.result;
file_data_array = audioblob;
}
fileAudio.onerror = function (e) {
console.log('error' + e);
}
}
// for wav file, we get the sample rate
if (file_ext == "wav") {
for (let i = 0; i < len; i++) {
let fileAudio = new FileReader();
fileAudio.readAsArrayBuffer(this.files[i]);
fileAudio.onload = function () {
audioblob = new Uint8Array(fileAudio.result);
var info = readWavInfo(audioblob);
file_sample_rate = info.sampleRate;
}
}
}
}
function play_file() {
var audioblob = new Blob([new Uint8Array(file_data_array)], { type: "audio/wav" });
var audio_record = document.getElementById('audio_record');
audio_record.src = (window.URL || webkitURL).createObjectURL(audioblob);
audio_record.controls = true;
}
function start_file_send() {
sampleBuf = new Uint8Array(file_data_array);
var chunk_size = 960; // for asr chunk_size [5, 10, 5]
while (sampleBuf.length >= chunk_size) {
sendBuf = sampleBuf.slice(0, chunk_size);
totalsend = totalsend + sampleBuf.length;
sampleBuf = sampleBuf.slice(chunk_size, sampleBuf.length);
wsconnecter.wsSend(sendBuf);
}
stop();
}
function stop() {
var chunk_size = new Array(5, 10, 5);
var request = {
"chunk_size": chunk_size,
"wav_name": "h5",
"is_speaking": false,
"chunk_interval": 10,
"mode": getAsrMode(),
};
if (sampleBuf.length > 0) {
wsconnecter.wsSend(sampleBuf);
sampleBuf = new Int16Array();
}
wsconnecter.wsSend(JSON.stringify(request));
// 控件状态更新
isRec = false;
if (isfilemode == false) {
//wait 3s for asr result
setTimeout(function () {
wsconnecter.wsStop();
}, 3000);
rec.stop(function (blob, duration) {
var audioBlob = Recorder.pcm2wav(data = { sampleRate: 16000, bitRate: 16, blob: blob },
function (theblob, duration) {
console.log(theblob);
var audio_record = document.getElementById('audio_record');
audio_record.src = (window.URL || webkitURL).createObjectURL(theblob);
audio_record.controls = true;
}, function (msg) {
console.log(msg);
}
);
}, function (errMsg) {
console.log("errMsg: " + errMsg);
});
}
// 停止连接
}
function getAsrMode() {
return 'offline';
}
function getHotwords() {
return null
}
function handleWithTimestamp(tmptext, tmptime) {
if (tmptime == null || tmptime == "undefined" || tmptext.length <= 0) {
return tmptext;
}
tmptext = tmptext.replace(/。|||、|\?|\.|\ /g, ","); // in case there are a lot of "。"
var words = tmptext.split(","); // split to chinese sentence or english words
var jsontime = JSON.parse(tmptime); //JSON.parse(tmptime.replace(/\]\]\[\[/g, "],[")); // in case there are a lot segments by VAD
var char_index = 0; // index for timestamp
var text_withtime = "";
for (var i = 0; i < words.length; i++) {
if (words[i] == "undefined" || words[i].length <= 0) {
continue;
}
if (/^[a-zA-Z]+$/.test(words[i])) { // if it is english
text_withtime = text_withtime + jsontime[char_index][0] / 1000 + ":" + words[i] + "\n";
char_index = char_index + 1; //for english, timestamp unit is about a word
}
else {
text_withtime = text_withtime + jsontime[char_index][0] / 1000 + ":" + words[i] + "\n";
char_index = char_index + words[i].length; //for chinese, timestamp unit is about a char
}
}
return text_withtime;
}
// 语音识别结果; 对jsonMsg数据解析,将识别结果附加到编辑框中
function getJsonMessage(jsonMsg) {
var rectxt = "" + JSON.parse(jsonMsg.data)['text'];
var asrmodel = JSON.parse(jsonMsg.data)['mode'];
var is_final = JSON.parse(jsonMsg.data)['is_final'];
var timestamp = JSON.parse(jsonMsg.data)['timestamp'];
if (asrmodel == "2pass-offline" || asrmodel == "offline") {
offline_text = offline_text + handleWithTimestamp(rectxt, timestamp); //rectxt; //.replace(/ +/g,"");
rec_text = offline_text;
} else {
rec_text = rec_text + rectxt;
}
videoText = rec_text;
if (is_final == true) {
play_file();
wsconnecter.wsStop();
btnConnect.disabled = false;
}
}
// 连接状态响应
function getConnState(connState) {
if (connState === 0) start_file_send();
}
// 识别启动、停止、清空操作
function start() {
var ret = wsconnecter.wsStart();//启动连接
return ret == 1 ? 1 : 0;
}
function recProcess(buffer, powerLevel, bufferDuration, bufferSampleRate, newBufferIdx, asyncEnd) {
if (isRec === true) {
var data_48k = buffer[buffer.length - 1];
var array_48k = new Array(data_48k);
var data_16k = Recorder.SampleData(array_48k, bufferSampleRate, 16000).data;
sampleBuf = Int16Array.from([...sampleBuf, ...data_16k]);
var chunk_size = 960; // for asr chunk_size [5, 10, 5]
while (sampleBuf.length >= chunk_size) {
sendBuf = sampleBuf.slice(0, chunk_size);
sampleBuf = sampleBuf.slice(chunk_size, sampleBuf.length);
wsconnecter.wsSend(sendBuf);
}
}
}
function getUseITN() {
return false;
}