bugfix
This commit is contained in:
parent
70ce70dbd6
commit
7099adf136
@ -28,13 +28,16 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
|||||||
if (this.opts.autoplay){
|
if (this.opts.autoplay){
|
||||||
this.audio.addEventListener('canplay', this.play.bind(this));
|
this.audio.addEventListener('canplay', this.play.bind(this));
|
||||||
}
|
}
|
||||||
|
this.audio.addEventListener('ended', this.playended.bind(this));
|
||||||
this.audio.style.width = "100%"
|
this.audio.style.width = "100%"
|
||||||
this.dom_element.appendChild(this.audio);
|
this.dom_element.appendChild(this.audio);
|
||||||
if ( this.url ){
|
if ( this.url ){
|
||||||
this.set_source(this.url);
|
this.set_source(this.url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
playended(e){
|
||||||
|
this.dispatch('ended');
|
||||||
|
}
|
||||||
set_stream_urls(response){
|
set_stream_urls(response){
|
||||||
async function* dyn_urls(response) {
|
async function* dyn_urls(response) {
|
||||||
const reader = response.body.getReader();
|
const reader = response.body.getReader();
|
||||||
@ -56,6 +59,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
|||||||
}
|
}
|
||||||
this.url_generator = dyn_urls(response);
|
this.url_generator = dyn_urls(response);
|
||||||
this.srcList = [];
|
this.srcList = [];
|
||||||
|
this.notBegin = true;
|
||||||
schedule_once(this.load_queue_url.bind(this), 0.1);
|
schedule_once(this.load_queue_url.bind(this), 0.1);
|
||||||
}
|
}
|
||||||
async load_queue_url(){
|
async load_queue_url(){
|
||||||
@ -93,7 +97,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
|||||||
this.audio.appendChild(this.source);
|
this.audio.appendChild(this.source);
|
||||||
}
|
}
|
||||||
this.url = this.audio.src = url;
|
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){
|
set_source_from_response(resp){
|
||||||
// 将服务器返回的数据设置为音频源
|
// 将服务器返回的数据设置为音频源
|
||||||
@ -113,6 +117,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
|
|||||||
}
|
}
|
||||||
set_url(url){
|
set_url(url){
|
||||||
this.set_source(url);
|
this.set_source(url);
|
||||||
|
this.audio.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,35 +301,58 @@ bricks.AudioRecorder = class extends bricks.HBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bricks.SttClient = class extends bricks.VBox {
|
bricks.TextedAudioPlayer = class extends bricks.VBox {
|
||||||
/*
|
|
||||||
{
|
|
||||||
"upload_url"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
constructor(opts){
|
constructor(opts){
|
||||||
super(opts);
|
super(opts);
|
||||||
this.recorder = new bricks.AudioRecorder({
|
this.audio = new bricks.AudioPlayer({
|
||||||
icon_rate:2,
|
height:'60px'
|
||||||
upload_url:opts.upload_url,
|
|
||||||
upload_resp:'json'
|
|
||||||
});
|
});
|
||||||
this.add_widget(this.recorder);
|
this.audio.bind('ended', this.playnext.bind(this));
|
||||||
this.result_text = new bricks.Text({
|
var filler, panel;
|
||||||
text:'',
|
filler = new bricks.Filler({});
|
||||||
dynsize:true
|
this.add_widget(this.audio);
|
||||||
|
this.add_widget(filler);
|
||||||
|
panel = new bricks.VScrollPanel({
|
||||||
|
height: '100%'
|
||||||
});
|
});
|
||||||
this.add_widget(this.result_text);
|
filler.add_widget(panel);
|
||||||
this.recorder.bind('uploaded', this.set_result_text.bind(this));
|
this.textw = new bricks.Text({
|
||||||
|
text: ' ',
|
||||||
|
wrap: true
|
||||||
|
});
|
||||||
|
panel.add_widget(this.textw);
|
||||||
|
this.streaming_buffer = [];
|
||||||
|
this.wait_play = true;
|
||||||
}
|
}
|
||||||
set_result_text(event){
|
async playnext(){
|
||||||
var txt = event.params.text;
|
var json = this.streaming_buffer.shift();
|
||||||
this.result_text.set_text(txt);
|
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('AudioPlayer', bricks.AudioPlayer);
|
||||||
bricks.Factory.register('AudioRecorder', bricks.AudioRecorder);
|
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 || {};
|
var bricks = window.bricks || {};
|
||||||
bricks.bug = false;
|
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) {
|
function blobToBase64(blob) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
Loading…
Reference in New Issue
Block a user