bugfix
This commit is contained in:
parent
76abe0935f
commit
a47d155bf9
188
bricks/audio.js
188
bricks/audio.js
@ -1,4 +1,16 @@
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class AudioPlayer extends JsWidget {
|
||||
/*
|
||||
{
|
||||
@ -35,6 +47,7 @@ class AudioPlayer extends JsWidget {
|
||||
}
|
||||
|
||||
|
||||
this.player.source.src = url;
|
||||
//webkitURL is deprecated but nevertheless
|
||||
var URL = window.URL || window.webkitURL;
|
||||
var AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
@ -44,66 +57,135 @@ class AudioRecorder extends HBox {
|
||||
super(opts);
|
||||
this.start_icon = opts.start_icon || bricks_resource('imgs/start_recording.png');
|
||||
this.stop_icon = opts.stop_icon || bricks_resource('imgs/stop_recording.png');
|
||||
console.log('this.start_icon=', this.start_icon, this.stop_icon);
|
||||
this.gumStream = null; //stream from getUserMedia()
|
||||
this.recorder = null;
|
||||
// shim for AudioContext when it's not avb.
|
||||
this.img = new Image({height:'100%', url:this.start_icon});
|
||||
this.player = new AudioPlayer({});
|
||||
this.player.disabled(true);
|
||||
this.add_widget(this.img);
|
||||
this.add_widget(this.player);
|
||||
this.img.bind('click', this.btn_clicked.bind(this));
|
||||
this.audioContext = null;
|
||||
this.stream = null;
|
||||
this.chunks = [];
|
||||
this.rec = null;
|
||||
this.wave = null;
|
||||
this.recBlob = null;
|
||||
this.recOpen();
|
||||
}
|
||||
on_process(buffers,powerLevel,
|
||||
bufferDuration,bufferSampleRate,
|
||||
newBufferIdx,asyncEnd){
|
||||
//录音实时回调,大约1秒调用12次本回调
|
||||
document.querySelector(".recpowerx").style.width=powerLevel+"%";
|
||||
document.querySelector(".recpowert").innerText=formatMs(bufferDuration,1)+" / "+powerLevel;
|
||||
|
||||
//可视化图形绘制
|
||||
wave.input(buffers[buffers.length-1],powerLevel,bufferSampleRate);
|
||||
}
|
||||
recOpen(){
|
||||
this.rec=null;
|
||||
this.wave=null;
|
||||
this.recBlob=null;
|
||||
var newRec=Recorder({
|
||||
type:"wav",sampleRate:16000,bitRate:16
|
||||
,onProcess:this.on_process.bind(this)
|
||||
}
|
||||
});
|
||||
|
||||
newRec.open(function(){//打开麦克风授权获得相关资源
|
||||
this.rec=newRec;
|
||||
//此处创建这些音频可视化图形绘制浏览器支持妥妥的
|
||||
this.wave=Recorder.FrequencyHistogramView({elem:".recwave"});
|
||||
}.bind(this),function(msg,isUserNotAllow){//用户拒绝未授权或不支持
|
||||
console.log('open recorder failed');
|
||||
});
|
||||
}
|
||||
recClose(){
|
||||
if(this.rec){
|
||||
this.rec.close();
|
||||
}else{
|
||||
console.log('close recorder error');
|
||||
};
|
||||
}
|
||||
start_recording(){
|
||||
console.log("recordButton clicked", this);
|
||||
var constraints = { audio: true, video:false }
|
||||
navigator.mediaDevices.getUserMedia(constraints)
|
||||
.then(function(stream) {
|
||||
console.log("getUserMedia() success, stream created, initializing Recorder.js ...", this);
|
||||
this.img.set_url(this.stop_icon);
|
||||
this.audioContext = new AudioContext();
|
||||
this.gumStream = stream;
|
||||
/* use the stream */
|
||||
try {
|
||||
var input = this.audioContext.createMediaStreamSource(stream);
|
||||
} catch(e){
|
||||
console.log('e====', e);
|
||||
}
|
||||
this.recorder = new Recorder(input,{numChannels:1})
|
||||
this.recorder.record()
|
||||
console.log("Recording started");
|
||||
}.bind(this)).catch(function(err) {
|
||||
//enable the record button if getUserMedia() fails
|
||||
this.img.set_url(this.start_icon);
|
||||
}.bind(this));
|
||||
if(this.rec&&Recorder.IsOpen()){
|
||||
this.recBlob=null;
|
||||
this.rec.start();
|
||||
}else{
|
||||
console.log("ajKR::未打开录音");
|
||||
};
|
||||
}
|
||||
pause_recording(){
|
||||
if(this.rec&&Recorder.IsOpen()){
|
||||
this.rec.pause();
|
||||
}else{
|
||||
console.log("gCAR::未打开录音");
|
||||
};
|
||||
}
|
||||
resume_recording(){
|
||||
if(this.rec&&Recorder.IsOpen()){
|
||||
this.rec.resume();
|
||||
}else{
|
||||
console.log("Ob6S::未打开录音");
|
||||
};
|
||||
}
|
||||
stop_recording(){
|
||||
this.img.set_url(this.start_icon);
|
||||
this.recorder.stop();
|
||||
this.gumStream.getAudioTracks()[0].stop();
|
||||
this.recorder.exportWAV(this.createWAV.bind(this));
|
||||
if(!(this.rec&&Recorder.IsOpen())){
|
||||
console.log("5JuL::未打开录音");
|
||||
return;
|
||||
};
|
||||
this.rec.stop(function(blob,duration){
|
||||
console.log(blob,(window.URL||webkitURL).createObjectURL(blob),Html_xT(Html_$T("gOix::时长:{1}ms",0,duration)));
|
||||
|
||||
this.recBlob=blob;
|
||||
console.log("0LHf::已录制mp3:{1}ms {2}字节,可以点击播放、上传、本地下载了",0,formatMs(duration),blob.size);
|
||||
}.bind(this),function(msg){
|
||||
console.log("kGZO::录音失败:");
|
||||
});
|
||||
}
|
||||
createWAV(blob){
|
||||
console.log('reord stoped .....', this);
|
||||
var url = URL.createObjectURL(blob);
|
||||
this.player.set_source(url);
|
||||
this.player.disabled(false);
|
||||
console.log('---------done------------', url);
|
||||
play_record(){
|
||||
if(!this.recBlob){
|
||||
console.log("tIke::请先录音,然后停止后再播放");
|
||||
return;
|
||||
};
|
||||
var cls=("a"+Math.random()).replace(".","");
|
||||
var audio=document.createElement("audio");
|
||||
audio.controls=true;
|
||||
document.querySelector("."+cls).appendChild(audio);
|
||||
//简单利用URL生成播放地址,注意不用了时需要revokeObjectURL,否则霸占内存
|
||||
audio.src=(window.URL||webkitURL).createObjectURL(recBlob);
|
||||
audio.play();
|
||||
|
||||
setTimeout(function(){
|
||||
(window.URL||webkitURL).revokeObjectURL(audio.src);
|
||||
},5000);
|
||||
}
|
||||
btn_clicked(){
|
||||
if (!this.isRecording){
|
||||
this.img.src = this.stop_icon;
|
||||
this.isRecording = true;
|
||||
this.start_recording();
|
||||
} else {
|
||||
this.img.src = this.start_icon;
|
||||
this.isRecording = false;
|
||||
this.stop_recording();
|
||||
upload(){
|
||||
var blob=this.recBlob;
|
||||
if(!blob){
|
||||
console.log("DUTn::请先录音,然后停止后再上传");
|
||||
return;
|
||||
};
|
||||
var form=new FormData();
|
||||
form.append("audiofile",blob,"recorder.wav");
|
||||
const data = new URLSearchParams();
|
||||
for (const pair of form)) {
|
||||
data.append(pair[0], pair[1]);
|
||||
}
|
||||
hj = HttpJson()
|
||||
ret = await hj.post(this.upload_url,{
|
||||
params:data
|
||||
});
|
||||
console.log('ret=', ret);
|
||||
this.dispatch('updated', ret)
|
||||
}
|
||||
download(){
|
||||
if(!this.recBlob){
|
||||
console.log('recorder not opened');
|
||||
return;
|
||||
};
|
||||
var fileName="recorder-"+Date.now()+".wav";
|
||||
var downA=document.createElement("A");
|
||||
downA.innerHTML="下载")+fileName;
|
||||
downA.href=(window.URL||webkitURL).createObjectURL(this.recBlob);
|
||||
downA.download=fileName;
|
||||
# document.querySelector("."+cls).appendChild(downA);
|
||||
if(/mobile/i.test(navigator.userAgent)){
|
||||
;
|
||||
}
|
||||
downA.click();
|
||||
//不用了时需要revokeObjectURL,否则霸占内存
|
||||
(window.URL||webkitURL).revokeObjectURL(downA.href);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
<link rel="stylesheet" href="/bricks/css/bricks.css">
|
||||
</head>
|
||||
<body>
|
||||
<script src="/3parties/recorder.wav.min.js"></script>
|
||||
<script src="/bricks/bricks.js"></script>
|
||||
<script>
|
||||
const opts = {
|
||||
|
BIN
bricks/imgs/download.png
Normal file
BIN
bricks/imgs/download.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
bricks/imgs/resume-record.png
Normal file
BIN
bricks/imgs/resume-record.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
bricks/imgs/stop.png
Normal file
BIN
bricks/imgs/stop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
bricks/imgs/upload.png
Normal file
BIN
bricks/imgs/upload.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -40,15 +40,17 @@ class HttpText {
|
||||
add_own_params(params){
|
||||
if (! params)
|
||||
params = {};
|
||||
var session = bricks_app.get_session();
|
||||
if (params instanceof FormData){
|
||||
for ( const [key, value] of Object.entries(this.params)){
|
||||
params.append(key, value);
|
||||
}
|
||||
if(session){
|
||||
params.append('session', session);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
else {
|
||||
params = Object.assign(this.params, params);
|
||||
}
|
||||
var session = bricks_app.get_session();
|
||||
params = Object.assign(this.params, params);
|
||||
if (session){
|
||||
extend(params,{session:session});
|
||||
}
|
||||
@ -60,7 +62,6 @@ class HttpText {
|
||||
}
|
||||
return Object.assign(this.headers, headers);
|
||||
}
|
||||
|
||||
async httpcall(url, {method='GET', headers=null, params=null}={}){
|
||||
url = this.url_parse(url);
|
||||
var data = this.add_own_params(params);
|
||||
@ -93,8 +94,6 @@ class HttpText {
|
||||
if (fetchResult.status == 401 && bricks_app.login_url){
|
||||
return await this.withLoginInfo(url, _params);
|
||||
}
|
||||
console.log('method=', method, 'url=', url, 'params=', params);
|
||||
console.log('jsoncall error:');
|
||||
const resp_error = {
|
||||
"type":"Error",
|
||||
"message":result.message || 'Something went wrong',
|
||||
|
Loading…
Reference in New Issue
Block a user