bugfix
This commit is contained in:
parent
70ce70dbd6
commit
7099adf136
@ -28,13 +28,16 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
||||
if (this.opts.autoplay){
|
||||
this.audio.addEventListener('canplay', this.play.bind(this));
|
||||
}
|
||||
this.audio.addEventListener('ended', this.playended.bind(this));
|
||||
this.audio.style.width = "100%"
|
||||
this.dom_element.appendChild(this.audio);
|
||||
if ( this.url ){
|
||||
this.set_source(this.url);
|
||||
}
|
||||
}
|
||||
|
||||
playended(e){
|
||||
this.dispatch('ended');
|
||||
}
|
||||
set_stream_urls(response){
|
||||
async function* dyn_urls(response) {
|
||||
const reader = response.body.getReader();
|
||||
@ -56,6 +59,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
||||
}
|
||||
this.url_generator = dyn_urls(response);
|
||||
this.srcList = [];
|
||||
this.notBegin = true;
|
||||
schedule_once(this.load_queue_url.bind(this), 0.1);
|
||||
}
|
||||
async load_queue_url(){
|
||||
@ -93,7 +97,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
||||
this.audio.appendChild(this.source);
|
||||
}
|
||||
this.url = this.audio.src = url;
|
||||
bricks.debug(this.audio.src,' new src seted');
|
||||
console.log(this.audio.src,' new src seted');
|
||||
}
|
||||
set_source_from_response(resp){
|
||||
// 将服务器返回的数据设置为音频源
|
||||
@ -113,6 +117,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
||||
}
|
||||
set_url(url){
|
||||
this.set_source(url);
|
||||
this.audio.play();
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,35 +301,58 @@ bricks.AudioRecorder = class extends bricks.HBox {
|
||||
}
|
||||
}
|
||||
|
||||
bricks.SttClient = class extends bricks.VBox {
|
||||
/*
|
||||
{
|
||||
"upload_url"
|
||||
}
|
||||
*/
|
||||
bricks.TextedAudioPlayer = class extends bricks.VBox {
|
||||
constructor(opts){
|
||||
super(opts);
|
||||
this.recorder = new bricks.AudioRecorder({
|
||||
icon_rate:2,
|
||||
upload_url:opts.upload_url,
|
||||
upload_resp:'json'
|
||||
this.audio = new bricks.AudioPlayer({
|
||||
height:'60px'
|
||||
});
|
||||
this.add_widget(this.recorder);
|
||||
this.result_text = new bricks.Text({
|
||||
text:'',
|
||||
dynsize:true
|
||||
this.audio.bind('ended', this.playnext.bind(this));
|
||||
var filler, panel;
|
||||
filler = new bricks.Filler({});
|
||||
this.add_widget(this.audio);
|
||||
this.add_widget(filler);
|
||||
panel = new bricks.VScrollPanel({
|
||||
height: '100%'
|
||||
});
|
||||
this.add_widget(this.result_text);
|
||||
this.recorder.bind('uploaded', this.set_result_text.bind(this));
|
||||
filler.add_widget(panel);
|
||||
this.textw = new bricks.Text({
|
||||
text: ' ',
|
||||
wrap: true
|
||||
});
|
||||
panel.add_widget(this.textw);
|
||||
this.streaming_buffer = [];
|
||||
this.wait_play = true;
|
||||
}
|
||||
set_result_text(event){
|
||||
var txt = event.params.text;
|
||||
this.result_text.set_text(txt);
|
||||
async playnext(){
|
||||
var json = this.streaming_buffer.shift();
|
||||
console.log('======', json);
|
||||
if (json && ! json.done){
|
||||
var url = base64_to_url(json.audio);
|
||||
this.audio.set_url(url);
|
||||
this.wait_play = false;
|
||||
this.textw.set_text(json.text);
|
||||
await this.audio.play();
|
||||
} else {
|
||||
this.textw.set_text('');
|
||||
this.audio.set_url(null);
|
||||
this.wait_play = true;
|
||||
}
|
||||
}
|
||||
async set_stream_urls(response){
|
||||
this.wait_play = true;
|
||||
await streamResponseJson(response, this.load_stream_data.bind(this));
|
||||
}
|
||||
async load_stream_data(json){
|
||||
console.log('***', json);
|
||||
this.streaming_buffer.push(json);
|
||||
if (this.wait_play) {
|
||||
await this.playnext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bricks.Factory.register('AudioPlayer', bricks.AudioPlayer);
|
||||
bricks.Factory.register('AudioRecorder', bricks.AudioRecorder);
|
||||
bricks.Factory.register('SttClient', bricks.SttClient);
|
||||
bricks.Factory.register('TextedAudioPlayer', bricks.TextedAudioPlayer);
|
||||
|
||||
|
||||
|
@ -1,6 +1,53 @@
|
||||
var bricks = window.bricks || {};
|
||||
bricks.bug = false;
|
||||
|
||||
async function streamResponseJson(response, onJson) {
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
let buffer = "";
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
// 按换行切分 NDJSON
|
||||
let lines = buffer.split("\n");
|
||||
buffer = lines.pop(); // 可能是不完整的一行,留到下一轮
|
||||
for (const line of lines) {
|
||||
if (line.trim()) {
|
||||
try {
|
||||
const json = JSON.parse(line);
|
||||
onJson(json); // 👈 回调处理每个 JSON 对象
|
||||
} catch (err) {
|
||||
console.warn("Failed to parse JSON line:", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理最后残留的一行
|
||||
if (buffer.trim()) {
|
||||
try {
|
||||
const json = JSON.parse(buffer);
|
||||
onJson(json);
|
||||
} catch (err) {
|
||||
console.warn("Failed to parse trailing JSON line:", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function base64_to_url(base64, mimeType = "audio/wav") {
|
||||
const binary = atob(base64); // 解码 Base64 成 binary 字符串
|
||||
const len = binary.length;
|
||||
const bytes = new Uint8Array(len);
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
|
||||
const blob = new Blob([bytes], { type: mimeType });
|
||||
const url = URL.createObjectURL(blob);
|
||||
return url;
|
||||
}
|
||||
|
||||
function blobToBase64(blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
|
Loading…
Reference in New Issue
Block a user