This commit is contained in:
yumoqing 2024-12-26 10:33:39 +08:00
parent 8462fdfe8d
commit 536adc7887
8 changed files with 300 additions and 71 deletions

View File

@ -26,7 +26,7 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
this.audio = this._create('audio'); this.audio = this._create('audio');
this.audio.controls = true; this.audio.controls = true;
if (this.opts.autoplay){ if (this.opts.autoplay){
this.audio.addEventListener('canplay', this.play_audio.bind(this)); this.audio.addEventListener('canplay', this.play.bind(this));
} }
this.audio.style.width = "100%" this.audio.style.width = "100%"
this.dom_element.appendChild(this.audio); this.dom_element.appendChild(this.audio);
@ -34,6 +34,58 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
this.set_source(this.url); this.set_source(this.url);
} }
} }
set_stream_urls(response){
async function* dyn_urls(response) {
const reader = response.body.getReader();
var value;
var done;
while (true){
done, value = await reader.read();
if (value.done){
console.log('done=', done, 'value=', value);
break;
}
let result = '';
for (let i = 0; i < value.value.length; i++) {
result += String.fromCharCode(value.value[i]);
}
console.log('audio set url=', result);
yield result;
}
}
this.url_generator = dyn_urls(response);
this.srcList = [];
schedule_once(this.load_queue_url.bind(this), 0.1);
}
async load_queue_url(){
while (true){
var d = await this.url_generator.next();
if (d.done){
return;
}
this.srcList.push({played:false, url:d.value});
if (this.srcList.length < 2 ){
await this.play_srclist();
this.audio.addEventListener('ended',
this.play_srclist.bind(this));
}
}
}
async play_srclist(evnet){
if (event && ! this.audio.ended){
return;
}
for (var i=0;i<this.srcList.length;i++){
if (!this.srcList[i].played){
console.log('playit', i, this.srcList[i]);
this.set_url(this.srcList[i].url);
this.srcList[i].played = true;
await this.play();
return;
}
}
}
set_source(url){ set_source(url){
if (! this.source){ if (! this.source){
this.source = this._create('source'); this.source = this._create('source');
@ -49,14 +101,14 @@ bricks.AudioPlayer = class extends bricks.JsWidget {
// 播放音频 // 播放音频
this.audio.play(); this.audio.play();
} }
play(){ async play(){
this.audio.play(); await this.audio.play();
} }
toggle_play(){ async toggle_play(){
if (this.audio.paused){ if (this.audio.paused){
this.audio.play(); await this.audio.play();
} else { } else {
this.audio.pause(); await this.audio.pause();
} }
} }
set_url(url){ set_url(url){
@ -81,6 +133,7 @@ bricks.AudioRecorder = class extends bricks.HBox {
*/ */
constructor(opts){ constructor(opts){
super(opts); super(opts);
this.set_css('clickable');
this.start_icon = opts.start_icon || bricks_resource('imgs/start_recording.png'); 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.stop_icon = opts.stop_icon || bricks_resource('imgs/stop_recording.png');
this.rec_btn = new bricks.Icon({ this.rec_btn = new bricks.Icon({
@ -97,7 +150,7 @@ bricks.AudioRecorder = class extends bricks.HBox {
width:'120px' width:'120px'
}); });
this.upload_url = opts.upload_url; this.upload_url = opts.upload_url;
this.rec_btn.bind('click', this.rec_btn_pressed.bind(this)) this.bind('click', this.rec_btn_pressed.bind(this))
this.URL = window.URL||webkitURL; this.URL = window.URL||webkitURL;
this.rec = null; this.rec = null;
this.wave = null; this.wave = null;

View File

@ -32,3 +32,25 @@ bricks.UpStreaming = class extends bricks.JsWidget {
this.stream_ctlr = controller; this.stream_ctlr = controller;
} }
} }
bricks.down_streaming = async function*(response) {
if (! response){
return;
}
const reader = response.body.getReader();
var value;
var t = 0;
while (true){
done, value = await reader.read();
if (value.done){
break;
}
let result = '';
for (let i = 0; i < value.value.length; i++) {
result += String.fromCharCode(value.value[i]);
}
console.log('audio set url=', result);
yield result;
}
}

View File

@ -38,4 +38,5 @@ cp -a ../examples/* ../dist/examples
cp -a ../3parties/* ../dist/3parties cp -a ../3parties/* ../dist/3parties
cp -a ../docs/* ../dist/docs cp -a ../docs/* ../dist/docs
cp *.tmpl ../dist cp *.tmpl ../dist
cp -a ../dist /tmp
echo "Finished ..." echo "Finished ..."

View File

@ -41,7 +41,7 @@ hr {
background-color: #eeeeee; background-color: #eeeeee;
} }
.clickable { .clickable {
color: #80ff88; color: #40cc40;
cursor: pointer; cursor: pointer;
} }

View File

@ -4,11 +4,11 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/bricks/3parties/xterm.css" /> <link rel="stylesheet" href="{{entire_url('/bricks/3parties/xterm.css')}}" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/js-docx-viewer/dist/css/docxviewer.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/js-docx-viewer/dist/css/docxviewer.min.css">
<link href="/bricks/3parties/video-js.css" rel="stylesheet" /> <link href="{{entire_url('/bricks/3parties/video-js.css')}}" rel="stylesheet" />
<link rel="stylesheet" href="/bricks/css/bricks.css"> <link rel="stylesheet" href="{{entire_url('/bricks/css/bricks.css')}}">
<link rel="stylesheet", href="/css/myapp.css"> <link rel="stylesheet", href="{{entire_url('/css/myapp.css')}}">
</head> </head>
<body> <body>
<!-- <!--
@ -23,17 +23,17 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.2/mammoth.browser.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.2/mammoth.browser.min.js"></script>
<script type="text/javascript" src="https://registry.npmmirror.com/echarts/5.5.1/files/dist/echarts.min.js"></script> <script type="text/javascript" src="https://registry.npmmirror.com/echarts/5.5.1/files/dist/echarts.min.js"></script>
<script src="/bricks/3parties/marked.min.js"></script> <script src="{{entire_url('/bricks/3parties/marked.min.js')}}"></script>
<script src="/bricks/3parties/xterm.js"></script> <script src="{{entire_url('/bricks/3parties/xterm.js')}}"></script>
<script src="/bricks/3parties/video.min.js"></script> <script src="{{entire_url('/bricks/3parties/video.min.js')}}"></script>
<!--- <!---
<link href="https://unpkg.com/video.js@6/dist/video-js.css" rel="stylesheet"> <link href="https://unpkg.com/video.js@6/dist/video-js.css" rel="stylesheet">
<script src="https://unpkg.com/video.js@6/dist/video.js"></script></head> <script src="https://unpkg.com/video.js@6/dist/video.js"></script></head>
---> --->
<script src="/bricks/3parties/recorder.wav.min.js"></script> <script src="{{entire_url('/bricks/3parties/recorder.wav.min.js')}}"></script>
<script src="/bricks/bricks.js"></script> <script src="{{entire_url('/bricks/bricks.js')}}"></script>
<script src="/js/myapp.js"></script> <script src="{{entire_url('/js/myapp.js')}}"></script>
<script> <script>
const opts = { const opts = {
"widget": "widget":

View File

@ -49,6 +49,47 @@ bricks.UiType =class extends bricks.Layout {
} }
} }
bricks.UiAudioRecorder = class extends bricks.AudioRecorder {
constructor(opts){
super(opts);
this.uitype = 'audiorecorder';
this.name = this.opts.name;
this.required = opts.required || false;
this.value = opts.value || opts.defaultvalue||'';
this.bind('record_ended', this.getValue.bind(this));
}
getValue(){
var o = {}
this.value = this.recordData.data;
o[this.name] = this.value;
return o;
}
set_formdata(formdata){
formdata.append(this.name, this.value, 'record.wav');
}
resultValue(){
return this.value;
}
focus(){
this.dom_element.focus();
}
reset(){
}
setValue(v){
return;
}
set_disabled(f){
this.dom_element.disabled = f;
}
set_readonly(f){
this.dom_element.readOnly = f;
}
set_required(f){
this.dom_element.required = f;
this.required = f;
}
}
bricks.UiAudioText = class extends bricks.UiType { bricks.UiAudioText = class extends bricks.UiType {
/* /*
{ {
@ -337,7 +378,7 @@ bricks.UiFile =class extends bricks.UiStr {
return this.dom_element.files; return this.dom_element.files;
} }
resultValue(){ resultValue(){
return this.get_files(); return this.get_files()[0];
} }
setValue(v){ setValue(v){
return; return;
@ -910,6 +951,7 @@ bricks.UiVideo =class extends bricks.UiStr {
} }
} }
var Input = new bricks._Input(); var Input = new bricks._Input();
Input.register('UiAudioRecorder', 'audiorecorder', bricks.UiAudioRecorder);
Input.register('UiStr', 'str', bricks.UiStr); Input.register('UiStr', 'str', bricks.UiStr);
Input.register('UiHide', 'hide', bricks.UiHide); Input.register('UiHide', 'hide', bricks.UiHide);
Input.register('UiTel', 'tel', bricks.UiTel); Input.register('UiTel', 'tel', bricks.UiTel);

View File

@ -102,7 +102,7 @@ bricks.HttpText = class {
} }
return Object.assign(this.headers, headers); return Object.assign(this.headers, headers);
} }
async httpcall(url, {method='GET', headers=null, params=null}={}){ async bricks_fetch(url, {method='GET', headers=null, params=null}={}){
url = this.url_parse(url); url = this.url_parse(url);
var data = this.add_own_params(params); var data = this.add_own_params(params);
var header = this.add_own_headers(headers); var header = this.add_own_headers(headers);
@ -120,8 +120,13 @@ bricks.HttpText = class {
_params.body = JSON.stringify(data); _params.body = JSON.stringify(data);
} }
} }
const fetchResult = await fetch(url, _params); return await fetch(url, _params);
// console.log('fetchResult.status=', fetchResult.status, url, 'login url=', bricks.app.login_url); }
async httpcall(url, opts){
const fetchResult = await this.bricks_fetch(url, {
method: opts.method,
headers: opts.headers,
params: opts.params});
if (fetchResult.status == 401 && bricks.app.login_url){ if (fetchResult.status == 401 && bricks.app.login_url){
console.log('go to login') console.log('go to login')
return await this.withLoginInfo(url, _params); return await this.withLoginInfo(url, _params);

View File

@ -367,6 +367,46 @@ var objcopy = function(obj){
return o; return o;
} }
bricks.set_stream_source = async function(target, url, params){
var widget;
if (typeof target == typeof ''){
widget = bricks.getWidgetById(target);
} else if (target instanceof bricks.JsWidget){
widget = target;
} else {
widget = await bricks.widgetBuild(target);
}
if (! widget){
bricks.debug('playResponseAudio():', target, 'can not found or build a widget');
return;
}
const mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen);
widget.set_url(URL.createObjectURL(mediaSource));
function handleSourceOpen(){
const sourceBuffer = mediaSource.addSourceBuffer('audio/wav; codecs=1');
var ht = new bricks.HttpText();
ht.bricks_fetch(url, {params:params})
.then(response => response.body)
.then(body => {
const reader = body.getReader();
const read = () => {
reader.read().then(({ done, value }) => {
if (done) {
mediaSource.endOfStream();
return;
}
sourceBuffer.appendBuffer(value);
read();
}).catch(error => {
console.error('Error reading audio stream:', error);
});
};
read();
});
}
}
bricks.playResponseAudio = async function(response, target){ bricks.playResponseAudio = async function(response, target){
var widget = null; var widget = null;
if (response.status != 200){ if (response.status != 200){
@ -410,12 +450,78 @@ bricks.Observable = class {
this.value = v; this.value = v;
} }
set(v){ set(v){
if (this.value != v){ var ov = this.value;
this.value = v;
if (this.value != ov){
this.owner.dispatch(this.name, v); this.owner.dispatch(this.name, v);
} }
this.value = v;
} }
get(){ get(){
return this.v; return this.v;
} }
} }
bricks.Queue = class {
constructor() {
this.items = [];
this._done = false;
}
// 添加元素到队列尾部
enqueue(element) {
this.items.push(element);
}
done(){
this._done = true;
}
is_done(){
return this._done;
}
// 移除队列的第一个元素并返回
dequeue() {
if (this.isEmpty()) {
return null;
}
return this.items.shift();
}
// 查看队列的第一个元素
peek() {
if (this.isEmpty()) {
return null;
}
return this.items[0];
}
// 检查队列是否为空
isEmpty() {
return this.items.length === 0;
}
// 获取队列的大小
size() {
return this.items.length;
}
// 清空队列
clear() {
this.items = [];
}
// 打印队列元素
print() {
console.log(this.items.toString());
}
}
/*
// 使用队列
const queue = new Queue();
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
queue.print(); // 输出: 1,2,3
console.log(queue.dequeue()); // 输出: 1
queue.print(); // 输出: 2,3
*/