262 lines
6.3 KiB
JavaScript
Executable File
262 lines
6.3 KiB
JavaScript
Executable File
var bricks = window.bricks || {};
|
||
|
||
bricks.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;
|
||
};
|
||
|
||
bricks.AudioPlayer = class extends bricks.JsWidget {
|
||
/*
|
||
{
|
||
url:
|
||
autoplay:
|
||
}
|
||
*/
|
||
|
||
constructor(options){
|
||
super(options);
|
||
this.url = options.url;
|
||
this.audio = this._create('audio');
|
||
this.audio.controls = true;
|
||
if (this.opts.autoplay){
|
||
this.audio.addEventListener('canplay', this.play_audio.bind(this));
|
||
}
|
||
this.audio.style.width = "100%"
|
||
this.source = this._create('source');
|
||
this.source.src = this.opts.url;
|
||
this.audio.appendChild(this.source);
|
||
this.dom_element.appendChild(this.audio);
|
||
}
|
||
set_source(url){
|
||
this.audio.src = url;
|
||
bricks.debug(this.audio.src,' new src seted');
|
||
}
|
||
play(){
|
||
this.audio.play();
|
||
}
|
||
toggle_play(){
|
||
if (this.audio.paused){
|
||
this.audio.play();
|
||
} else {
|
||
this.audio.pause();
|
||
}
|
||
}
|
||
set_url(url){
|
||
this.set_source(url);
|
||
}
|
||
}
|
||
|
||
|
||
bricks.AudioRecorder = class extends bricks.HBox {
|
||
/*
|
||
{
|
||
"upload_url":
|
||
"icon_rate":
|
||
}
|
||
we need this module:
|
||
https://gitee.com/xiangyuecn/Recorder
|
||
events:
|
||
record_started
|
||
record_ended
|
||
realtime record wave show need a another package
|
||
we only use the wav file format
|
||
*/
|
||
constructor(opts){
|
||
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');
|
||
this.rec_btn = new bricks.Icon({
|
||
dynsize:true,
|
||
url:this.start_icon,
|
||
rate:this.icon_rate
|
||
});
|
||
// this.player = new bricks.AudioPlayer({url:"",width:'80px'});
|
||
this.rec_time = new bricks.Text({
|
||
text:" record time",
|
||
i18n:false,
|
||
dynsize:true,
|
||
wrap:false,
|
||
width:'120px'
|
||
});
|
||
this.upload_url = opts.upload_url;
|
||
this.rec_btn.bind('click', this.rec_btn_pressed.bind(this))
|
||
this.URL = window.URL||webkitURL;
|
||
this.rec = null;
|
||
this.wave = null;
|
||
this.mic_opened = false;
|
||
this.add_widget(this.rec_btn);
|
||
this.add_widget(this.rec_time);
|
||
this.recordData = null;
|
||
this.bind('record_ended', this.upload.bind(this));
|
||
}
|
||
rec_btn_pressed(){
|
||
bricks.debug(this.rec_btn.url, ':url:', this.start_icon, this.stop_icon);
|
||
if(this.rec_btn.url == this.start_icon){
|
||
this.rec_btn.set_url(this.stop_icon);
|
||
this.start_recording();
|
||
} else {
|
||
this.rec_btn.set_url(this.start_icon);
|
||
this.stop_recording();
|
||
}
|
||
}
|
||
on_process(buffers,powerLevel,
|
||
bufferDuration,bufferSampleRate,
|
||
newBufferIdx,asyncEnd){
|
||
//录音实时回调,大约1秒调用12次本回调
|
||
// document.querySelector(".recpowerx").style.width=powerLevel+"%";
|
||
//可视化图形绘制
|
||
// wave.input(buffers[buffers.length-1],powerLevel,bufferSampleRate);
|
||
this.rec_time.set_text(' ' + bricks.formatMs(bufferDuration,1));
|
||
|
||
}
|
||
recOpen(){
|
||
this.rec=null;
|
||
this.wave=null;
|
||
var newRec = Recorder({
|
||
type:"wav",sampleRate:16000,bitRate:16
|
||
,onProcess:this.on_process.bind(this)
|
||
});
|
||
|
||
newRec.open(function(){//打开麦克风授权获得相关资源
|
||
this.mic_opened = true;
|
||
this.rec=newRec;
|
||
this.rec.start();
|
||
this.dispatch('record_started');
|
||
//此处创建这些音频可视化图形绘制浏览器支持妥妥的
|
||
//this.wave=Recorder.FrequencyHistogramView({elem:".recwave"});
|
||
}.bind(this),function(msg,isUserNotAllow){//用户拒绝未授权或不支持
|
||
bricks.debug('open recorder failed');
|
||
});
|
||
}
|
||
recClose(){
|
||
if(this.rec){
|
||
this.rec.close();
|
||
this.rec = null;
|
||
this.mic_opened = false;
|
||
}else{
|
||
bricks.debug('close recorder error');
|
||
};
|
||
}
|
||
start_recording(){
|
||
this.recordData = null;
|
||
if( this.recordData ){
|
||
this.URL.revokeObjectURL(this.recordData.url);
|
||
}
|
||
if (this.mic_opened){
|
||
this.rec.start();
|
||
this.dispatch('record_started');
|
||
}
|
||
this.recOpen();
|
||
}
|
||
pause_recording(){
|
||
if(this.rec&&Recorder.IsOpen()){
|
||
this.rec.pause();
|
||
}else{
|
||
bricks.debug("gCAR::未打开录音");
|
||
};
|
||
}
|
||
resume_recording(){
|
||
if(this.rec&&Recorder.IsOpen()){
|
||
this.rec.resume();
|
||
}else{
|
||
bricks.debug("Ob6S::未打开录音");
|
||
};
|
||
}
|
||
stop_recording(){
|
||
if(!(this.rec&&Recorder.IsOpen())){
|
||
bricks.debug("5JuL::未打开录音");
|
||
return;
|
||
};
|
||
this.rec.stop(function(blob,duration){
|
||
var localURL = this.URL.createObjectURL(blob);
|
||
var d = {
|
||
data:blob,
|
||
url:localURL,
|
||
duration:duration
|
||
}
|
||
this.recordData = d;
|
||
this.dispatch('record_ended', d);
|
||
|
||
}.bind(this),function(msg){
|
||
bricks.debug("kGZO::录音失败:");
|
||
});
|
||
this.recClose();
|
||
}
|
||
upload = async function(){
|
||
var running = new bricks.Running({target:this});
|
||
if(!this.recordData){
|
||
bricks.debug("DUTn::请先录音,然后停止后再上传");
|
||
return;
|
||
};
|
||
if(!this.upload_url){
|
||
return;
|
||
}
|
||
var blob=this.recordData.data;
|
||
bricks.debug('blob=', blob, this.recordData);
|
||
var form=new FormData();
|
||
form.append("audiofile",blob,"recorder.wav");
|
||
var jpost = bricks.jpost
|
||
var ret = await jpost(this.upload_url,{
|
||
params:form
|
||
});
|
||
bricks.debug('ret=', ret);
|
||
this.dispatch('uploaded', ret)
|
||
running.dismiss();
|
||
}
|
||
download(){
|
||
if(!this.recordData){
|
||
bricks.debug('recorder not opened');
|
||
return;
|
||
};
|
||
var fileName="recorder-"+Date.now()+".wav";
|
||
var downA=document.createElement("A");
|
||
downA.innerHTML="下载"+fileName;
|
||
downA.href=this.recordData.url;
|
||
downA.download=fileName;
|
||
// document.querySelector("."+cls).appendChild(downA);
|
||
if(/mobile/i.test(navigator.userAgent)){
|
||
bricks.debug('mobile device');
|
||
}
|
||
downA.click();
|
||
//不用了时需要revokeObjectURL,否则霸占内存
|
||
(window.URL||webkitURL).revokeObjectURL(downA.href);
|
||
}
|
||
}
|
||
|
||
bricks.SttClient = class extends bricks.VBox {
|
||
/*
|
||
{
|
||
"upload_url"
|
||
}
|
||
*/
|
||
constructor(opts){
|
||
super(opts);
|
||
this.recorder = new bricks.AudioRecorder({
|
||
icon_rate:2,
|
||
upload_url:opts.upload_url,
|
||
upload_resp:'json'
|
||
});
|
||
this.add_widget(this.recorder);
|
||
this.result_text = new bricks.Text({
|
||
text:'',
|
||
dynsize:true
|
||
});
|
||
this.add_widget(this.result_text);
|
||
this.recorder.bind('uploaded', this.set_result_text.bind(this));
|
||
}
|
||
set_result_text(event){
|
||
var txt = event.params.text;
|
||
this.result_text.set_text(txt);
|
||
}
|
||
}
|
||
bricks.Factory.register('AudioPlayer', bricks.AudioPlayer);
|
||
bricks.Factory.register('AudioRecorder', bricks.AudioRecorder);
|
||
bricks.Factory.register('SttClient', bricks.SttClient);
|