diff --git a/bricks/build.sh b/bricks/build.sh index d94486c..b8f7da4 100755 --- a/bricks/build.sh +++ b/bricks/build.sh @@ -6,7 +6,7 @@ SOURCES=" page_data_loader.js factory.js uitypesdef.js utils.js uitype.js \ tree.js multiple_state_image.js dynamiccolumn.js form.js message.js conform.js \ paging.js datagrid.js iframe.js cols.js echartsext.js \ floaticonbar.js miniform.js wterm.js dynamicaccordion.js \ - binstreaming.js streaming_audio.js \ + binstreaming.js streaming_audio.js vadtext.js \ llm_dialog.js llm.js websocket.js datarow.js tabular.js \ line.js pie.js bar.js gobang.js " echo ${SOURCES} diff --git a/bricks/vadtext.js b/bricks/vadtext.js new file mode 100644 index 0000000..a19ce4c --- /dev/null +++ b/bricks/vadtext.js @@ -0,0 +1,87 @@ +var bricks = window.bricks || {}; + +bricks.VadText = class extends bricks.VBox { + constructor(opts){ + opts.height = '100%'; + opts.name = opts.name || 'asr_text'; + super(opts); + this.button = new bricks.Button({ + label:'start', + icon:bricks_resource('imgs/speak.png') + }); + this.filler = new bricks.Filler({}); + this.add_widget(this.button); + this.add_widget(this.filler); + this.text_w = new bricks.Text({text:' ', wrap:true}); + this.filler.add_widget(this.text_w); + this.button.bind('click', this.toggle_status.bind(this)); + this.bind('audio_ready', this.handle_audio.bind(this)); + } + toggle_status(){ + if (this.vad){ + this.stop(); + } else { + this.start(); + } + } + start(){ + this.button.text_w.set_otext('stop'); + schedule_once(this._start.bind(this), 0.1); + } + async _start(){ + if (bricks.vad){ + await bricks.vad.stop(); + } + this.vad = await vad.MicVAD.new({ + onSpeechEnd:(audio) => { + console.log(audio, this.vad); + this.dispatch('audio_ready', audio); + this.handle_audio(audio); + } + }); + this.vad.start(); + bricks.vad = this; + this.text = ''; + } + stop(){ + this.button.text_w.set_otext('start'); + schedule_once(this._stop.bind(this), 0.1); + } + async _stop(){ + await this.vad.pause(); + this.vad = null; + bricks.vad = null; + if(this.text != ''){ + this.dispatch('changed', this.getValue()); + } + } + async handle_audio(audio){ + console.log('handle_audil() called', audio); + var b64audio = btoa(audio); + var hj = new bricks.HttpJson(); + var d={ + method:'POST', + params:{ + model:this.model, + audiob64:b64audio + } + } + var rj = await hj.httpcall(this.url, d); + if (rj.status == 'ok'){ + this.text += rj.content + this.text_w.set_text(this.text); + } else { + w = new bricks.Error({title:'Error', + timeout:4, + message:rj.message + }); + w.open(); + } + } + getValue(){ + var d = {} + d[this.name] = this.text; + } +} + +bricks.Factory.register('VadText', bricks.VadText);