var begin = document.getElementsByClassName('start-button');
var wsUrl = 'wss://ws-rtasr.hivoice.cn/v1/ws';
var wstime = '1626325549809'
var appkey = '45gn7md5n44aak7a57rdjud3b5l4xdgv75saomys'
var sign = 'EE1CB17678086F0ED8F83B22B31444045206138E6A67FDCE9331BF91B291F344'
var ws = null;
var record = null;
var str = '';
var state = 'STOPING';
var fixedArr = [];
var fixedNum = -1;
var flag = false;
var SubTxt = [];
var timer;
localStorage.setItem('SubTxt',JSON.stringify(SubTxt))
function init(rec) {
record = rec;
}
var Recorder = function (stream) {
var sampleBits = 16;
var sampleRate = 16000;
var context = new AudioContext();
var audioInput = context.createMediaStreamSource(stream);
var recorder = context.createScriptProcessor(4096, 1, 1);
var audioData = {
size: 0,
buffer: [],
inputSampleRate: 48000,
inputSampleBits: 16,
outputSampleRate: sampleRate,
oututSampleBits: sampleBits,
clear: function () {
this.buffer = [];
this.size = 0;
},
input: function (data) {
this.buffer.push(new Float32Array(data));
this.size += data.length;
},
compress: function () {
var data = new Float32Array(this.size);
var offset = 0;
for (var i = 0; i < this.buffer.length; i++) {
data.set(this.buffer[i], offset);
offset += this.buffer[i].length;
}
var compression = parseInt(this.inputSampleRate / this.outputSampleRate);
var length = data.length / compression;
var result = new Float32Array(length);
var index = 0,
j = 0;
while (index < length) {
result[index] = data[j];
j += compression;
index++;
}
return result;
},
encodePCM: function () {
var sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate);
var sampleBits = Math.min(this.inputSampleBits, this.oututSampleBits);
var bytes = this.compress();
var dataLength = bytes.length * (sampleBits / 8);
var buffer = new ArrayBuffer(dataLength);
var data = new DataView(buffer);
var offset = 0;
for (var i = 0; i < bytes.length; i++, offset += 2) {
var s = Math.max(-1, Math.min(1, bytes[i]));
data.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
}
return new Blob([data]);
}
};
var sendData = function () {
var reader = new FileReader();
reader.onload = e => {
var outbuffer = e.target.result;
ws.send(outbuffer);
ws.send(JSON.stringify({
"type": "heartbeat"
}));
};
reader.readAsArrayBuffer(audioData.encodePCM());
audioData.clear();
};
this.start = function () {
audioInput.connect(recorder);
recorder.connect(context.destination);
}
this.stop = function () {
recorder.disconnect();
}
this.getBlob = function () {
return audioData.encodePCM();
}
this.clear = function () {
audioData.clear();
}
recorder.onaudioprocess = function (e) {
var inputBuffer = e.inputBuffer.getChannelData(0);
audioData.input(inputBuffer);
sendData();
}
}
function useWebSocket() {
ws = new WebSocket(`ws://59.110.116.36/v1/ws?time=1642471777442&appkey=45gn7md5n44aak7a57rdjud3b5l4xdgv75saomys&sign=D54B7D7AFE27A7DC7CE389AF8E232B502C1F9326BBE34C1F51B42AB03679F32D`);
ws.binaryType = 'arraybuffer';
ws.onopen = function () {
console.log('握手成功');
ws.send(JSON.stringify({
"type": "start",
"data": {
"domain":"general",
"sample": "16k",
"lang": "cn",
"punctuation": "true",
"post_proc": "true",
"server_vad": "true",
"max_start_silence": "5000",
"max_end_silence": "500",
"user_id": "userid"
}
}))
if (ws.readyState == 1) {
record.start();
}
};
ws.onmessage = function (msg) {
let data = JSON.parse(msg.data);
if (data.type == 'fixed') {
fixedArr.push(data.text)
str += data.text;
$("#result_output").html(str);
}else{
$("#result_output").html(str+data.text);
}
if (data.end == true && data.code ==0) {
ws.close();
record.stop();
}
console.log(str);
}
ws.onerror = function (err) {
console.info(err)
}
}
$('.start-button').click(function () {
if (state === 'STOPING') {
$('.start-button').text('结束识别')
state = 'STARTING'
}else{
$('.start-button').text('开始识别')
state = 'STOPING'
if (ws) {
ws.send(JSON.stringify({
"type": "end"
}))
}
record.stop();
return;
}
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
if (!navigator.getUserMedia) {
alert('浏览器不支持音频输入');
} else {
navigator.getUserMedia({
audio: true
},
function (mediaStream) {
init(new Recorder(mediaStream));
console.log('开始对讲');
useWebSocket();
},
function (error) {
console.log(error);
switch (error.message || error.name) {
case 'PERMISSION_DENIED':
case 'PermissionDeniedError':
console.info('用户拒绝提供信息。');
break;
case 'NOT_SUPPORTED_ERROR':
case 'NotSupportedError':
console.info('浏览器不支持硬件设备。');
break;
case 'MANDATORY_UNSATISFIED_ERROR':
case 'MandatoryUnsatisfiedError':
console.info('无法发现指定的硬件设备。');
break;
default:
console.info('无法打开麦克风。异常信息:' + (error.code || error.name));
break;
}
}
)
}
})
function sent_confirm(){
if (flag) {
return ;
}
if ($("#first_sent").val()!='') {
if (fixedNum>=fixedArr.length) {
return;
}
let p_sent = document.createElement('p');
p_sent.innerText=$("#first_sent").val();
document.getElementById("recordingslist").appendChild(p_sent);
SubTxt.push($("#first_sent").val())
localStorage.setItem('SubTxt',JSON.stringify(SubTxt))
$("#recordingslist").scrollTop($("#recordingslist")[0].scrollHeight)
$("#first_sent").val('')
$('.confirm').val('获取');
return;
}else{
if (fixedNum<=fixedArr.length-2) {
fixedNum++;
}else{
return;
}
$("#first_sent").val(fixedArr[fixedNum]);
str = str.replace('<strong style="color:yellow">','')
str = str.replace('</strong>','')
let p = $("#first_sent").val()
let newp = '<strong style="color:yellow">' +$("#first_sent").val()+'</strong>'
var reg = new RegExp("(.*)"+p,"g");
str = str.replace(reg,`$1${newp}`)
console.log(str);
$("#result_output").html(str);
$('.confirm').val('提交');
}
}
function cheakboxbtn() {
if (!flag){
flag = true;
if ($("#first_sent").val()!='') {
let p_sent = document.createElement('p');
p_sent.innerText=$("#first_sent").val();
document.getElementById("recordingslist").appendChild(p_sent);
SubTxt.push($("#first_sent").val())
localStorage.setItem('SubTxt',JSON.stringify(SubTxt))
$("#recordingslist").scrollTop($("#recordingslist")[0].scrollHeight)
$("#first_sent").val('')
}
timer = setInterval(() => {
if (fixedNum<fixedArr.length-1){
fixedNum++;
let p_sent = document.createElement('p');
p_sent.innerText=fixedArr[fixedNum];
document.getElementById("recordingslist").appendChild(p_sent);
SubTxt.push(fixedArr[fixedNum])
localStorage.setItem('SubTxt',JSON.stringify(SubTxt))
$("#recordingslist").scrollTop($("#recordingslist")[0].scrollHeight)
}
}, 1000);
}
else {
flag = false;
clearInterval(timer)
}
}
function sent_restore(){
if ($("#first_sent").val()!='') {
$("#first_sent").val(fixedArr[fixedNum]);
}
}
function sent_clear(){
$("#recordingslist").html('');
}
function wordgen(){
console.log(123132);
$("#recordingslist").wordExport("会议记录");
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link href="index.css" type="text/css" rel="stylesheet">
<link rel="stylesheet" href="./css/bootstrap.min.css">
<link rel="stylesheet" href="./css/meeting.css">
<link rel="stylesheet" href="./css/voicedictation.css">
<link rel="stylesheet" href="./css/reset.css">
</head>
<body>
<div>
</div>
<div class="container">
<div class="demoBody">
<div class="lBody">
<div class="lTitle">
<i></i>
<p>会议内容分段修改</p>
<a class="conference" href="conference.html" target="_blank">会议记录</a>
</div>
<div class="lMessage">
<div class="lDetail">
<div class="lDetail-content"><textarea name="" id="first_sent" class="record" cols="" rows=""></textarea></div>
<div class="lMessage-bottom">
<div >
<label for="u3_input"></label>
<input id="u3_input" type="checkbox" value="checkbox" onclick='cheakboxbtn()'/>自动确认
</div>
<div class="divRight2" >
<input class="btn2 confirm" onclick="sent_confirm()" type="button" value="获取"/>
<input class="btn2" onclick="sent_restore()" type="button" value="恢复"/>
</div>
</div>
</div>
<div class="lDetail lDetail2">
<div class="lDetail2-title"><span class="buttomTitle">会议实时语音转换:</span></div>
<div class="lDetail2-content"><div name="" id="result_output" class="record record2" style="height:300px;overflow-y:auto" disabled="disabled"></div> </div>
<div class="lDetail2-bottom">
<div class="service-item service-item-taste">
<div class="service-item-content service-item-taste-content">
<div class="start-taste flex-display-1">
<div class="start-taste-left">
<div class="start-taste-button">
<button class="taste-button start-button">开始识别</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="rBody">
<div class="rTitle">
<i></i>
<p>会议记录</p>
</div>
<div class="lMessage lMessage-right" id="recordingslist" style="line-height:26px">
</div>
<div class="button-group-right">
<button id="btn_start" class="btn" onclick="wordgen()">生成word文档</button>
<button id="btn_clear" class="btn" onclick="sent_clear()">清除</button>
</div>
</div>
</div>
</div>
<script src="jquery.js"></script>
<script src="hmac-sha256.js"></script>
<script src="enc-base64-min.js"></script>
<script type="text/javascript" src="./js/FileSaver.js"></script>
<script type="text/javascript" src="./js/jquery.wordexport.js"></script>
<script src="index1.js"></script>
</body>
</html>