GateWay/public/web/voice_copy.html

404 lines
12 KiB
HTML
Raw Permalink Normal View History

2024-11-13 11:26:59 +08:00
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="js/webView.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title reclang="XvFp">远程喊话</title>
<link rel="stylesheet" href="./css/voice_style.css">
<script>
var PageLM = "2023-12-08 20:41";
</script>
</head>
<body>
<script src="js/recorder.core.js"></script>
<script src="js/mp3.js"></script>
<script src="js/mp3-engine.js"></script>
<script src="js/MQTT_port.js"></script>
<script src="js/jquery-3.4.1.min.js"></script>
<!-- 【2】构建界面 Build the web interface -->
<div class="content">
<div class="record-container">
<button class="break_btn" onclick="return_function()">返回</button>
<div id="record-popup" class="record-popup" style="display: none;">
<!-- 录音动效和提示信息 -->
<div id="recording-animation" style="display: none;">录音中...</div>
<div id="cancel-tip" style="display: none;">松手发送</div>
</div>
<div id="voice-wave-animation" class="voice-line-wrap" style="display: none;">
<div class="voice-line"></div>
<div class="voice-line"></div>
<div class="voice-line"></div>
<div class="voice-line"></div>
<div class="voice-line"></div>
<div class="voice-line"></div>
<div class="voice-line"></div>
</div>
<div class="voice-btn-wrap">
<button id="record-btn">喊话</button>
</div>
<audio id="audio-playback" controls style="display: none;"></audio>
</div>
</div>
<!-- 【3】实现录音逻辑 Implement recording logic -->
<script>
document.getElementById('record-btn').addEventListener('mousedown', recStart);
document.getElementById('record-btn').addEventListener('mouseup', recStop);
document.getElementById('record-btn').addEventListener("touchstart", recStart); // 移动端
document.getElementById('record-btn').addEventListener("touchend", recStop); // 移动端
//-----------------------------------------------------------------------//
var voice_reply_parse_fun;
function return_function() {
//location.href='screen_main.html';
window.history.go(-1);
}
function voice_reply_parse(json_str) {
let json = jQuery.parseJSON(json_str);
if ("sound_card" in json) {
switch (json.sound_card.state || json.sound_card.on_state) {
case "succeed":
console.log("---succeed---");
break;
case "playing":
console.log("---playing---");
break;
case "downloadin":
console.log("---downloadin---");
break;
}
}
}
voice_reply_parse_fun = voice_reply_parse;
function send_voice_function(url, interrupt) {
var send_json = {};
send_json.board_id=103;
send_json.online_play = new Object();
send_json.online_play.url = url;
if (interrupt) {
send_json.interrupt = interrupt;
}
var str = JSON.stringify(send_json);
console.log(str);
MQTT_json_send(str, "sound_card");
}
//-----------------------------------------------------------------------//
var rec, recBlob;
/**调用open打开录音请求好录音权限 Call open to open the recording and request the recording permission**/
function recOpen() {
//一般在显示出录音按钮或相关的录音界面时进行此方法调用,后面用户点击开始录音时就能畅通无阻了
rec = null;
recBlob = null;
var newRec = Recorder({
type: "mp3",
sampleRate: 16000,
bitRate: 16, //mp3格式指定采样率hz、比特率kbps其他参数使用默认配置注意是数字的参数必须提供数字不要用字符串需要使用的type类型需提前把格式支持文件加载进来比如使用wav格式需要提前加载wav.js编码引擎
onProcess: function (
buffers,
powerLevel,
bufferDuration,
bufferSampleRate,
newBufferIdx,
asyncEnd
) {
//录音实时回调大约1秒调用12次本回调
// document.querySelector(".recpowerx").style.width=powerLevel+"%";
// document.querySelector(".recpowert").innerText=formatMs(bufferDuration,1)+" / "+powerLevel;
},
});
newRec.open(
function () {
//打开麦克风授权获得相关资源
rec = newRec;
},
function (msg, isUserNotAllow) {
//用户拒绝未授权或不支持
}
);
}
/**关闭录音,释放资源 Close recording, release resources**/
function recClose() {
if (rec) {
rec.close();
reclog(Html_$T("jqOs::已关闭"));
} else {
reclog(Html_$T("VOOw::未打开录音"), 1);
}
}
/**开始录音 Start recording**/
function recStart() {
// this.preventDefault();
//打开了录音后才能进行start、stop调用
if (rec && Recorder.IsOpen()) {
recBlob = null;
rec.start();
document.getElementById('voice-wave-animation').style.display = 'flex';
// 显示录音动效
document.getElementById('record-popup').style.display = 'block';
document.getElementById('recording-animation').style.display = 'block';
document.getElementById('cancel-tip').style.display = 'block';
} else {
}
}
/**结束录音,得到音频文件 Stop recording and get audio files**/
function recStop() {
if (!(rec && Recorder.IsOpen())) {
return;
}
rec.stop(
function (blob, duration) {
recBlob = blob;
let playAudio = document.getElementById("audio-playback");
// 将音频 URL 赋值给第二个 audio 元素
playAudio.src = (window.URL || webkitURL).createObjectURL(recBlob);
// send_voice_function(playAudio.src, 0);
// playAudio.play();
document.getElementById('voice-wave-animation').style.display = 'none';
document.getElementById('record-popup').style.display = 'none';
// 隐藏录音动效
document.getElementById('recording-animation').style.display = 'none';
document.getElementById('audio-playback').style.display = 'block';
recUpload();
},
function (msg) { }
);
}
/**播放 Play**/
function recPlay() {
if (!recBlob) {
reclog(Html_$T("tIke::请先录音,然后停止后再播放"), 1);
return;
}
let playAudio = document.getElementById("audioPlay");
// 将音频 URL 赋值给第二个 audio 元素
playAudio.src = (window.URL || webkitURL).createObjectURL(recBlob);
// send_voice_function(playAudio.src, 0);
playAudio.play();
setTimeout(function () {
(window.URL || webkitURL).revokeObjectURL(audio.src);
}, 5000);
}
function getQueryString(name) {
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
let r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(decodeURI(r[2]));
return null;
}
/**上传 Upload**/
function recUpload() {
var blob = recBlob;
if (!blob) {
reclog(Html_$T("DUTn::请先录音,然后停止后再上传"), 1);
return;
}
// 创建 FormData 对象
let formData = new FormData();
// 将 Blob 对象添加到 FormData 中,假设字段名为 'audioFile'
formData.append("file", blob, "recording.mp3");
// 发送 POST 请求到服务器
fetch("http://iot.pcpnb.cn/prod-api/iot/tool/upload", {
method: "POST",
headers: {
Authorization: localStorage.getItem('token'),
},
body: formData,
})
.then((response) => {
console.log(response);
if (response.ok) {
return response.json(); // 或者 response.text() 如果服务器返回的是文本
}
throw new Error("Network response was not ok.");
})
.then((data) => {
console.log("Success:", data);
// 处理服务器返回的数据
send_voice_function("http://iot.pcpnb.cn/prod-api" + data.fileName, 99);
})
.catch((error) => {
console.error("Error:", error);
});
}
/**本地下载 Local download**/
function recLocalDown() {
if (!recBlob) {
reclog(Html_$T("M86h::请先录音,然后停止后再下载"), 1);
return;
}
var cls = ("a" + Math.random()).replace(".", "");
recdown64.lastCls = cls;
reclog(
Html_$T("vJPl::点击 ") +
'<span class="' +
cls +
'"></span>' +
Html_$T("Whtc:: 下载,或复制文本") +
"<button onclick=\"recdown64('" +
cls +
"')\">" +
Html_$T("XK4l::生成Base64文本") +
'</button><span class="' +
cls +
'_b64"></span>'
);
var fileName = "recorder-" + Date.now() + ".mp3";
var downA = document.createElement("A");
downA.innerHTML = Html_$T("g8Fy::下载 ") + fileName;
downA.href = (window.URL || webkitURL).createObjectURL(recBlob);
downA.download = fileName;
document.querySelector("." + cls).appendChild(downA);
if (/mobile/i.test(navigator.userAgent)) {
alert(
Html_xT(
Html_$T(
"DIEK::因移动端绝大部分国产浏览器未适配Blob Url的下载所以本demo代码在移动端未调用downA.click()。请尝试点击日志中显示的下载链接下载"
)
)
);
} else {
downA.click();
}
//不用了时需要revokeObjectURL否则霸占内存
//(window.URL||webkitURL).revokeObjectURL(downA.href);
}
function recdown64(cls) {
var el = document.querySelector("." + cls + "_b64");
if (recdown64.lastCls != cls) {
el.innerHTML =
'<span style="color:red">' +
Html_$T("eKKx::老的数据没有保存,只支持最新的一条") +
"</span>";
return;
}
var reader = new FileReader();
reader.onloadend = function () {
el.innerHTML = "<textarea></textarea>";
el.querySelector("textarea").value = reader.result;
};
reader.readAsDataURL(recBlob);
}
var formatMs = function (ms, all) {
var ss = ms % 1000;
ms = (ms - ss) / 1000;
var s = ms % 60;
ms = (ms - s) / 60;
var m = ms % 60;
ms = (ms - m) / 60;
var h = ms;
var t =
(h ? h + ":" : "") +
(all || h + m ? ("0" + m).substr(-2) + ":" : "") +
(all || h + m + s ? ("0" + s).substr(-2) + "″" : "") +
("00" + ss).substr(-3);
return t;
};
recOpen();
</script>
<!--以下这坨可以忽略 The following can be ignored-->
<script>
function reclog(s, color) { }
function Html_$T(s) {
return s;
}
</script>
<style>
body {
word-wrap: break-word;
background: #f5f5f5 center top no-repeat;
background-size: auto 680px;
}
pre {
white-space: pre-wrap;
}
a {
text-decoration: none;
color: #06c;
}
a:hover {
color: #f00;
}
.main {
max-width: 700px;
margin: 0 auto;
padding-bottom: 80px;
}
.mainBox {
margin-top: 12px;
padding: 12px;
border-radius: 6px;
background: #fff;
--border: 1px solid #f60;
box-shadow: 2px 2px 3px #aaa;
}
.btns button {
display: inline-block;
cursor: pointer;
border: none;
border-radius: 3px;
background: #f60;
color: #fff;
padding: 0 15px;
margin: 3px 20px 3px 0;
line-height: 36px;
height: 36px;
overflow: hidden;
vertical-align: middle;
}
.btns button:active {
background: #f00;
}
.pd {
padding: 0 0 6px 0;
}
.lb {
display: inline-block;
vertical-align: middle;
background: #00940e;
color: #fff;
font-size: 14px;
padding: 2px 8px;
border-radius: 99px;
}
.voice-btn-wrap button {
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
</style>
</body>
</html>