Xin Zhang commited on
Commit
eb39b90
·
2 Parent(s): 7858456 9226b1d

Merge branch 'vad'

Browse files

* vad:
[fix]: update web.
[fix]: whisper_full_with_state: input is too short - 990 ms < 1000 ms. consider padding the input audio with silence.
[fix]: to 1.5b
filter empty message
update zh-en prompt add limit
update code structures and some code
update prompts and words

config/hotwords.json CHANGED
@@ -5,8 +5,23 @@
5
  "GO SAME": "GOSIM",
6
  "go same": "GOSIM",
7
  "GoSync": "GOSIM",
 
8
  "CSN": "CSDN",
9
  "CSDF": "CSDN",
10
  "CSTN": "CSDN",
11
- "OpenAZI": "Open AGI"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  }
 
5
  "GO SAME": "GOSIM",
6
  "go same": "GOSIM",
7
  "GoSync": "GOSIM",
8
+ "Go Son": "GOSIM",
9
  "CSN": "CSDN",
10
  "CSDF": "CSDN",
11
  "CSTN": "CSDN",
12
+ "OpenAZI": "Open AGI",
13
+ "CSdn": "CSDN",
14
+ "DeepSeq": "DeepSeek",
15
+ "deep sig": "DeepSeek",
16
+ "deep sick": "DeepSeek",
17
+ "chat GBT": "ChatGPT",
18
+ "Deep sike": "DeepSeek",
19
+ "Deep sink": "DeepSeek",
20
+ "它跟face": "huggingface",
21
+ "拉么index": "LlamaIndex",
22
+ "lama index": "LlamaIndex",
23
+ "rug": "RAG",
24
+ "defive": "Dify",
25
+ "define": "Dify",
26
+ "open minus":"open manus"
27
  }
config/hotwords.txt CHANGED
@@ -32,3 +32,6 @@ MoXIN
32
  Function
33
  Func
34
  Lava
 
 
 
 
32
  Function
33
  Func
34
  Lava
35
+ C++
36
+ 阿里
37
+ pipeline
config/keywords.txt CHANGED
@@ -1,4 +1,8 @@
1
  OpenAGI
2
  GOSIM
3
  Rust
4
- LLaMA Factory
 
 
 
 
 
1
  OpenAGI
2
  GOSIM
3
  Rust
4
+ LLaMA Factory
5
+ OPENGL
6
+ GPU
7
+ Web3
8
+ DeepSeek
config/prompt.py CHANGED
@@ -34,16 +34,24 @@ LLM_SYS_7B_PROMPT_EN = """
34
  """.format(keywords_mapping_string=keywords_mapping_string)
35
 
36
  LLM_SYS_7B_PROMPT_ZH = """
37
- 你是一个中英文翻译专家,请将以下文本从中文翻译成英文,但保留所有英文专业术语、产品名称、代码片段和专有名词的原始英文形式。遇到英文专业术语或需要保留的内容时,请使用原始英文表达,不要翻译。
38
- 翻译规则:
39
- 1. 保留以下内容的原始英文形式,不翻译:
40
- - 技术术语和专业词汇
41
- - 产品名称、品牌名称
42
- - 代码片段、函数名、变量名
43
- - 专有名词、缩写和首字母缩略词
44
- 2. 翻译其余内容时,请确保:
45
- - 保持原文的段落结构
46
- - 翻译内容符合中文表达习惯
47
- - 保持专业性和准确性
48
- 如遇到难以判断是否需要保留英文的情况,请优先保留原始英文形式。
 
 
 
 
 
49
  文本:"""
 
 
 
 
34
  """.format(keywords_mapping_string=keywords_mapping_string)
35
 
36
  LLM_SYS_7B_PROMPT_ZH = """
37
+ 你是一位中英文翻译专家。请将以下中文文本翻译成英文,遵循以下要求:
38
+
39
+ 翻译要求:
40
+ - 保留原文英文内容:以下内容请保持原始英文形式,不进行翻译或改写:
41
+ - 技术术语与专业词汇
42
+ - 产品名称、品牌名称
43
+ - 代码片段、函数名、变量名
44
+ - 专有名词、缩写、首字母缩略词(如 API、NLP、RAG 等)
45
+ - 翻译符合英文表达习惯,流畅自然,不生硬直译。
46
+ - 保持专业性与准确性,清晰传达原意。
47
+ - 如遇原文表达模糊或逻辑不清的情况,允许适度调整语序或措辞,以增强英文表述的清晰度和逻辑性。
48
+
49
+ 注意:
50
+ 若难以确定某个词汇是否需要翻译,请优先保留原始英文形式。
51
+ 不需添加额外解释或注释,仅翻译正文内容。
52
+ 特别注意,翻译的内容只能包含英文,不能包含其他的语言。
53
+
54
  文本:"""
55
+
56
+ LLM_SYS_PROMPT_EN = LLM_SYS_7B_PROMPT_EN
57
+ LLM_SYS_PROMPT_ZH =LLM_SYS_7B_PROMPT_ZH
frontend/assets/{index-a619a94d.js → index-4906844f.js} RENAMED
@@ -492,9 +492,9 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
492
  * vue-router v4.4.3
493
  * (c) 2024 Eduardo San Martin Morote
494
  * @license MIT
495
- */const Xl=typeof document<"u";function xye(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const Pt=Object.assign;function sv(e,t){const n={};for(const o in t){const r=t[o];n[o]=Xo(r)?r.map(e):e(r)}return n}const Us=()=>{},Xo=Array.isArray,w_=/#/g,wye=/&/g,Oye=/\//g,Pye=/=/g,Iye=/\?/g,O_=/\+/g,Tye=/%5B/g,Eye=/%5D/g,P_=/%5E/g,Mye=/%60/g,I_=/%7B/g,_ye=/%7C/g,T_=/%7D/g,Aye=/%20/g;function RS(e){return encodeURI(""+e).replace(_ye,"|").replace(Tye,"[").replace(Eye,"]")}function Rye(e){return RS(e).replace(I_,"{").replace(T_,"}").replace(P_,"^")}function i0(e){return RS(e).replace(O_,"%2B").replace(Aye,"+").replace(w_,"%23").replace(wye,"%26").replace(Mye,"`").replace(I_,"{").replace(T_,"}").replace(P_,"^")}function Dye(e){return i0(e).replace(Pye,"%3D")}function Bye(e){return RS(e).replace(w_,"%23").replace(Iye,"%3F")}function Nye(e){return e==null?"":Bye(e).replace(Oye,"%2F")}function Ec(e){try{return decodeURIComponent(""+e)}catch{}return""+e}const kye=/\/$/,Fye=e=>e.replace(kye,"");function cv(e,t,n="/"){let o,r={},i="",l="";const a=t.indexOf("#");let s=t.indexOf("?");return a<s&&a>=0&&(s=-1),s>-1&&(o=t.slice(0,s),i=t.slice(s+1,a>-1?a:t.length),r=e(i)),a>-1&&(o=o||t.slice(0,a),l=t.slice(a,t.length)),o=jye(o??t,n),{fullPath:o+(i&&"?")+i+l,path:o,query:r,hash:Ec(l)}}function Lye(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function D3(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function zye(e,t,n){const o=t.matched.length-1,r=n.matched.length-1;return o>-1&&o===r&&Da(t.matched[o],n.matched[r])&&E_(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Da(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function E_(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!Hye(e[n],t[n]))return!1;return!0}function Hye(e,t){return Xo(e)?B3(e,t):Xo(t)?B3(t,e):e===t}function B3(e,t){return Xo(t)?e.length===t.length&&e.every((n,o)=>n===t[o]):e.length===1&&e[0]===t}function jye(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),o=e.split("/"),r=o[o.length-1];(r===".."||r===".")&&o.push("");let i=n.length-1,l,a;for(l=0;l<o.length;l++)if(a=o[l],a!==".")if(a==="..")i>1&&i--;else break;return n.slice(0,i).join("/")+"/"+o.slice(l).join("/")}const ti={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};var Mc;(function(e){e.pop="pop",e.push="push"})(Mc||(Mc={}));var Gs;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Gs||(Gs={}));function Wye(e){if(!e)if(Xl){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),Fye(e)}const Vye=/^[^#]+#/;function Kye(e,t){return e.replace(Vye,"#")+t}function Uye(e,t){const n=document.documentElement.getBoundingClientRect(),o=e.getBoundingClientRect();return{behavior:t.behavior,left:o.left-n.left-(t.left||0),top:o.top-n.top-(t.top||0)}}const wh=()=>({left:window.scrollX,top:window.scrollY});function Gye(e){let t;if("el"in e){const n=e.el,o=typeof n=="string"&&n.startsWith("#"),r=typeof n=="string"?o?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!r)return;t=Uye(r,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function N3(e,t){return(history.state?history.state.position-t:-1)+e}const l0=new Map;function Xye(e,t){l0.set(e,t)}function Yye(e){const t=l0.get(e);return l0.delete(e),t}let qye=()=>location.protocol+"//"+location.host;function M_(e,t){const{pathname:n,search:o,hash:r}=t,i=e.indexOf("#");if(i>-1){let a=r.includes(e.slice(i))?e.slice(i).length:1,s=r.slice(a);return s[0]!=="/"&&(s="/"+s),D3(s,"")}return D3(n,e)+o+r}function Zye(e,t,n,o){let r=[],i=[],l=null;const a=({state:f})=>{const h=M_(e,location),v=n.value,g=t.value;let b=0;if(f){if(n.value=h,t.value=f,l&&l===v){l=null;return}b=g?f.position-g.position:0}else o(h);r.forEach(y=>{y(n.value,v,{delta:b,type:Mc.pop,direction:b?b>0?Gs.forward:Gs.back:Gs.unknown})})};function s(){l=n.value}function c(f){r.push(f);const h=()=>{const v=r.indexOf(f);v>-1&&r.splice(v,1)};return i.push(h),h}function u(){const{history:f}=window;f.state&&f.replaceState(Pt({},f.state,{scroll:wh()}),"")}function d(){for(const f of i)f();i=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",u)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",u,{passive:!0}),{pauseListeners:s,listen:c,destroy:d}}function k3(e,t,n,o=!1,r=!1){return{back:e,current:t,forward:n,replaced:o,position:window.history.length,scroll:r?wh():null}}function Qye(e){const{history:t,location:n}=window,o={value:M_(e,n)},r={value:t.state};r.value||i(o.value,{back:null,current:o.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(s,c,u){const d=e.indexOf("#"),f=d>-1?(n.host&&document.querySelector("base")?e:e.slice(d))+s:qye()+e+s;try{t[u?"replaceState":"pushState"](c,"",f),r.value=c}catch(h){console.error(h),n[u?"replace":"assign"](f)}}function l(s,c){const u=Pt({},t.state,k3(r.value.back,s,r.value.forward,!0),c,{position:r.value.position});i(s,u,!0),o.value=s}function a(s,c){const u=Pt({},r.value,t.state,{forward:s,scroll:wh()});i(u.current,u,!0);const d=Pt({},k3(o.value,s,null),{position:u.position+1},c);i(s,d,!1),o.value=s}return{location:o,state:r,push:a,replace:l}}function Jye(e){e=Wye(e);const t=Qye(e),n=Zye(e,t.state,t.location,t.replace);function o(i,l=!0){l||n.pauseListeners(),history.go(i)}const r=Pt({location:"",base:e,go:o,createHref:Kye.bind(null,e)},t,n);return Object.defineProperty(r,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(r,"state",{enumerable:!0,get:()=>t.state.value}),r}function e1e(e){return typeof e=="string"||e&&typeof e=="object"}function __(e){return typeof e=="string"||typeof e=="symbol"}const A_=Symbol("");var F3;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(F3||(F3={}));function Ba(e,t){return Pt(new Error,{type:e,[A_]:!0},t)}function Sr(e,t){return e instanceof Error&&A_ in e&&(t==null||!!(e.type&t))}const L3="[^/]+?",t1e={sensitive:!1,strict:!1,start:!0,end:!0},n1e=/[.+*?^${}()[\]/\\]/g;function o1e(e,t){const n=Pt({},t1e,t),o=[];let r=n.start?"^":"";const i=[];for(const c of e){const u=c.length?[]:[90];n.strict&&!c.length&&(r+="/");for(let d=0;d<c.length;d++){const f=c[d];let h=40+(n.sensitive?.25:0);if(f.type===0)d||(r+="/"),r+=f.value.replace(n1e,"\\$&"),h+=40;else if(f.type===1){const{value:v,repeatable:g,optional:b,regexp:y}=f;i.push({name:v,repeatable:g,optional:b});const S=y||L3;if(S!==L3){h+=10;try{new RegExp(`(${S})`)}catch(x){throw new Error(`Invalid custom RegExp for param "${v}" (${S}): `+x.message)}}let $=g?`((?:${S})(?:/(?:${S}))*)`:`(${S})`;d||($=b&&c.length<2?`(?:/${$})`:"/"+$),b&&($+="?"),r+=$,h+=20,b&&(h+=-8),g&&(h+=-20),S===".*"&&(h+=-50)}u.push(h)}o.push(u)}if(n.strict&&n.end){const c=o.length-1;o[c][o[c].length-1]+=.7000000000000001}n.strict||(r+="/?"),n.end?r+="$":n.strict&&(r+="(?:/|$)");const l=new RegExp(r,n.sensitive?"":"i");function a(c){const u=c.match(l),d={};if(!u)return null;for(let f=1;f<u.length;f++){const h=u[f]||"",v=i[f-1];d[v.name]=h&&v.repeatable?h.split("/"):h}return d}function s(c){let u="",d=!1;for(const f of e){(!d||!u.endsWith("/"))&&(u+="/"),d=!1;for(const h of f)if(h.type===0)u+=h.value;else if(h.type===1){const{value:v,repeatable:g,optional:b}=h,y=v in c?c[v]:"";if(Xo(y)&&!g)throw new Error(`Provided param "${v}" is an array but it is not repeatable (* or + modifiers)`);const S=Xo(y)?y.join("/"):y;if(!S)if(b)f.length<2&&(u.endsWith("/")?u=u.slice(0,-1):d=!0);else throw new Error(`Missing required param "${v}"`);u+=S}}return u||"/"}return{re:l,score:o,keys:i,parse:a,stringify:s}}function r1e(e,t){let n=0;for(;n<e.length&&n<t.length;){const o=t[n]-e[n];if(o)return o;n++}return e.length<t.length?e.length===1&&e[0]===40+40?-1:1:e.length>t.length?t.length===1&&t[0]===40+40?1:-1:0}function R_(e,t){let n=0;const o=e.score,r=t.score;for(;n<o.length&&n<r.length;){const i=r1e(o[n],r[n]);if(i)return i;n++}if(Math.abs(r.length-o.length)===1){if(z3(o))return 1;if(z3(r))return-1}return r.length-o.length}function z3(e){const t=e[e.length-1];return e.length>0&&t[t.length-1]<0}const i1e={type:0,value:""},l1e=/[a-zA-Z0-9_]/;function a1e(e){if(!e)return[[]];if(e==="/")return[[i1e]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(h){throw new Error(`ERR (${n})/"${c}": ${h}`)}let n=0,o=n;const r=[];let i;function l(){i&&r.push(i),i=[]}let a=0,s,c="",u="";function d(){c&&(n===0?i.push({type:0,value:c}):n===1||n===2||n===3?(i.length>1&&(s==="*"||s==="+")&&t(`A repeatable param (${c}) must be alone in its segment. eg: '/:ids+.`),i.push({type:1,value:c,regexp:u,repeatable:s==="*"||s==="+",optional:s==="*"||s==="?"})):t("Invalid state to consume buffer"),c="")}function f(){c+=s}for(;a<e.length;){if(s=e[a++],s==="\\"&&n!==2){o=n,n=4;continue}switch(n){case 0:s==="/"?(c&&d(),l()):s===":"?(d(),n=1):f();break;case 4:f(),n=o;break;case 1:s==="("?n=2:l1e.test(s)?f():(d(),n=0,s!=="*"&&s!=="?"&&s!=="+"&&a--);break;case 2:s===")"?u[u.length-1]=="\\"?u=u.slice(0,-1)+s:n=3:u+=s;break;case 3:d(),n=0,s!=="*"&&s!=="?"&&s!=="+"&&a--,u="";break;default:t("Unknown state");break}}return n===2&&t(`Unfinished custom RegExp for param "${c}"`),d(),l(),r}function s1e(e,t,n){const o=o1e(a1e(e.path),n),r=Pt(o,{record:e,parent:t,children:[],alias:[]});return t&&!r.record.aliasOf==!t.record.aliasOf&&t.children.push(r),r}function c1e(e,t){const n=[],o=new Map;t=W3({strict:!1,end:!0,sensitive:!1},t);function r(d){return o.get(d)}function i(d,f,h){const v=!h,g=u1e(d);g.aliasOf=h&&h.record;const b=W3(t,d),y=[g];if("alias"in d){const x=typeof d.alias=="string"?[d.alias]:d.alias;for(const C of x)y.push(Pt({},g,{components:h?h.record.components:g.components,path:C,aliasOf:h?h.record:g}))}let S,$;for(const x of y){const{path:C}=x;if(f&&C[0]!=="/"){const O=f.record.path,w=O[O.length-1]==="/"?"":"/";x.path=f.record.path+(C&&w+C)}if(S=s1e(x,f,b),h?h.alias.push(S):($=$||S,$!==S&&$.alias.push(S),v&&d.name&&!j3(S)&&l(d.name)),D_(S)&&s(S),g.children){const O=g.children;for(let w=0;w<O.length;w++)i(O[w],S,h&&h.children[w])}h=h||S}return $?()=>{l($)}:Us}function l(d){if(__(d)){const f=o.get(d);f&&(o.delete(d),n.splice(n.indexOf(f),1),f.children.forEach(l),f.alias.forEach(l))}else{const f=n.indexOf(d);f>-1&&(n.splice(f,1),d.record.name&&o.delete(d.record.name),d.children.forEach(l),d.alias.forEach(l))}}function a(){return n}function s(d){const f=p1e(d,n);n.splice(f,0,d),d.record.name&&!j3(d)&&o.set(d.record.name,d)}function c(d,f){let h,v={},g,b;if("name"in d&&d.name){if(h=o.get(d.name),!h)throw Ba(1,{location:d});b=h.record.name,v=Pt(H3(f.params,h.keys.filter($=>!$.optional).concat(h.parent?h.parent.keys.filter($=>$.optional):[]).map($=>$.name)),d.params&&H3(d.params,h.keys.map($=>$.name))),g=h.stringify(v)}else if(d.path!=null)g=d.path,h=n.find($=>$.re.test(g)),h&&(v=h.parse(g),b=h.record.name);else{if(h=f.name?o.get(f.name):n.find($=>$.re.test(f.path)),!h)throw Ba(1,{location:d,currentLocation:f});b=h.record.name,v=Pt({},f.params,d.params),g=h.stringify(v)}const y=[];let S=h;for(;S;)y.unshift(S.record),S=S.parent;return{name:b,path:g,params:v,matched:y,meta:f1e(y)}}e.forEach(d=>i(d));function u(){n.length=0,o.clear()}return{addRoute:i,resolve:c,removeRoute:l,clearRoutes:u,getRoutes:a,getRecordMatcher:r}}function H3(e,t){const n={};for(const o of t)o in e&&(n[o]=e[o]);return n}function u1e(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:d1e(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}}}function d1e(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const o in e.components)t[o]=typeof n=="object"?n[o]:n;return t}function j3(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function f1e(e){return e.reduce((t,n)=>Pt(t,n.meta),{})}function W3(e,t){const n={};for(const o in e)n[o]=o in t?t[o]:e[o];return n}function p1e(e,t){let n=0,o=t.length;for(;n!==o;){const i=n+o>>1;R_(e,t[i])<0?o=i:n=i+1}const r=h1e(e);return r&&(o=t.lastIndexOf(r,o-1)),o}function h1e(e){let t=e;for(;t=t.parent;)if(D_(t)&&R_(e,t)===0)return t}function D_({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function g1e(e){const t={};if(e===""||e==="?")return t;const o=(e[0]==="?"?e.slice(1):e).split("&");for(let r=0;r<o.length;++r){const i=o[r].replace(O_," "),l=i.indexOf("="),a=Ec(l<0?i:i.slice(0,l)),s=l<0?null:Ec(i.slice(l+1));if(a in t){let c=t[a];Xo(c)||(c=t[a]=[c]),c.push(s)}else t[a]=s}return t}function V3(e){let t="";for(let n in e){const o=e[n];if(n=Dye(n),o==null){o!==void 0&&(t+=(t.length?"&":"")+n);continue}(Xo(o)?o.map(i=>i&&i0(i)):[o&&i0(o)]).forEach(i=>{i!==void 0&&(t+=(t.length?"&":"")+n,i!=null&&(t+="="+i))})}return t}function v1e(e){const t={};for(const n in e){const o=e[n];o!==void 0&&(t[n]=Xo(o)?o.map(r=>r==null?null:""+r):o==null?o:""+o)}return t}const m1e=Symbol(""),K3=Symbol(""),DS=Symbol(""),B_=Symbol(""),a0=Symbol("");function ps(){let e=[];function t(o){return e.push(o),()=>{const r=e.indexOf(o);r>-1&&e.splice(r,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function ai(e,t,n,o,r,i=l=>l()){const l=o&&(o.enterCallbacks[r]=o.enterCallbacks[r]||[]);return()=>new Promise((a,s)=>{const c=f=>{f===!1?s(Ba(4,{from:n,to:t})):f instanceof Error?s(f):e1e(f)?s(Ba(2,{from:t,to:f})):(l&&o.enterCallbacks[r]===l&&typeof f=="function"&&l.push(f),a())},u=i(()=>e.call(o&&o.instances[r],t,n,c));let d=Promise.resolve(u);e.length<3&&(d=d.then(c)),d.catch(f=>s(f))})}function uv(e,t,n,o,r=i=>i()){const i=[];for(const l of e)for(const a in l.components){let s=l.components[a];if(!(t!=="beforeRouteEnter"&&!l.instances[a]))if(b1e(s)){const u=(s.__vccOpts||s)[t];u&&i.push(ai(u,n,o,l,a,r))}else{let c=s();i.push(()=>c.then(u=>{if(!u)return Promise.reject(new Error(`Couldn't resolve component "${a}" at "${l.path}"`));const d=xye(u)?u.default:u;l.components[a]=d;const h=(d.__vccOpts||d)[t];return h&&ai(h,n,o,l,a,r)()}))}}return i}function b1e(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function U3(e){const t=We(DS),n=We(B_),o=I(()=>{const s=Et(e.to);return t.resolve(s)}),r=I(()=>{const{matched:s}=o.value,{length:c}=s,u=s[c-1],d=n.matched;if(!u||!d.length)return-1;const f=d.findIndex(Da.bind(null,u));if(f>-1)return f;const h=G3(s[c-2]);return c>1&&G3(u)===h&&d[d.length-1].path!==h?d.findIndex(Da.bind(null,s[c-2])):f}),i=I(()=>r.value>-1&&C1e(n.params,o.value.params)),l=I(()=>r.value>-1&&r.value===n.matched.length-1&&E_(n.params,o.value.params));function a(s={}){return $1e(s)?t[Et(e.replace)?"replace":"push"](Et(e.to)).catch(Us):Promise.resolve()}return{route:o,href:I(()=>o.value.href),isActive:i,isExactActive:l,navigate:a}}const y1e=re({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:U3,setup(e,{slots:t}){const n=ct(U3(e)),{options:o}=We(DS),r=I(()=>({[X3(e.activeClass,o.linkActiveClass,"router-link-active")]:n.isActive,[X3(e.exactActiveClass,o.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const i=t.default&&t.default(n);return e.custom?i:Sa("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:r.value},i)}}}),S1e=y1e;function $1e(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function C1e(e,t){for(const n in t){const o=t[n],r=e[n];if(typeof o=="string"){if(o!==r)return!1}else if(!Xo(r)||r.length!==o.length||o.some((i,l)=>i!==r[l]))return!1}return!0}function G3(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const X3=(e,t,n)=>e??t??n,x1e=re({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const o=We(a0),r=I(()=>e.route||o.value),i=We(K3,0),l=I(()=>{let c=Et(i);const{matched:u}=r.value;let d;for(;(d=u[c])&&!d.components;)c++;return c}),a=I(()=>r.value.matched[l.value]);Ge(K3,I(()=>l.value+1)),Ge(m1e,a),Ge(a0,r);const s=oe();return be(()=>[s.value,a.value,e.name],([c,u,d],[f,h,v])=>{u&&(u.instances[d]=c,h&&h!==u&&c&&c===f&&(u.leaveGuards.size||(u.leaveGuards=h.leaveGuards),u.updateGuards.size||(u.updateGuards=h.updateGuards))),c&&u&&(!h||!Da(u,h)||!f)&&(u.enterCallbacks[d]||[]).forEach(g=>g(c))},{flush:"post"}),()=>{const c=r.value,u=e.name,d=a.value,f=d&&d.components[u];if(!f)return Y3(n.default,{Component:f,route:c});const h=d.props[u],v=h?h===!0?c.params:typeof h=="function"?h(c):h:null,b=Sa(f,Pt({},v,t,{onVnodeUnmounted:y=>{y.component.isUnmounted&&(d.instances[u]=null)},ref:s}));return Y3(n.default,{Component:b,route:c})||b}}});function Y3(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const w1e=x1e;function O1e(e){const t=c1e(e.routes,e),n=e.parseQuery||g1e,o=e.stringifyQuery||V3,r=e.history,i=ps(),l=ps(),a=ps(),s=ne(ti);let c=ti;Xl&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const u=sv.bind(null,K=>""+K),d=sv.bind(null,Nye),f=sv.bind(null,Ec);function h(K,ee){let Z,U;return __(K)?(Z=t.getRecordMatcher(K),U=ee):U=K,t.addRoute(U,Z)}function v(K){const ee=t.getRecordMatcher(K);ee&&t.removeRoute(ee)}function g(){return t.getRoutes().map(K=>K.record)}function b(K){return!!t.getRecordMatcher(K)}function y(K,ee){if(ee=Pt({},ee||s.value),typeof K=="string"){const te=cv(n,K,ee.path),se=t.resolve({path:te.path},ee),ie=r.createHref(te.fullPath);return Pt(te,se,{params:f(se.params),hash:Ec(te.hash),redirectedFrom:void 0,href:ie})}let Z;if(K.path!=null)Z=Pt({},K,{path:cv(n,K.path,ee.path).path});else{const te=Pt({},K.params);for(const se in te)te[se]==null&&delete te[se];Z=Pt({},K,{params:d(te)}),ee.params=d(ee.params)}const U=t.resolve(Z,ee),Q=K.hash||"";U.params=u(f(U.params));const W=Lye(o,Pt({},K,{hash:Rye(Q),path:U.path})),G=r.createHref(W);return Pt({fullPath:W,hash:Q,query:o===V3?v1e(K.query):K.query||{}},U,{redirectedFrom:void 0,href:G})}function S(K){return typeof K=="string"?cv(n,K,s.value.path):Pt({},K)}function $(K,ee){if(c!==K)return Ba(8,{from:ee,to:K})}function x(K){return w(K)}function C(K){return x(Pt(S(K),{replace:!0}))}function O(K){const ee=K.matched[K.matched.length-1];if(ee&&ee.redirect){const{redirect:Z}=ee;let U=typeof Z=="function"?Z(K):Z;return typeof U=="string"&&(U=U.includes("?")||U.includes("#")?U=S(U):{path:U},U.params={}),Pt({query:K.query,hash:K.hash,params:U.path!=null?{}:K.params},U)}}function w(K,ee){const Z=c=y(K),U=s.value,Q=K.state,W=K.force,G=K.replace===!0,te=O(Z);if(te)return w(Pt(S(te),{state:typeof te=="object"?Pt({},Q,te.state):Q,force:W,replace:G}),ee||Z);const se=Z;se.redirectedFrom=ee;let ie;return!W&&zye(o,U,Z)&&(ie=Ba(16,{to:se,from:U}),z(U,U,!0,!1)),(ie?Promise.resolve(ie):M(se,U)).catch(de=>Sr(de)?Sr(de,2)?de:L(de):k(de,se,U)).then(de=>{if(de){if(Sr(de,2))return w(Pt({replace:G},S(de.to),{state:typeof de.to=="object"?Pt({},Q,de.to.state):Q,force:W}),ee||se)}else de=A(se,U,!0,G,Q);return E(se,U,de),de})}function P(K,ee){const Z=$(K,ee);return Z?Promise.reject(Z):Promise.resolve()}function T(K){const ee=Y.values().next().value;return ee&&typeof ee.runWithContext=="function"?ee.runWithContext(K):K()}function M(K,ee){let Z;const[U,Q,W]=P1e(K,ee);Z=uv(U.reverse(),"beforeRouteLeave",K,ee);for(const te of U)te.leaveGuards.forEach(se=>{Z.push(ai(se,K,ee))});const G=P.bind(null,K,ee);return Z.push(G),J(Z).then(()=>{Z=[];for(const te of i.list())Z.push(ai(te,K,ee));return Z.push(G),J(Z)}).then(()=>{Z=uv(Q,"beforeRouteUpdate",K,ee);for(const te of Q)te.updateGuards.forEach(se=>{Z.push(ai(se,K,ee))});return Z.push(G),J(Z)}).then(()=>{Z=[];for(const te of W)if(te.beforeEnter)if(Xo(te.beforeEnter))for(const se of te.beforeEnter)Z.push(ai(se,K,ee));else Z.push(ai(te.beforeEnter,K,ee));return Z.push(G),J(Z)}).then(()=>(K.matched.forEach(te=>te.enterCallbacks={}),Z=uv(W,"beforeRouteEnter",K,ee,T),Z.push(G),J(Z))).then(()=>{Z=[];for(const te of l.list())Z.push(ai(te,K,ee));return Z.push(G),J(Z)}).catch(te=>Sr(te,8)?te:Promise.reject(te))}function E(K,ee,Z){a.list().forEach(U=>T(()=>U(K,ee,Z)))}function A(K,ee,Z,U,Q){const W=$(K,ee);if(W)return W;const G=ee===ti,te=Xl?history.state:{};Z&&(U||G?r.replace(K.fullPath,Pt({scroll:G&&te&&te.scroll},Q)):r.push(K.fullPath,Q)),s.value=K,z(K,ee,Z,G),L()}let R;function H(){R||(R=r.listen((K,ee,Z)=>{if(!X.listening)return;const U=y(K),Q=O(U);if(Q){w(Pt(Q,{replace:!0}),U).catch(Us);return}c=U;const W=s.value;Xl&&Xye(N3(W.fullPath,Z.delta),wh()),M(U,W).catch(G=>Sr(G,12)?G:Sr(G,2)?(w(G.to,U).then(te=>{Sr(te,20)&&!Z.delta&&Z.type===Mc.pop&&r.go(-1,!1)}).catch(Us),Promise.reject()):(Z.delta&&r.go(-Z.delta,!1),k(G,U,W))).then(G=>{G=G||A(U,W,!1),G&&(Z.delta&&!Sr(G,8)?r.go(-Z.delta,!1):Z.type===Mc.pop&&Sr(G,20)&&r.go(-1,!1)),E(U,W,G)}).catch(Us)}))}let _=ps(),B=ps(),N;function k(K,ee,Z){L(K);const U=B.list();return U.length?U.forEach(Q=>Q(K,ee,Z)):console.error(K),Promise.reject(K)}function F(){return N&&s.value!==ti?Promise.resolve():new Promise((K,ee)=>{_.add([K,ee])})}function L(K){return N||(N=!K,H(),_.list().forEach(([ee,Z])=>K?Z(K):ee()),_.reset()),K}function z(K,ee,Z,U){const{scrollBehavior:Q}=e;if(!Xl||!Q)return Promise.resolve();const W=!Z&&Yye(N3(K.fullPath,0))||(U||!Z)&&history.state&&history.state.scroll||null;return ot().then(()=>Q(K,ee,W)).then(G=>G&&Gye(G)).catch(G=>k(G,K,ee))}const j=K=>r.go(K);let q;const Y=new Set,X={currentRoute:s,listening:!0,addRoute:h,removeRoute:v,clearRoutes:t.clearRoutes,hasRoute:b,getRoutes:g,resolve:y,options:e,push:x,replace:C,go:j,back:()=>j(-1),forward:()=>j(1),beforeEach:i.add,beforeResolve:l.add,afterEach:a.add,onError:B.add,isReady:F,install(K){const ee=this;K.component("RouterLink",S1e),K.component("RouterView",w1e),K.config.globalProperties.$router=ee,Object.defineProperty(K.config.globalProperties,"$route",{enumerable:!0,get:()=>Et(s)}),Xl&&!q&&s.value===ti&&(q=!0,x(r.location).catch(Q=>{}));const Z={};for(const Q in ti)Object.defineProperty(Z,Q,{get:()=>s.value[Q],enumerable:!0});K.provide(DS,ee),K.provide(B_,gO(Z)),K.provide(a0,s);const U=K.unmount;Y.add(K),K.unmount=function(){Y.delete(K),Y.size<1&&(c=ti,R&&R(),R=null,s.value=ti,q=!1,N=!1),U()}}};function J(K){return K.reduce((ee,Z)=>ee.then(()=>T(Z)),Promise.resolve())}return X}function P1e(e,t){const n=[],o=[],r=[],i=Math.max(t.matched.length,e.matched.length);for(let l=0;l<i;l++){const a=t.matched[l];a&&(e.matched.find(c=>Da(c,a))?o.push(a):n.push(a));const s=e.matched[l];s&&(t.matched.find(c=>Da(c,s))||r.push(s))}return[n,o,r]}const I1e={class:"not-found-wrapper"},T1e=re({__name:"index",setup(e){const t=()=>{NS.replace("/")};return(n,o)=>{const r=xo("a-button"),i=xo("a-result");return di(),Yl("div",I1e,[p(i,{status:"404",title:"404","sub-title":"Sorry, the page you visited does not exist."},{extra:vn(()=>[p(r,{onClick:t,type:"primary"},{default:vn(()=>[Lt("Back Home")]),_:1})]),_:1})])}}}),E1e=xh(T1e,[["__scopeId","data-v-aef52a59"]]),BS=e=>(X7("data-v-1bbbedd4"),e=e(),Y7(),e),M1e={class:"view-wrapper"},_1e={style:{"margin-top":"10vh",padding:"32px"}},A1e={class:"chat-box-placeholder"},R1e=["data-seg-id"],D1e={class:"actions-box"},B1e={class:"left-actions"},N1e={class:"config-content"},k1e={class:"config-block"},F1e=BS(()=>tn("h4",{style:{"font-weight":"500"}},"Page Max Width:",-1)),L1e={class:"config-block"},z1e=BS(()=>tn("h4",{style:{"font-weight":"500"}},"Show Realtime Buffer:",-1)),H1e={class:"config-block"},j1e=BS(()=>tn("h4",{style:{"font-weight":"500"}},"Text Font Size:",-1)),W1e={style:{display:"flex","justify-content":"end"}},V1e="Please check if the microphone is available before the experience, specify the audio language and translation language, click the switch button to start recording, and you can get the recognized and translated text in real time.",K1e=re({__name:"index",setup(e){const t=Tc(),n=window.location.host;let o="ws";n.startsWith("127.0.0.1")||n.startsWith("localhost")?o="ws":o="wss";const r=`${o}://`+n+"/ws?";console.warn("ws_url: ",r);const i=oe(null),l=async Y=>{console.warn("start websocket ..."),i.value&&i.value.readyState!==WebSocket.CLOSED&&i.value.close();const X=`${r}${Y}`;i.value=new WebSocket(X),i.value.binaryType="arraybuffer",console.warn("created web socket ..."),i.value.addEventListener("open",()=>{console.log("WebSocket 连接成功"),v(),h.value=!0}),i.value.addEventListener("close",()=>{console.log("WebSocket 连接已关闭")}),i.value.onclose=J=>{console.log("code:",J.code,"reason:",J.reason,"wasClean:",J.wasClean),console.log("WebSocket 连接已关闭:",J)},i.value.addEventListener("error",J=>{console.error("WebSocket 连接错误:",J)}),i.value.addEventListener("message",J=>{const K=JSON.parse(J.data);console.log("WebSocket 收到消息:",K),K&&K.result&&E(K.result)})},a=async()=>{i.value&&(await i.value.close(),i.value=null)},s=oe(null),c=oe(null),u=oe(null),d=oe(null),f=oe(null),h=oe(!1),v=async()=>{try{const Y=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:16e3,channelCount:1}});s.value=Y;const X=new AudioContext({sampleRate:16e3});u.value=X;const J=X.createMediaStreamSource(Y);d.value=J;const K=X.createScriptProcessor(4096,1,1);f.value=K,J.connect(K),K.connect(X.destination),K.onaudioprocess=ee=>{if(!h.value||!i.value||i.value.readyState!==WebSocket.OPEN)return;const Z=ee.inputBuffer.getChannelData(0),U=new Int16Array(Z.length);for(let Q=0;Q<Z.length;Q++)U[Q]=Math.max(-1,Math.min(1,Z[Q]))*32767;g(U)},h.value=!0,console.log("音频捕获已启动")}catch(Y){console.error("音频捕获失败:",Y)}},g=Y=>{if(i.value)i.value.send(Y),console.log("WebSocket send audio chunk success");else{console.error("WebSocket not initialized, sendAudioChunk failed");return}},b=async()=>{console.log("requirePermissionAction");try{if(!i.value||i.value.readyState!==WebSocket.OPEN){console.log("current lang_str : ",x.value);const Y=x.value;A(),await l(Y)}}catch(Y){console.log("Error accessing microphone: ",Y)}};je(()=>{console.log("[translator]: mounted"),z.value=t.$state.fs,L.value=t.$state.width_max,F.value=t.$state.vad}),xn(()=>{console.log("[HomePage]: unmounted"),i.value&&i.value.close(),c.value&&y()});const y=()=>{h.value=!1,a(),console.log("音频捕获已停止"),f.value&&(f.value.disconnect(),f.value=null),d.value&&(d.value.disconnect(),d.value=null),s.value&&(s.value.getTracks().forEach(Y=>Y.stop()),s.value=null),u.value&&(u.value.close(),u.value=null),console.log("录音已停止")},S=async Y=>{console.log(`selected ${Y}`),h.value=!1,await y(),console.log("new lang_str: ",Y),console.log("trans_lang : ",x.value)},$=Y=>{h.value=Y,Y?b():y()},x=oe("from=en&to=zh"),C=[{value:"from=en&to=zh",label:"English -> Chinese"},{value:"from=zh&to=en",label:"Chinese -> English"}],O=[],w=ct([]),P=oe(""),T=oe(""),M=oe(""),E=Y=>{if(console.log("updateViewData: ",Y),Y){const{context:X,from:J,to:K,seg_id:ee,partial:Z,tranContent:U}=Y;if(Z==!0){P.value=X,T.value=U,M.value=ee;return}else{const Q={context:X,from:J,to:K,seg_id:ee,partial:Z,tranContent:U};w.length>100&&w.splice(0,40),w.push(Q);const W=`[src]: ${X}
496
  ${"-".repeat(80)}
497
  [dst]: ${U}
498
 
499
  `;O.push(W),P.value="",T.value="",M.value=""}}_()},A=()=>{w.splice(0,w.length),O.splice(0,O.length)},R=async()=>{const Y=O.join(`
500
- `),X=new Blob([Y],{type:"text/plain"}),J=URL.createObjectURL(X),K=document.createElement("a");K.href=J,K.download="record.txt",document.body.appendChild(K),K.click(),document.body.removeChild(K),URL.revokeObjectURL(J)},H=oe(null),_=()=>{ot(()=>{H.value&&(H.value.scrollTop=H.value.scrollHeight+144)})};be(()=>[...w],()=>{_()},{deep:!0}),be(()=>T.value,()=>{_()});const B=oe(!1),N=()=>{B.value=!0},k=()=>{B.value=!1,F.value!=t.$state.vad&&(t.$state.vad=F.value,c.value&&y())},F=oe(.3),L=oe(!1),z=oe("trans-font-size-18"),j=oe(!0),q=Y=>{console.log("onFontSizeChange",Y.target.value),z.value=Y.target.value,t.$state.fs=Y.target.value};return(Y,X)=>{const J=xo("a-radio"),K=xo("a-radio-group"),ee=xo("a-switch"),Z=xo("a-button"),U=xo("a-popover"),Q=xo("a-select"),W=xo("a-popconfirm"),G=xo("a-card");return di(),Yl("div",M1e,[tn("div",{class:Pr(["content-wrapper",L.value?"wrapper-width-auto":"wrapper-width-fixed"])},[tn("div",_1e,[p(G,{bordered:!1,style:{width:"100%","min-width":"100%"}},{actions:vn(()=>[tn("div",D1e,[tn("div",B1e,[p(U,{open:B.value,"onUpdate:open":X[4]||(X[4]=te=>B.value=te),placement:"topLeft",trigger:"click"},{content:vn(()=>[tn("div",N1e,[LA("",!0),tn("div",k1e,[F1e,p(ee,{checked:L.value,"onUpdate:checked":X[1]||(X[1]=te=>L.value=te)},null,8,["checked"])]),tn("div",L1e,[z1e,p(ee,{checked:j.value,"onUpdate:checked":X[2]||(X[2]=te=>j.value=te)},null,8,["checked"])]),tn("div",H1e,[j1e,p(K,{value:z.value,"onUpdate:value":X[3]||(X[3]=te=>z.value=te),onChange:q},{default:vn(()=>[p(J,{value:"trans-font-size-16"},{default:vn(()=>[Lt("Small")]),_:1}),p(J,{value:"trans-font-size-18"},{default:vn(()=>[Lt("Default")]),_:1}),p(J,{value:"trans-font-size-20"},{default:vn(()=>[Lt("Normal")]),_:1}),p(J,{value:"trans-font-size-22"},{default:vn(()=>[Lt("Medium")]),_:1}),p(J,{value:"trans-font-size-24"},{default:vn(()=>[Lt("Large")]),_:1})]),_:1},8,["value"])])]),tn("div",W1e,[p(Z,{type:"primary",onClick:k},{default:vn(()=>[Lt("Done")]),_:1})])]),default:vn(()=>[p(Z,{type:"dashed",shape:"circle",size:"middle",onClick:N},{icon:vn(()=>[p(Et(vme))]),_:1})]),_:1},8,["open"]),p(Q,{value:x.value,"onUpdate:value":X[5]||(X[5]=te=>x.value=te),style:{width:"240px"},placeholder:"Select Language",options:C,onChange:S},null,8,["value"]),p(W,{title:"save the current text content?",onConfirm:R,"ok-text":"Yes","cancel-text":"No"},{icon:vn(()=>[p(Et(sme),{style:{color:"red"}})]),default:vn(()=>[p(Z,{type:"dashed",shape:"circle",size:"middle"},{icon:vn(()=>[p(Et(MM))]),_:1})]),_:1})]),p(ee,{key:"switcher",size:"large",type:"danger","checked-children":"ON","un-checked-children":"OFF",checked:h.value,"onUpdate:checked":X[6]||(X[6]=te=>h.value=te),onChange:$},null,8,["checked"])])]),default:vn(()=>[fn(tn("div",A1e,ns(V1e),512),[[mn,!(w.length||P.value)]]),fn(tn("div",{class:"trans-list",ref_key:"transListRef",ref:H},[(di(!0),Yl(Ve,null,pA(w,te=>(di(),Yl("div",{key:te.context,class:Pr(["node"]),"data-seg-id":te.seg_id},[tn("div",{class:Pr(["trans-src-lang",z.value])},ns(te.context),3),tn("div",{class:Pr(["trans-dst-lang",z.value])},ns(te.tranContent),3)],8,R1e))),128)),fn((di(),Yl("div",{class:"node current_node",key:M.value},[tn("div",{class:Pr(["trans-src-lang",z.value])},ns(P.value),3),tn("div",{class:Pr(["trans-dst-lang",z.value])},ns(T.value),3)])),[[mn,j.value]])],512),[[mn,w.length||P.value]])]),_:1})])],2)])}}}),U1e=xh(K1e,[["__scopeId","data-v-1bbbedd4"]]),G1e=AS({id:"play_state",persist:!1,state:()=>{const e=Tc();return console.log("configState",e.$state.role_name),{current_state:"init",video_url:"",urls:{waiting:e.$state.roles_resources[e.$state.role_name].waiting,listening:e.$state.roles_resources[e.$state.role_name].listening,thinking:e.$state.roles_resources[e.$state.role_name].thinking,talking:""}}},actions:{changeRole(e){this.$patch(t=>{const n=Tc();t.urls.waiting=n.$state.roles_resources[n.$state.role_name].waiting,t.urls.listening=n.$state.roles_resources[n.$state.role_name].listening,t.urls.thinking=n.$state.roles_resources[n.$state.role_name].thinking})},changeState(e){if(["waiting","listening","thinking","talking","init"].indexOf(e)==-1){console.error("invalid state",e);return}this.$patch(t=>{t.video_url=t.urls[e],t.current_state=e})},changeTalkingVideoUrl(e){this.$patch(t=>{t.urls.talking=e})}}}),X1e={class:"content-wrapper"},Y1e=re({__name:"index",setup(e){const t=Tc();return G1e(),je(()=>{console.log("config",t.$state)}),oe(t.$state.file_type),oe(t.$state.role_name),(n,o)=>{const r=xo("a-result");return di(),Yl("div",X1e,[p(r,{style:{width:"100%"},title:"Settings"})])}}}),q1e=xh(Y1e,[["__scopeId","data-v-c39ab0d6"]]),Z1e=[{name:"home",path:"/",component:U1e,meta:{requiresAgreement:!1}},{name:"settings",path:"/settings",component:q1e},{name:"404",path:"/404",component:E1e}],NS=O1e({history:Jye("/app/"),routes:Z1e});NS.beforeEach((e,t,n)=>{console.log("=============== router to : ",e),e.matched.length===0?n({name:"404"}):n()});const N_=aye();N_.use(yye);rP(Cye).use(N_).use(NS).use(w0e).mount("#app")});export default Q1e();
 
492
  * vue-router v4.4.3
493
  * (c) 2024 Eduardo San Martin Morote
494
  * @license MIT
495
+ */const Xl=typeof document<"u";function xye(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const Pt=Object.assign;function sv(e,t){const n={};for(const o in t){const r=t[o];n[o]=Xo(r)?r.map(e):e(r)}return n}const Us=()=>{},Xo=Array.isArray,w_=/#/g,wye=/&/g,Oye=/\//g,Pye=/=/g,Iye=/\?/g,O_=/\+/g,Tye=/%5B/g,Eye=/%5D/g,P_=/%5E/g,Mye=/%60/g,I_=/%7B/g,_ye=/%7C/g,T_=/%7D/g,Aye=/%20/g;function RS(e){return encodeURI(""+e).replace(_ye,"|").replace(Tye,"[").replace(Eye,"]")}function Rye(e){return RS(e).replace(I_,"{").replace(T_,"}").replace(P_,"^")}function i0(e){return RS(e).replace(O_,"%2B").replace(Aye,"+").replace(w_,"%23").replace(wye,"%26").replace(Mye,"`").replace(I_,"{").replace(T_,"}").replace(P_,"^")}function Dye(e){return i0(e).replace(Pye,"%3D")}function Bye(e){return RS(e).replace(w_,"%23").replace(Iye,"%3F")}function Nye(e){return e==null?"":Bye(e).replace(Oye,"%2F")}function Ec(e){try{return decodeURIComponent(""+e)}catch{}return""+e}const kye=/\/$/,Fye=e=>e.replace(kye,"");function cv(e,t,n="/"){let o,r={},i="",l="";const a=t.indexOf("#");let s=t.indexOf("?");return a<s&&a>=0&&(s=-1),s>-1&&(o=t.slice(0,s),i=t.slice(s+1,a>-1?a:t.length),r=e(i)),a>-1&&(o=o||t.slice(0,a),l=t.slice(a,t.length)),o=jye(o??t,n),{fullPath:o+(i&&"?")+i+l,path:o,query:r,hash:Ec(l)}}function Lye(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function D3(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function zye(e,t,n){const o=t.matched.length-1,r=n.matched.length-1;return o>-1&&o===r&&Da(t.matched[o],n.matched[r])&&E_(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Da(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function E_(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!Hye(e[n],t[n]))return!1;return!0}function Hye(e,t){return Xo(e)?B3(e,t):Xo(t)?B3(t,e):e===t}function B3(e,t){return Xo(t)?e.length===t.length&&e.every((n,o)=>n===t[o]):e.length===1&&e[0]===t}function jye(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),o=e.split("/"),r=o[o.length-1];(r===".."||r===".")&&o.push("");let i=n.length-1,l,a;for(l=0;l<o.length;l++)if(a=o[l],a!==".")if(a==="..")i>1&&i--;else break;return n.slice(0,i).join("/")+"/"+o.slice(l).join("/")}const ti={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};var Mc;(function(e){e.pop="pop",e.push="push"})(Mc||(Mc={}));var Gs;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Gs||(Gs={}));function Wye(e){if(!e)if(Xl){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),Fye(e)}const Vye=/^[^#]+#/;function Kye(e,t){return e.replace(Vye,"#")+t}function Uye(e,t){const n=document.documentElement.getBoundingClientRect(),o=e.getBoundingClientRect();return{behavior:t.behavior,left:o.left-n.left-(t.left||0),top:o.top-n.top-(t.top||0)}}const wh=()=>({left:window.scrollX,top:window.scrollY});function Gye(e){let t;if("el"in e){const n=e.el,o=typeof n=="string"&&n.startsWith("#"),r=typeof n=="string"?o?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!r)return;t=Uye(r,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function N3(e,t){return(history.state?history.state.position-t:-1)+e}const l0=new Map;function Xye(e,t){l0.set(e,t)}function Yye(e){const t=l0.get(e);return l0.delete(e),t}let qye=()=>location.protocol+"//"+location.host;function M_(e,t){const{pathname:n,search:o,hash:r}=t,i=e.indexOf("#");if(i>-1){let a=r.includes(e.slice(i))?e.slice(i).length:1,s=r.slice(a);return s[0]!=="/"&&(s="/"+s),D3(s,"")}return D3(n,e)+o+r}function Zye(e,t,n,o){let r=[],i=[],l=null;const a=({state:f})=>{const h=M_(e,location),v=n.value,g=t.value;let b=0;if(f){if(n.value=h,t.value=f,l&&l===v){l=null;return}b=g?f.position-g.position:0}else o(h);r.forEach(y=>{y(n.value,v,{delta:b,type:Mc.pop,direction:b?b>0?Gs.forward:Gs.back:Gs.unknown})})};function s(){l=n.value}function c(f){r.push(f);const h=()=>{const v=r.indexOf(f);v>-1&&r.splice(v,1)};return i.push(h),h}function u(){const{history:f}=window;f.state&&f.replaceState(Pt({},f.state,{scroll:wh()}),"")}function d(){for(const f of i)f();i=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",u)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",u,{passive:!0}),{pauseListeners:s,listen:c,destroy:d}}function k3(e,t,n,o=!1,r=!1){return{back:e,current:t,forward:n,replaced:o,position:window.history.length,scroll:r?wh():null}}function Qye(e){const{history:t,location:n}=window,o={value:M_(e,n)},r={value:t.state};r.value||i(o.value,{back:null,current:o.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(s,c,u){const d=e.indexOf("#"),f=d>-1?(n.host&&document.querySelector("base")?e:e.slice(d))+s:qye()+e+s;try{t[u?"replaceState":"pushState"](c,"",f),r.value=c}catch(h){console.error(h),n[u?"replace":"assign"](f)}}function l(s,c){const u=Pt({},t.state,k3(r.value.back,s,r.value.forward,!0),c,{position:r.value.position});i(s,u,!0),o.value=s}function a(s,c){const u=Pt({},r.value,t.state,{forward:s,scroll:wh()});i(u.current,u,!0);const d=Pt({},k3(o.value,s,null),{position:u.position+1},c);i(s,d,!1),o.value=s}return{location:o,state:r,push:a,replace:l}}function Jye(e){e=Wye(e);const t=Qye(e),n=Zye(e,t.state,t.location,t.replace);function o(i,l=!0){l||n.pauseListeners(),history.go(i)}const r=Pt({location:"",base:e,go:o,createHref:Kye.bind(null,e)},t,n);return Object.defineProperty(r,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(r,"state",{enumerable:!0,get:()=>t.state.value}),r}function e1e(e){return typeof e=="string"||e&&typeof e=="object"}function __(e){return typeof e=="string"||typeof e=="symbol"}const A_=Symbol("");var F3;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(F3||(F3={}));function Ba(e,t){return Pt(new Error,{type:e,[A_]:!0},t)}function Sr(e,t){return e instanceof Error&&A_ in e&&(t==null||!!(e.type&t))}const L3="[^/]+?",t1e={sensitive:!1,strict:!1,start:!0,end:!0},n1e=/[.+*?^${}()[\]/\\]/g;function o1e(e,t){const n=Pt({},t1e,t),o=[];let r=n.start?"^":"";const i=[];for(const c of e){const u=c.length?[]:[90];n.strict&&!c.length&&(r+="/");for(let d=0;d<c.length;d++){const f=c[d];let h=40+(n.sensitive?.25:0);if(f.type===0)d||(r+="/"),r+=f.value.replace(n1e,"\\$&"),h+=40;else if(f.type===1){const{value:v,repeatable:g,optional:b,regexp:y}=f;i.push({name:v,repeatable:g,optional:b});const S=y||L3;if(S!==L3){h+=10;try{new RegExp(`(${S})`)}catch(x){throw new Error(`Invalid custom RegExp for param "${v}" (${S}): `+x.message)}}let $=g?`((?:${S})(?:/(?:${S}))*)`:`(${S})`;d||($=b&&c.length<2?`(?:/${$})`:"/"+$),b&&($+="?"),r+=$,h+=20,b&&(h+=-8),g&&(h+=-20),S===".*"&&(h+=-50)}u.push(h)}o.push(u)}if(n.strict&&n.end){const c=o.length-1;o[c][o[c].length-1]+=.7000000000000001}n.strict||(r+="/?"),n.end?r+="$":n.strict&&(r+="(?:/|$)");const l=new RegExp(r,n.sensitive?"":"i");function a(c){const u=c.match(l),d={};if(!u)return null;for(let f=1;f<u.length;f++){const h=u[f]||"",v=i[f-1];d[v.name]=h&&v.repeatable?h.split("/"):h}return d}function s(c){let u="",d=!1;for(const f of e){(!d||!u.endsWith("/"))&&(u+="/"),d=!1;for(const h of f)if(h.type===0)u+=h.value;else if(h.type===1){const{value:v,repeatable:g,optional:b}=h,y=v in c?c[v]:"";if(Xo(y)&&!g)throw new Error(`Provided param "${v}" is an array but it is not repeatable (* or + modifiers)`);const S=Xo(y)?y.join("/"):y;if(!S)if(b)f.length<2&&(u.endsWith("/")?u=u.slice(0,-1):d=!0);else throw new Error(`Missing required param "${v}"`);u+=S}}return u||"/"}return{re:l,score:o,keys:i,parse:a,stringify:s}}function r1e(e,t){let n=0;for(;n<e.length&&n<t.length;){const o=t[n]-e[n];if(o)return o;n++}return e.length<t.length?e.length===1&&e[0]===40+40?-1:1:e.length>t.length?t.length===1&&t[0]===40+40?1:-1:0}function R_(e,t){let n=0;const o=e.score,r=t.score;for(;n<o.length&&n<r.length;){const i=r1e(o[n],r[n]);if(i)return i;n++}if(Math.abs(r.length-o.length)===1){if(z3(o))return 1;if(z3(r))return-1}return r.length-o.length}function z3(e){const t=e[e.length-1];return e.length>0&&t[t.length-1]<0}const i1e={type:0,value:""},l1e=/[a-zA-Z0-9_]/;function a1e(e){if(!e)return[[]];if(e==="/")return[[i1e]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(h){throw new Error(`ERR (${n})/"${c}": ${h}`)}let n=0,o=n;const r=[];let i;function l(){i&&r.push(i),i=[]}let a=0,s,c="",u="";function d(){c&&(n===0?i.push({type:0,value:c}):n===1||n===2||n===3?(i.length>1&&(s==="*"||s==="+")&&t(`A repeatable param (${c}) must be alone in its segment. eg: '/:ids+.`),i.push({type:1,value:c,regexp:u,repeatable:s==="*"||s==="+",optional:s==="*"||s==="?"})):t("Invalid state to consume buffer"),c="")}function f(){c+=s}for(;a<e.length;){if(s=e[a++],s==="\\"&&n!==2){o=n,n=4;continue}switch(n){case 0:s==="/"?(c&&d(),l()):s===":"?(d(),n=1):f();break;case 4:f(),n=o;break;case 1:s==="("?n=2:l1e.test(s)?f():(d(),n=0,s!=="*"&&s!=="?"&&s!=="+"&&a--);break;case 2:s===")"?u[u.length-1]=="\\"?u=u.slice(0,-1)+s:n=3:u+=s;break;case 3:d(),n=0,s!=="*"&&s!=="?"&&s!=="+"&&a--,u="";break;default:t("Unknown state");break}}return n===2&&t(`Unfinished custom RegExp for param "${c}"`),d(),l(),r}function s1e(e,t,n){const o=o1e(a1e(e.path),n),r=Pt(o,{record:e,parent:t,children:[],alias:[]});return t&&!r.record.aliasOf==!t.record.aliasOf&&t.children.push(r),r}function c1e(e,t){const n=[],o=new Map;t=W3({strict:!1,end:!0,sensitive:!1},t);function r(d){return o.get(d)}function i(d,f,h){const v=!h,g=u1e(d);g.aliasOf=h&&h.record;const b=W3(t,d),y=[g];if("alias"in d){const x=typeof d.alias=="string"?[d.alias]:d.alias;for(const C of x)y.push(Pt({},g,{components:h?h.record.components:g.components,path:C,aliasOf:h?h.record:g}))}let S,$;for(const x of y){const{path:C}=x;if(f&&C[0]!=="/"){const O=f.record.path,w=O[O.length-1]==="/"?"":"/";x.path=f.record.path+(C&&w+C)}if(S=s1e(x,f,b),h?h.alias.push(S):($=$||S,$!==S&&$.alias.push(S),v&&d.name&&!j3(S)&&l(d.name)),D_(S)&&s(S),g.children){const O=g.children;for(let w=0;w<O.length;w++)i(O[w],S,h&&h.children[w])}h=h||S}return $?()=>{l($)}:Us}function l(d){if(__(d)){const f=o.get(d);f&&(o.delete(d),n.splice(n.indexOf(f),1),f.children.forEach(l),f.alias.forEach(l))}else{const f=n.indexOf(d);f>-1&&(n.splice(f,1),d.record.name&&o.delete(d.record.name),d.children.forEach(l),d.alias.forEach(l))}}function a(){return n}function s(d){const f=p1e(d,n);n.splice(f,0,d),d.record.name&&!j3(d)&&o.set(d.record.name,d)}function c(d,f){let h,v={},g,b;if("name"in d&&d.name){if(h=o.get(d.name),!h)throw Ba(1,{location:d});b=h.record.name,v=Pt(H3(f.params,h.keys.filter($=>!$.optional).concat(h.parent?h.parent.keys.filter($=>$.optional):[]).map($=>$.name)),d.params&&H3(d.params,h.keys.map($=>$.name))),g=h.stringify(v)}else if(d.path!=null)g=d.path,h=n.find($=>$.re.test(g)),h&&(v=h.parse(g),b=h.record.name);else{if(h=f.name?o.get(f.name):n.find($=>$.re.test(f.path)),!h)throw Ba(1,{location:d,currentLocation:f});b=h.record.name,v=Pt({},f.params,d.params),g=h.stringify(v)}const y=[];let S=h;for(;S;)y.unshift(S.record),S=S.parent;return{name:b,path:g,params:v,matched:y,meta:f1e(y)}}e.forEach(d=>i(d));function u(){n.length=0,o.clear()}return{addRoute:i,resolve:c,removeRoute:l,clearRoutes:u,getRoutes:a,getRecordMatcher:r}}function H3(e,t){const n={};for(const o of t)o in e&&(n[o]=e[o]);return n}function u1e(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:d1e(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}}}function d1e(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const o in e.components)t[o]=typeof n=="object"?n[o]:n;return t}function j3(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function f1e(e){return e.reduce((t,n)=>Pt(t,n.meta),{})}function W3(e,t){const n={};for(const o in e)n[o]=o in t?t[o]:e[o];return n}function p1e(e,t){let n=0,o=t.length;for(;n!==o;){const i=n+o>>1;R_(e,t[i])<0?o=i:n=i+1}const r=h1e(e);return r&&(o=t.lastIndexOf(r,o-1)),o}function h1e(e){let t=e;for(;t=t.parent;)if(D_(t)&&R_(e,t)===0)return t}function D_({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function g1e(e){const t={};if(e===""||e==="?")return t;const o=(e[0]==="?"?e.slice(1):e).split("&");for(let r=0;r<o.length;++r){const i=o[r].replace(O_," "),l=i.indexOf("="),a=Ec(l<0?i:i.slice(0,l)),s=l<0?null:Ec(i.slice(l+1));if(a in t){let c=t[a];Xo(c)||(c=t[a]=[c]),c.push(s)}else t[a]=s}return t}function V3(e){let t="";for(let n in e){const o=e[n];if(n=Dye(n),o==null){o!==void 0&&(t+=(t.length?"&":"")+n);continue}(Xo(o)?o.map(i=>i&&i0(i)):[o&&i0(o)]).forEach(i=>{i!==void 0&&(t+=(t.length?"&":"")+n,i!=null&&(t+="="+i))})}return t}function v1e(e){const t={};for(const n in e){const o=e[n];o!==void 0&&(t[n]=Xo(o)?o.map(r=>r==null?null:""+r):o==null?o:""+o)}return t}const m1e=Symbol(""),K3=Symbol(""),DS=Symbol(""),B_=Symbol(""),a0=Symbol("");function ps(){let e=[];function t(o){return e.push(o),()=>{const r=e.indexOf(o);r>-1&&e.splice(r,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function ai(e,t,n,o,r,i=l=>l()){const l=o&&(o.enterCallbacks[r]=o.enterCallbacks[r]||[]);return()=>new Promise((a,s)=>{const c=f=>{f===!1?s(Ba(4,{from:n,to:t})):f instanceof Error?s(f):e1e(f)?s(Ba(2,{from:t,to:f})):(l&&o.enterCallbacks[r]===l&&typeof f=="function"&&l.push(f),a())},u=i(()=>e.call(o&&o.instances[r],t,n,c));let d=Promise.resolve(u);e.length<3&&(d=d.then(c)),d.catch(f=>s(f))})}function uv(e,t,n,o,r=i=>i()){const i=[];for(const l of e)for(const a in l.components){let s=l.components[a];if(!(t!=="beforeRouteEnter"&&!l.instances[a]))if(b1e(s)){const u=(s.__vccOpts||s)[t];u&&i.push(ai(u,n,o,l,a,r))}else{let c=s();i.push(()=>c.then(u=>{if(!u)return Promise.reject(new Error(`Couldn't resolve component "${a}" at "${l.path}"`));const d=xye(u)?u.default:u;l.components[a]=d;const h=(d.__vccOpts||d)[t];return h&&ai(h,n,o,l,a,r)()}))}}return i}function b1e(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function U3(e){const t=We(DS),n=We(B_),o=I(()=>{const s=Et(e.to);return t.resolve(s)}),r=I(()=>{const{matched:s}=o.value,{length:c}=s,u=s[c-1],d=n.matched;if(!u||!d.length)return-1;const f=d.findIndex(Da.bind(null,u));if(f>-1)return f;const h=G3(s[c-2]);return c>1&&G3(u)===h&&d[d.length-1].path!==h?d.findIndex(Da.bind(null,s[c-2])):f}),i=I(()=>r.value>-1&&C1e(n.params,o.value.params)),l=I(()=>r.value>-1&&r.value===n.matched.length-1&&E_(n.params,o.value.params));function a(s={}){return $1e(s)?t[Et(e.replace)?"replace":"push"](Et(e.to)).catch(Us):Promise.resolve()}return{route:o,href:I(()=>o.value.href),isActive:i,isExactActive:l,navigate:a}}const y1e=re({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:U3,setup(e,{slots:t}){const n=ct(U3(e)),{options:o}=We(DS),r=I(()=>({[X3(e.activeClass,o.linkActiveClass,"router-link-active")]:n.isActive,[X3(e.exactActiveClass,o.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const i=t.default&&t.default(n);return e.custom?i:Sa("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:r.value},i)}}}),S1e=y1e;function $1e(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function C1e(e,t){for(const n in t){const o=t[n],r=e[n];if(typeof o=="string"){if(o!==r)return!1}else if(!Xo(r)||r.length!==o.length||o.some((i,l)=>i!==r[l]))return!1}return!0}function G3(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const X3=(e,t,n)=>e??t??n,x1e=re({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const o=We(a0),r=I(()=>e.route||o.value),i=We(K3,0),l=I(()=>{let c=Et(i);const{matched:u}=r.value;let d;for(;(d=u[c])&&!d.components;)c++;return c}),a=I(()=>r.value.matched[l.value]);Ge(K3,I(()=>l.value+1)),Ge(m1e,a),Ge(a0,r);const s=oe();return be(()=>[s.value,a.value,e.name],([c,u,d],[f,h,v])=>{u&&(u.instances[d]=c,h&&h!==u&&c&&c===f&&(u.leaveGuards.size||(u.leaveGuards=h.leaveGuards),u.updateGuards.size||(u.updateGuards=h.updateGuards))),c&&u&&(!h||!Da(u,h)||!f)&&(u.enterCallbacks[d]||[]).forEach(g=>g(c))},{flush:"post"}),()=>{const c=r.value,u=e.name,d=a.value,f=d&&d.components[u];if(!f)return Y3(n.default,{Component:f,route:c});const h=d.props[u],v=h?h===!0?c.params:typeof h=="function"?h(c):h:null,b=Sa(f,Pt({},v,t,{onVnodeUnmounted:y=>{y.component.isUnmounted&&(d.instances[u]=null)},ref:s}));return Y3(n.default,{Component:b,route:c})||b}}});function Y3(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const w1e=x1e;function O1e(e){const t=c1e(e.routes,e),n=e.parseQuery||g1e,o=e.stringifyQuery||V3,r=e.history,i=ps(),l=ps(),a=ps(),s=ne(ti);let c=ti;Xl&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const u=sv.bind(null,K=>""+K),d=sv.bind(null,Nye),f=sv.bind(null,Ec);function h(K,ee){let Z,U;return __(K)?(Z=t.getRecordMatcher(K),U=ee):U=K,t.addRoute(U,Z)}function v(K){const ee=t.getRecordMatcher(K);ee&&t.removeRoute(ee)}function g(){return t.getRoutes().map(K=>K.record)}function b(K){return!!t.getRecordMatcher(K)}function y(K,ee){if(ee=Pt({},ee||s.value),typeof K=="string"){const te=cv(n,K,ee.path),se=t.resolve({path:te.path},ee),ie=r.createHref(te.fullPath);return Pt(te,se,{params:f(se.params),hash:Ec(te.hash),redirectedFrom:void 0,href:ie})}let Z;if(K.path!=null)Z=Pt({},K,{path:cv(n,K.path,ee.path).path});else{const te=Pt({},K.params);for(const se in te)te[se]==null&&delete te[se];Z=Pt({},K,{params:d(te)}),ee.params=d(ee.params)}const U=t.resolve(Z,ee),Q=K.hash||"";U.params=u(f(U.params));const W=Lye(o,Pt({},K,{hash:Rye(Q),path:U.path})),G=r.createHref(W);return Pt({fullPath:W,hash:Q,query:o===V3?v1e(K.query):K.query||{}},U,{redirectedFrom:void 0,href:G})}function S(K){return typeof K=="string"?cv(n,K,s.value.path):Pt({},K)}function $(K,ee){if(c!==K)return Ba(8,{from:ee,to:K})}function x(K){return w(K)}function C(K){return x(Pt(S(K),{replace:!0}))}function O(K){const ee=K.matched[K.matched.length-1];if(ee&&ee.redirect){const{redirect:Z}=ee;let U=typeof Z=="function"?Z(K):Z;return typeof U=="string"&&(U=U.includes("?")||U.includes("#")?U=S(U):{path:U},U.params={}),Pt({query:K.query,hash:K.hash,params:U.path!=null?{}:K.params},U)}}function w(K,ee){const Z=c=y(K),U=s.value,Q=K.state,W=K.force,G=K.replace===!0,te=O(Z);if(te)return w(Pt(S(te),{state:typeof te=="object"?Pt({},Q,te.state):Q,force:W,replace:G}),ee||Z);const se=Z;se.redirectedFrom=ee;let ie;return!W&&zye(o,U,Z)&&(ie=Ba(16,{to:se,from:U}),z(U,U,!0,!1)),(ie?Promise.resolve(ie):M(se,U)).catch(de=>Sr(de)?Sr(de,2)?de:L(de):k(de,se,U)).then(de=>{if(de){if(Sr(de,2))return w(Pt({replace:G},S(de.to),{state:typeof de.to=="object"?Pt({},Q,de.to.state):Q,force:W}),ee||se)}else de=A(se,U,!0,G,Q);return E(se,U,de),de})}function P(K,ee){const Z=$(K,ee);return Z?Promise.reject(Z):Promise.resolve()}function T(K){const ee=Y.values().next().value;return ee&&typeof ee.runWithContext=="function"?ee.runWithContext(K):K()}function M(K,ee){let Z;const[U,Q,W]=P1e(K,ee);Z=uv(U.reverse(),"beforeRouteLeave",K,ee);for(const te of U)te.leaveGuards.forEach(se=>{Z.push(ai(se,K,ee))});const G=P.bind(null,K,ee);return Z.push(G),J(Z).then(()=>{Z=[];for(const te of i.list())Z.push(ai(te,K,ee));return Z.push(G),J(Z)}).then(()=>{Z=uv(Q,"beforeRouteUpdate",K,ee);for(const te of Q)te.updateGuards.forEach(se=>{Z.push(ai(se,K,ee))});return Z.push(G),J(Z)}).then(()=>{Z=[];for(const te of W)if(te.beforeEnter)if(Xo(te.beforeEnter))for(const se of te.beforeEnter)Z.push(ai(se,K,ee));else Z.push(ai(te.beforeEnter,K,ee));return Z.push(G),J(Z)}).then(()=>(K.matched.forEach(te=>te.enterCallbacks={}),Z=uv(W,"beforeRouteEnter",K,ee,T),Z.push(G),J(Z))).then(()=>{Z=[];for(const te of l.list())Z.push(ai(te,K,ee));return Z.push(G),J(Z)}).catch(te=>Sr(te,8)?te:Promise.reject(te))}function E(K,ee,Z){a.list().forEach(U=>T(()=>U(K,ee,Z)))}function A(K,ee,Z,U,Q){const W=$(K,ee);if(W)return W;const G=ee===ti,te=Xl?history.state:{};Z&&(U||G?r.replace(K.fullPath,Pt({scroll:G&&te&&te.scroll},Q)):r.push(K.fullPath,Q)),s.value=K,z(K,ee,Z,G),L()}let R;function H(){R||(R=r.listen((K,ee,Z)=>{if(!X.listening)return;const U=y(K),Q=O(U);if(Q){w(Pt(Q,{replace:!0}),U).catch(Us);return}c=U;const W=s.value;Xl&&Xye(N3(W.fullPath,Z.delta),wh()),M(U,W).catch(G=>Sr(G,12)?G:Sr(G,2)?(w(G.to,U).then(te=>{Sr(te,20)&&!Z.delta&&Z.type===Mc.pop&&r.go(-1,!1)}).catch(Us),Promise.reject()):(Z.delta&&r.go(-Z.delta,!1),k(G,U,W))).then(G=>{G=G||A(U,W,!1),G&&(Z.delta&&!Sr(G,8)?r.go(-Z.delta,!1):Z.type===Mc.pop&&Sr(G,20)&&r.go(-1,!1)),E(U,W,G)}).catch(Us)}))}let _=ps(),B=ps(),N;function k(K,ee,Z){L(K);const U=B.list();return U.length?U.forEach(Q=>Q(K,ee,Z)):console.error(K),Promise.reject(K)}function F(){return N&&s.value!==ti?Promise.resolve():new Promise((K,ee)=>{_.add([K,ee])})}function L(K){return N||(N=!K,H(),_.list().forEach(([ee,Z])=>K?Z(K):ee()),_.reset()),K}function z(K,ee,Z,U){const{scrollBehavior:Q}=e;if(!Xl||!Q)return Promise.resolve();const W=!Z&&Yye(N3(K.fullPath,0))||(U||!Z)&&history.state&&history.state.scroll||null;return ot().then(()=>Q(K,ee,W)).then(G=>G&&Gye(G)).catch(G=>k(G,K,ee))}const j=K=>r.go(K);let q;const Y=new Set,X={currentRoute:s,listening:!0,addRoute:h,removeRoute:v,clearRoutes:t.clearRoutes,hasRoute:b,getRoutes:g,resolve:y,options:e,push:x,replace:C,go:j,back:()=>j(-1),forward:()=>j(1),beforeEach:i.add,beforeResolve:l.add,afterEach:a.add,onError:B.add,isReady:F,install(K){const ee=this;K.component("RouterLink",S1e),K.component("RouterView",w1e),K.config.globalProperties.$router=ee,Object.defineProperty(K.config.globalProperties,"$route",{enumerable:!0,get:()=>Et(s)}),Xl&&!q&&s.value===ti&&(q=!0,x(r.location).catch(Q=>{}));const Z={};for(const Q in ti)Object.defineProperty(Z,Q,{get:()=>s.value[Q],enumerable:!0});K.provide(DS,ee),K.provide(B_,gO(Z)),K.provide(a0,s);const U=K.unmount;Y.add(K),K.unmount=function(){Y.delete(K),Y.size<1&&(c=ti,R&&R(),R=null,s.value=ti,q=!1,N=!1),U()}}};function J(K){return K.reduce((ee,Z)=>ee.then(()=>T(Z)),Promise.resolve())}return X}function P1e(e,t){const n=[],o=[],r=[],i=Math.max(t.matched.length,e.matched.length);for(let l=0;l<i;l++){const a=t.matched[l];a&&(e.matched.find(c=>Da(c,a))?o.push(a):n.push(a));const s=e.matched[l];s&&(t.matched.find(c=>Da(c,s))||r.push(s))}return[n,o,r]}const I1e={class:"not-found-wrapper"},T1e=re({__name:"index",setup(e){const t=()=>{NS.replace("/")};return(n,o)=>{const r=xo("a-button"),i=xo("a-result");return di(),Yl("div",I1e,[p(i,{status:"404",title:"404","sub-title":"Sorry, the page you visited does not exist."},{extra:vn(()=>[p(r,{onClick:t,type:"primary"},{default:vn(()=>[Lt("Back Home")]),_:1})]),_:1})])}}}),E1e=xh(T1e,[["__scopeId","data-v-aef52a59"]]),BS=e=>(X7("data-v-b118bb94"),e=e(),Y7(),e),M1e={class:"view-wrapper"},_1e={style:{"margin-top":"10vh",padding:"32px"}},A1e={class:"chat-box-placeholder"},R1e=["data-seg-id"],D1e={class:"actions-box"},B1e={class:"left-actions"},N1e={class:"config-content"},k1e={class:"config-block"},F1e=BS(()=>tn("h4",{style:{"font-weight":"500"}},"Page Max Width:",-1)),L1e={class:"config-block"},z1e=BS(()=>tn("h4",{style:{"font-weight":"500"}},"Show Realtime Buffer:",-1)),H1e={class:"config-block"},j1e=BS(()=>tn("h4",{style:{"font-weight":"500"}},"Text Font Size:",-1)),W1e={style:{display:"flex","justify-content":"end"}},V1e="Please check if the microphone is available before the experience, specify the audio language and translation language, click the switch button to start recording, and you can get the recognized and translated text in real time.",K1e=re({__name:"index",setup(e){const t=Tc(),n=window.location.host;let o="ws";n.startsWith("127.0.0.1")||n.startsWith("localhost")?o="ws":o="wss";const r=`${o}://`+n+"/ws?";console.warn("ws_url: ",r);const i=oe(null),l=async Y=>{console.warn("start websocket ..."),i.value&&i.value.readyState!==WebSocket.CLOSED&&i.value.close();const X=`${r}${Y}`;i.value=new WebSocket(X),i.value.binaryType="arraybuffer",console.warn("created web socket ..."),i.value.addEventListener("open",()=>{console.log("WebSocket 连接成功"),v(),h.value=!0}),i.value.addEventListener("close",()=>{console.log("WebSocket 连接已关闭")}),i.value.onclose=J=>{console.log("code:",J.code,"reason:",J.reason,"wasClean:",J.wasClean),console.log("WebSocket 连接已关闭:",J)},i.value.addEventListener("error",J=>{console.error("WebSocket 连接错误:",J)}),i.value.addEventListener("message",J=>{const K=JSON.parse(J.data);console.log("WebSocket 收到消息:",K),K&&K.result&&E(K.result)})},a=async()=>{i.value&&(await i.value.close(),i.value=null)},s=oe(null),c=oe(null),u=oe(null),d=oe(null),f=oe(null),h=oe(!1),v=async()=>{try{const Y=await navigator.mediaDevices.getUserMedia({audio:{sampleRate:16e3,channelCount:1}});s.value=Y;const X=new AudioContext({sampleRate:16e3});u.value=X;const J=X.createMediaStreamSource(Y);d.value=J;const K=X.createScriptProcessor(1024*6,1,1);f.value=K,J.connect(K),K.connect(X.destination),K.onaudioprocess=ee=>{if(!h.value||!i.value||i.value.readyState!==WebSocket.OPEN)return;const Z=ee.inputBuffer.getChannelData(0),U=new Int16Array(Z.length);for(let Q=0;Q<Z.length;Q++)U[Q]=Math.max(-1,Math.min(1,Z[Q]))*32767;g(U)},h.value=!0,console.log("音频捕获已启动")}catch(Y){console.error("音频捕获失败:",Y)}},g=Y=>{if(i.value)i.value.send(Y),console.log("WebSocket send audio chunk success");else{console.error("WebSocket not initialized, sendAudioChunk failed");return}},b=async()=>{console.log("requirePermissionAction");try{if(!i.value||i.value.readyState!==WebSocket.OPEN){console.log("current lang_str : ",x.value);const Y=x.value;A(),await l(Y)}}catch(Y){console.log("Error accessing microphone: ",Y)}};je(()=>{console.log("[translator]: mounted"),z.value=t.$state.fs,L.value=t.$state.width_max,F.value=t.$state.vad}),xn(()=>{console.log("[HomePage]: unmounted"),i.value&&i.value.close(),c.value&&y()});const y=()=>{h.value=!1,a(),console.log("音频捕获已停止"),f.value&&(f.value.disconnect(),f.value=null),d.value&&(d.value.disconnect(),d.value=null),s.value&&(s.value.getTracks().forEach(Y=>Y.stop()),s.value=null),u.value&&(u.value.close(),u.value=null),P.value="",T.value="",M.value="",console.log("录音已停止")},S=async Y=>{console.log(`selected ${Y}`),h.value=!1,await y(),console.log("new lang_str: ",Y),console.log("trans_lang : ",x.value)},$=Y=>{h.value=Y,Y?b():y()},x=oe("from=en&to=zh"),C=[{value:"from=en&to=zh",label:"English -> Chinese"},{value:"from=zh&to=en",label:"Chinese -> English"}],O=[],w=ct([]),P=oe(""),T=oe(""),M=oe(""),E=Y=>{if(console.log("updateViewData: ",Y),Y){const{context:X,from:J,to:K,seg_id:ee,partial:Z,tranContent:U}=Y;if(Z==!0){P.value=X,T.value=U,M.value=ee;return}else{const Q={context:X,from:J,to:K,seg_id:ee,partial:Z,tranContent:U};w.length>100&&w.splice(0,40),w.push(Q);const W=`[src]: ${X}
496
  ${"-".repeat(80)}
497
  [dst]: ${U}
498
 
499
  `;O.push(W),P.value="",T.value="",M.value=""}}_()},A=()=>{w.splice(0,w.length),O.splice(0,O.length)},R=async()=>{const Y=O.join(`
500
+ `),X=new Blob([Y],{type:"text/plain"}),J=URL.createObjectURL(X),K=document.createElement("a");K.href=J,K.download="record.txt",document.body.appendChild(K),K.click(),document.body.removeChild(K),URL.revokeObjectURL(J)},H=oe(null),_=()=>{ot(()=>{H.value&&(H.value.scrollTop=H.value.scrollHeight+144)})};be(()=>[...w],()=>{_()},{deep:!0}),be(()=>T.value,()=>{_()});const B=oe(!1),N=()=>{B.value=!0},k=()=>{B.value=!1,F.value!=t.$state.vad&&(t.$state.vad=F.value,c.value&&y())},F=oe(.3),L=oe(!1),z=oe("trans-font-size-18"),j=oe(!0),q=Y=>{console.log("onFontSizeChange",Y.target.value),z.value=Y.target.value,t.$state.fs=Y.target.value};return(Y,X)=>{const J=xo("a-radio"),K=xo("a-radio-group"),ee=xo("a-switch"),Z=xo("a-button"),U=xo("a-popover"),Q=xo("a-select"),W=xo("a-popconfirm"),G=xo("a-card");return di(),Yl("div",M1e,[tn("div",{class:Pr(["content-wrapper",L.value?"wrapper-width-auto":"wrapper-width-fixed"])},[tn("div",_1e,[p(G,{bordered:!1,style:{width:"100%","min-width":"100%"}},{actions:vn(()=>[tn("div",D1e,[tn("div",B1e,[p(U,{open:B.value,"onUpdate:open":X[4]||(X[4]=te=>B.value=te),placement:"topLeft",trigger:"click"},{content:vn(()=>[tn("div",N1e,[LA("",!0),tn("div",k1e,[F1e,p(ee,{checked:L.value,"onUpdate:checked":X[1]||(X[1]=te=>L.value=te)},null,8,["checked"])]),tn("div",L1e,[z1e,p(ee,{checked:j.value,"onUpdate:checked":X[2]||(X[2]=te=>j.value=te)},null,8,["checked"])]),tn("div",H1e,[j1e,p(K,{value:z.value,"onUpdate:value":X[3]||(X[3]=te=>z.value=te),onChange:q},{default:vn(()=>[p(J,{value:"trans-font-size-16"},{default:vn(()=>[Lt("Small")]),_:1}),p(J,{value:"trans-font-size-18"},{default:vn(()=>[Lt("Default")]),_:1}),p(J,{value:"trans-font-size-20"},{default:vn(()=>[Lt("Normal")]),_:1}),p(J,{value:"trans-font-size-22"},{default:vn(()=>[Lt("Medium")]),_:1}),p(J,{value:"trans-font-size-24"},{default:vn(()=>[Lt("Large")]),_:1})]),_:1},8,["value"])])]),tn("div",W1e,[p(Z,{type:"primary",onClick:k},{default:vn(()=>[Lt("Done")]),_:1})])]),default:vn(()=>[p(Z,{type:"dashed",shape:"circle",size:"middle",onClick:N},{icon:vn(()=>[p(Et(vme))]),_:1})]),_:1},8,["open"]),p(Q,{value:x.value,"onUpdate:value":X[5]||(X[5]=te=>x.value=te),style:{width:"240px"},placeholder:"Select Language",options:C,onChange:S},null,8,["value"]),p(W,{title:"save the current text content?",onConfirm:R,"ok-text":"Yes","cancel-text":"No"},{icon:vn(()=>[p(Et(sme),{style:{color:"red"}})]),default:vn(()=>[p(Z,{type:"dashed",shape:"circle",size:"middle"},{icon:vn(()=>[p(Et(MM))]),_:1})]),_:1})]),p(ee,{key:"switcher",size:"large",type:"danger","checked-children":"ON","un-checked-children":"OFF",checked:h.value,"onUpdate:checked":X[6]||(X[6]=te=>h.value=te),onChange:$},null,8,["checked"])])]),default:vn(()=>[fn(tn("div",A1e,ns(V1e),512),[[mn,!(w.length||P.value)]]),fn(tn("div",{class:"trans-list",ref_key:"transListRef",ref:H},[(di(!0),Yl(Ve,null,pA(w,te=>(di(),Yl("div",{key:te.context,class:Pr(["node"]),"data-seg-id":te.seg_id},[tn("div",{class:Pr(["trans-src-lang",z.value])},ns(te.context),3),tn("div",{class:Pr(["trans-dst-lang",z.value])},ns(te.tranContent),3)],8,R1e))),128)),fn((di(),Yl("div",{class:"node current_node",key:M.value},[tn("div",{class:Pr(["trans-src-lang",z.value])},ns(P.value),3),tn("div",{class:Pr(["trans-dst-lang",z.value])},ns(T.value),3)])),[[mn,j.value]])],512),[[mn,w.length||P.value]])]),_:1})])],2)])}}}),U1e=xh(K1e,[["__scopeId","data-v-b118bb94"]]),G1e=AS({id:"play_state",persist:!1,state:()=>{const e=Tc();return console.log("configState",e.$state.role_name),{current_state:"init",video_url:"",urls:{waiting:e.$state.roles_resources[e.$state.role_name].waiting,listening:e.$state.roles_resources[e.$state.role_name].listening,thinking:e.$state.roles_resources[e.$state.role_name].thinking,talking:""}}},actions:{changeRole(e){this.$patch(t=>{const n=Tc();t.urls.waiting=n.$state.roles_resources[n.$state.role_name].waiting,t.urls.listening=n.$state.roles_resources[n.$state.role_name].listening,t.urls.thinking=n.$state.roles_resources[n.$state.role_name].thinking})},changeState(e){if(["waiting","listening","thinking","talking","init"].indexOf(e)==-1){console.error("invalid state",e);return}this.$patch(t=>{t.video_url=t.urls[e],t.current_state=e})},changeTalkingVideoUrl(e){this.$patch(t=>{t.urls.talking=e})}}}),X1e={class:"content-wrapper"},Y1e=re({__name:"index",setup(e){const t=Tc();return G1e(),je(()=>{console.log("config",t.$state)}),oe(t.$state.file_type),oe(t.$state.role_name),(n,o)=>{const r=xo("a-result");return di(),Yl("div",X1e,[p(r,{style:{width:"100%"},title:"Settings"})])}}}),q1e=xh(Y1e,[["__scopeId","data-v-c39ab0d6"]]),Z1e=[{name:"home",path:"/",component:U1e,meta:{requiresAgreement:!1}},{name:"settings",path:"/settings",component:q1e},{name:"404",path:"/404",component:E1e}],NS=O1e({history:Jye("/app/"),routes:Z1e});NS.beforeEach((e,t,n)=>{console.log("=============== router to : ",e),e.matched.length===0?n({name:"404"}):n()});const N_=aye();N_.use(yye);rP(Cye).use(N_).use(NS).use(w0e).mount("#app")});export default Q1e();
frontend/assets/{index-c1b225bf.css → index-54c9f9d3.css} RENAMED
@@ -1 +1 @@
1
- html,body{width:100%;height:100%}input::-ms-clear,input::-ms-reveal{display:none}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{margin:0}[tabindex="-1"]:focus{outline:none}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5em;font-weight:500}p{margin-top:0;margin-bottom:1em}abbr[title],abbr[data-original-title]{-webkit-text-decoration:underline dotted;text-decoration:underline;text-decoration:underline dotted;border-bottom:0;cursor:help}address{margin-bottom:1em;font-style:normal;line-height:inherit}input[type=text],input[type=password],input[type=number],textarea{-webkit-appearance:none}ol,ul,dl{margin-top:0;margin-bottom:1em}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:500}dd{margin-bottom:.5em;margin-left:0}blockquote{margin:0 0 1em}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}pre,code,kbd,samp{font-size:1em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}pre{margin-top:0;margin-bottom:1em;overflow:auto}figure{margin:0 0 1em}img{vertical-align:middle;border-style:none}a,area,button,[role=button],input:not([type=range]),label,select,summary,textarea{touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75em;padding-bottom:.3em;text-align:left;caption-side:bottom}input,button,select,optgroup,textarea{margin:0;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;margin:0;padding:0;border:0}legend{display:block;width:100%;max-width:100%;margin-bottom:.5em;padding:0;color:inherit;font-size:1.5em;line-height:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}mark{padding:.2em;background-color:#feffe6}:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;height:auto;min-height:auto;color:#333;background:#fff}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}.card{border-bottom:solid 2px lightgray;align-items:center;justify-content:center;margin-top:40px;display:flex;max-width:1024px;width:100%}.seg-title{margin:24px 0;font-size:20px;font-weight:500}.seg-co{width:1022px;text-align:left;border-left:solid 6px midnightblue;padding-left:8px;margin-left:2px;margin-top:36px;line-height:24px}#app{margin:0 auto;padding:0;text-align:center;width:100%}.ant-btn{padding:4px 12px}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.ant-card{background:#f5f6fa}.ant-card .ant-card-actions{background-color:#e8e8f8cc!important}.ant-popover{max-width:800px!important}.ant-form-item{background:transparent;margin-bottom:40px!important}.ant-form-item .ant-form-item-explain-error{color:#ff4d4f;text-align:left!important}.ant-form-item-label label{font-size:18px!important;color:#1a1a1a!important;font-weight:500!important}.ant-tooltip{max-width:1022px!important}.ant-page-header-heading{width:1022px!important}.highlight{background:ghostwhite}.content[data-v-178d5f9f]{background-color:#fff;max-width:1280px;min-height:720px;margin:0 auto;display:flex;flex-direction:column;align-items:center;justify-content:space-between}.not-found-wrapper[data-v-aef52a59]{height:calc(100vh - 104px)}.config-content[data-v-1bbbedd4]{width:420px;margin:12px}.config-content .config-block[data-v-1bbbedd4]{margin:12px;padding-bottom:12px}.view-wrapper[data-v-1bbbedd4]{width:100%;height:100%;background-color:#fff}.view-wrapper .wrapper-width-fixed[data-v-1bbbedd4]{width:1280px}.view-wrapper .wrapper-width-auto[data-v-1bbbedd4]{width:100vw}.view-wrapper .content-wrapper[data-v-1bbbedd4]{text-align:left;max-width:100vw;min-width:320px;margin-bottom:64px;min-height:calc(100vh - 438px)}.view-wrapper .content-wrapper .chat-box[data-v-1bbbedd4]{width:100%;height:54vh;border-radius:4px;padding:12px;color:#2e2f33;font-size:18px}.view-wrapper .content-wrapper .chat-box-placeholder[data-v-1bbbedd4]{width:100%;height:58vh;border-radius:4px;padding:12px;font-size:18px;color:#a4a6ac}.view-wrapper .content-wrapper .actions-box[data-v-1bbbedd4]{display:flex;align-items:center;justify-content:space-between;margin:0 24px;height:48px}.view-wrapper .content-wrapper .actions-box .left-actions[data-v-1bbbedd4]{display:flex;align-items:center;justify-content:space-between;width:332px}.view-wrapper .content-wrapper .actions-box .right-actions[data-v-1bbbedd4]{display:flex;align-items:center;justify-content:space-between;width:108px}.view-wrapper .content-wrapper .trans-list[data-v-1bbbedd4]{overflow-y:auto;width:100%;height:58vh;scrollbar-width:none;-ms-overflow-style:none}.view-wrapper .content-wrapper .trans-list[data-v-1bbbedd4]::-webkit-scrollbar{display:none}.view-wrapper .content-wrapper .trans-list .node[data-v-1bbbedd4]{margin-bottom:36px;width:100%!important;transition:all .3s ease}.view-wrapper .content-wrapper .trans-list .node .trans-time[data-v-1bbbedd4]{font-size:14px;color:#c4c6cc}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-16[data-v-1bbbedd4]{font-size:16px}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-18[data-v-1bbbedd4]{font-size:18px}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-20[data-v-1bbbedd4]{font-size:20px}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-22[data-v-1bbbedd4]{font-size:22px}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-24[data-v-1bbbedd4]{font-size:24px}.view-wrapper .content-wrapper .trans-list .node .trans-src-lang[data-v-1bbbedd4]{color:#909299;font-weight:500}.view-wrapper .content-wrapper .trans-list .node .trans-dst-lang[data-v-1bbbedd4]{color:#2e2f33;font-weight:600}.view-wrapper .content-wrapper .trans-list .current_node[data-v-1bbbedd4]{background-color:#f0f1f7;padding:4px 8px}@keyframes highlight-1bbbedd4{0%{background-color:transparent}50%{background-color:#fff1ce80}to{background-color:transparent}}@keyframes slideIn-1bbbedd4{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.content-wrapper[data-v-c39ab0d6]{text-align:left;max-width:800px;min-width:320px;margin-bottom:64px;min-height:calc(100vh - 438px)}.content-wrapper .content-box[data-v-c39ab0d6]{padding:24px;height:240px;background-color:#e8e8e8;border-radius:16px;width:50%;margin:48px auto;min-width:300px}.content-wrapper .video-box[data-v-c39ab0d6]{max-width:800px;min-width:320px;width:90vw;height:auto}
 
1
+ html,body{width:100%;height:100%}input::-ms-clear,input::-ms-reveal{display:none}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{margin:0}[tabindex="-1"]:focus{outline:none}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5em;font-weight:500}p{margin-top:0;margin-bottom:1em}abbr[title],abbr[data-original-title]{-webkit-text-decoration:underline dotted;text-decoration:underline;text-decoration:underline dotted;border-bottom:0;cursor:help}address{margin-bottom:1em;font-style:normal;line-height:inherit}input[type=text],input[type=password],input[type=number],textarea{-webkit-appearance:none}ol,ul,dl{margin-top:0;margin-bottom:1em}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:500}dd{margin-bottom:.5em;margin-left:0}blockquote{margin:0 0 1em}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}pre,code,kbd,samp{font-size:1em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}pre{margin-top:0;margin-bottom:1em;overflow:auto}figure{margin:0 0 1em}img{vertical-align:middle;border-style:none}a,area,button,[role=button],input:not([type=range]),label,select,summary,textarea{touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75em;padding-bottom:.3em;text-align:left;caption-side:bottom}input,button,select,optgroup,textarea{margin:0;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;margin:0;padding:0;border:0}legend{display:block;width:100%;max-width:100%;margin-bottom:.5em;padding:0;color:inherit;font-size:1.5em;line-height:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}mark{padding:.2em;background-color:#feffe6}:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;height:auto;min-height:auto;color:#333;background:#fff}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}.card{border-bottom:solid 2px lightgray;align-items:center;justify-content:center;margin-top:40px;display:flex;max-width:1024px;width:100%}.seg-title{margin:24px 0;font-size:20px;font-weight:500}.seg-co{width:1022px;text-align:left;border-left:solid 6px midnightblue;padding-left:8px;margin-left:2px;margin-top:36px;line-height:24px}#app{margin:0 auto;padding:0;text-align:center;width:100%}.ant-btn{padding:4px 12px}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.ant-card{background:#f5f6fa}.ant-card .ant-card-actions{background-color:#e8e8f8cc!important}.ant-popover{max-width:800px!important}.ant-form-item{background:transparent;margin-bottom:40px!important}.ant-form-item .ant-form-item-explain-error{color:#ff4d4f;text-align:left!important}.ant-form-item-label label{font-size:18px!important;color:#1a1a1a!important;font-weight:500!important}.ant-tooltip{max-width:1022px!important}.ant-page-header-heading{width:1022px!important}.highlight{background:ghostwhite}.content[data-v-178d5f9f]{background-color:#fff;max-width:1280px;min-height:720px;margin:0 auto;display:flex;flex-direction:column;align-items:center;justify-content:space-between}.not-found-wrapper[data-v-aef52a59]{height:calc(100vh - 104px)}.config-content[data-v-b118bb94]{width:420px;margin:12px}.config-content .config-block[data-v-b118bb94]{margin:12px;padding-bottom:12px}.view-wrapper[data-v-b118bb94]{width:100%;height:100%;background-color:#fff}.view-wrapper .wrapper-width-fixed[data-v-b118bb94]{width:1280px}.view-wrapper .wrapper-width-auto[data-v-b118bb94]{width:100vw}.view-wrapper .content-wrapper[data-v-b118bb94]{text-align:left;max-width:100vw;min-width:320px;margin-bottom:64px;min-height:calc(100vh - 438px)}.view-wrapper .content-wrapper .chat-box[data-v-b118bb94]{width:100%;height:54vh;border-radius:4px;padding:12px;color:#2e2f33;font-size:18px}.view-wrapper .content-wrapper .chat-box-placeholder[data-v-b118bb94]{width:100%;height:58vh;border-radius:4px;padding:12px;font-size:18px;color:#a4a6ac}.view-wrapper .content-wrapper .actions-box[data-v-b118bb94]{display:flex;align-items:center;justify-content:space-between;margin:0 24px;height:48px}.view-wrapper .content-wrapper .actions-box .left-actions[data-v-b118bb94]{display:flex;align-items:center;justify-content:space-between;width:332px}.view-wrapper .content-wrapper .actions-box .right-actions[data-v-b118bb94]{display:flex;align-items:center;justify-content:space-between;width:108px}.view-wrapper .content-wrapper .trans-list[data-v-b118bb94]{overflow-y:auto;width:100%;height:58vh;scrollbar-width:none;-ms-overflow-style:none}.view-wrapper .content-wrapper .trans-list[data-v-b118bb94]::-webkit-scrollbar{display:none}.view-wrapper .content-wrapper .trans-list .node[data-v-b118bb94]{margin-bottom:36px;width:100%!important;transition:all .3s ease}.view-wrapper .content-wrapper .trans-list .node .trans-time[data-v-b118bb94]{font-size:14px;color:#c4c6cc}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-16[data-v-b118bb94]{font-size:16px}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-18[data-v-b118bb94]{font-size:18px}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-20[data-v-b118bb94]{font-size:20px}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-22[data-v-b118bb94]{font-size:22px}.view-wrapper .content-wrapper .trans-list .node .trans-font-size-24[data-v-b118bb94]{font-size:24px}.view-wrapper .content-wrapper .trans-list .node .trans-src-lang[data-v-b118bb94]{color:#909299;font-weight:500}.view-wrapper .content-wrapper .trans-list .node .trans-dst-lang[data-v-b118bb94]{color:#2e2f33;font-weight:600}.view-wrapper .content-wrapper .trans-list .current_node[data-v-b118bb94]{background-color:#f0f1f7;padding:4px 8px}@keyframes highlight-b118bb94{0%{background-color:transparent}50%{background-color:#fff1ce80}to{background-color:transparent}}@keyframes slideIn-b118bb94{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.content-wrapper[data-v-c39ab0d6]{text-align:left;max-width:800px;min-width:320px;margin-bottom:64px;min-height:calc(100vh - 438px)}.content-wrapper .content-box[data-v-c39ab0d6]{padding:24px;height:240px;background-color:#e8e8e8;border-radius:16px;width:50%;margin:48px auto;min-width:300px}.content-wrapper .video-box[data-v-c39ab0d6]{max-width:800px;min-width:320px;width:90vw;height:auto}
frontend/index.html CHANGED
@@ -5,8 +5,8 @@
5
  <link rel="icon" type="image/svg+xml" href="./favicon.ico" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>Translator</title>
8
- <script type="module" crossorigin src="./assets/index-a619a94d.js"></script>
9
- <link rel="stylesheet" href="./assets/index-c1b225bf.css">
10
  </head>
11
  <body>
12
  <div id="app"></div>
 
5
  <link rel="icon" type="image/svg+xml" href="./favicon.ico" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>Translator</title>
8
+ <script type="module" crossorigin src="./assets/index-4906844f.js"></script>
9
+ <link rel="stylesheet" href="./assets/index-54c9f9d3.css">
10
  </head>
11
  <body>
12
  <div id="app"></div>
frontend/index2.html DELETED
@@ -1,169 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="zh">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>试试翻译</title>
6
- <style>
7
- body {
8
- background-color: #f9f9fc;
9
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
10
- margin: 0;
11
- padding: 2rem;
12
- }
13
- .translation-box {
14
- background: #f2f2f8;
15
- border-radius: 12px;
16
- padding: 1.5rem;
17
- max-width: 800px;
18
- margin: 0 auto;
19
- min-height: 200px;
20
- }
21
- .entry {
22
- margin-bottom: 1.5rem;
23
- }
24
- .timestamp {
25
- font-size: 0.75rem;
26
- color: #999;
27
- }
28
- .original {
29
- font-size: 1rem;
30
- color: #333;
31
- }
32
- .translation {
33
- font-size: 1rem;
34
- font-weight: bold;
35
- color: #000;
36
- }
37
- .footer {
38
- display: flex;
39
- justify-content: space-between;
40
- align-items: center;
41
- margin-top: 2rem;
42
- }
43
- .lang-select {
44
- background: white;
45
- border-radius: 9999px;
46
- padding: 0.4rem 1rem;
47
- border: none;
48
- font-size: 1rem;
49
- box-shadow: 0 0 0 1px #ddd;
50
- }
51
- .record-button {
52
- background-color: #1e40af;
53
- color: white;
54
- border: none;
55
- padding: 0.6rem 1.2rem;
56
- border-radius: 9999px;
57
- font-size: 1rem;
58
- cursor: pointer;
59
- }
60
- </style>
61
- </head>
62
- <body>
63
- <div class="translation-box" id="translationBox">
64
- <!-- 实时内容将插入这里 -->
65
- </div>
66
-
67
- <div class="footer">
68
- <select class="lang-select">
69
- <option>中文 » 英语</option>
70
- </select>
71
- <button class="record-button" onclick="startRecording()">🎤 录音</button>
72
- </div>
73
-
74
- <script>
75
- let ws;
76
- let mediaRecorder;
77
-
78
- function formatTimestamp(ms) {
79
- const sec = ms / 1000;
80
- const min = Math.floor(sec / 60);
81
- const s = (sec % 60).toFixed(1);
82
- return `${String(min).padStart(2, '0')}:${s.padStart(4, '0')}`;
83
- }
84
-
85
- let lastSegId = null; // 用于存储上一个 seg_id
86
-
87
- function addTranslation(result) {
88
- const box = document.getElementById('translationBox');
89
-
90
- // 创建一个新的 div 来显示翻译
91
- const entry = document.createElement('div');
92
- entry.className = 'entry';
93
-
94
- console.log(result);
95
-
96
- const start = formatTimestamp(result.bg);
97
- const end = formatTimestamp(result.ed);
98
-
99
- // 判断是否是新的一行
100
- if (result.seg_id === lastSegId) {
101
- // 如果 seg_id 相同,更新该行内容
102
- const existingEntry = box.querySelector(`.entry[data-seg-id="${result.seg_id}"]`);
103
- if (existingEntry) {
104
- const translationDiv = existingEntry.querySelector('.translation');
105
- translationDiv.innerHTML = result.tranContent;
106
- }
107
- } else {
108
- // 如果 seg_id 不同,表示是新的行,添加新行
109
- entry.setAttribute('data-seg-id', result.seg_id); // 设置 seg_id
110
- entry.innerHTML = `
111
- <div class="original">${result.context}</div>
112
- <div class="translation">${result.tranContent}</div>
113
- `;
114
- box.appendChild(entry);
115
- }
116
-
117
- // 更新 lastSegId 以便下一次判断
118
- lastSegId = result.seg_id;
119
- }
120
-
121
-
122
-
123
- async function startRecording() {
124
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
125
- const audioContext = new AudioContext({ sampleRate: 16000 });
126
- const source = audioContext.createMediaStreamSource(stream);
127
- const processor = audioContext.createScriptProcessor(4096, 1, 1);
128
-
129
- const wsUrl = "ws://localhost:9191/ws?from=zh&to=en";
130
- ws = new WebSocket(wsUrl);
131
-
132
- ws.binaryType = "arraybuffer";
133
-
134
- ws.onopen = () => {
135
- console.log("WebSocket opened");
136
- source.connect(processor);
137
- processor.connect(audioContext.destination);
138
-
139
- processor.onaudioprocess = (e) => {
140
- const input = e.inputBuffer.getChannelData(0);
141
- const buffer = new Int16Array(input.length);
142
- for (let i = 0; i < input.length; i++) {
143
- buffer[i] = Math.max(-1, Math.min(1, input[i])) * 0x7FFF;
144
- }
145
- ws.send(buffer);
146
- };
147
- };
148
-
149
- ws.onmessage = (event) => {
150
- try {
151
- const msg = JSON.parse(event.data);
152
- if (msg.result) {
153
- addTranslation(msg.result);
154
- }
155
- } catch (e) {
156
- console.error("Parse error:", e);
157
- }
158
- };
159
-
160
- ws.onerror = (e) => console.error("WebSocket error:", e);
161
- ws.onclose = () => {
162
- console.log("WebSocket closed");
163
- processor.disconnect();
164
- source.disconnect();
165
- };
166
- }
167
- </script>
168
- </body>
169
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
main.py CHANGED
@@ -1,6 +1,5 @@
1
  from fastapi import FastAPI, WebSocket, WebSocketDisconnect
2
- from urllib.parse import urlparse, parse_qsl
3
- from transcribe.whisper_llm_serve import WhisperTranscriptionService
4
  from uuid import uuid1
5
  from logging import getLogger
6
  import numpy as np
 
1
  from fastapi import FastAPI, WebSocket, WebSocketDisconnect
2
+ from transcribe.serve import WhisperTranscriptionService
 
3
  from uuid import uuid1
4
  from logging import getLogger
5
  import numpy as np
transcribe/pipelines/pipe_vad.py CHANGED
@@ -72,7 +72,7 @@ class VadPipe(BasePipe):
72
  logging.debug(" 🫷Speech ended, capturing audio up to frame: {}".format(rel_end_frame))
73
  else:
74
  self._status = 'END'
75
- target_audio = source_audio[rel_start_frame:rel_end_frame]
76
  logging.debug(" 🔄 Speech segment captured from frame {} to frame {}".format(rel_start_frame, rel_end_frame))
77
  # logging.debug("❌ No valid speech segment detected, setting status to END")
78
  else:
 
72
  logging.debug(" 🫷Speech ended, capturing audio up to frame: {}".format(rel_end_frame))
73
  else:
74
  self._status = 'END'
75
+ target_audio = source_audio[max(rel_start_frame-100, 0):rel_end_frame]
76
  logging.debug(" 🔄 Speech segment captured from frame {} to frame {}".format(rel_start_frame, rel_end_frame))
77
  # logging.debug("❌ No valid speech segment detected, setting status to END")
78
  else:
transcribe/{whisper_llm_serve.py → serve.py} RENAMED
@@ -7,9 +7,9 @@ import asyncio
7
  import numpy as np
8
  import config
9
  import collections
10
- from api_model import TransResult, Message, DebugResult
11
 
12
- from .utils import log_block, save_to_wave, TestDataWriter, filter_words
13
  from .translatepipes import TranslatePipes
14
 
15
  from transcribe.pipelines import MetaItem
@@ -18,26 +18,12 @@ from transcribe.pipelines import MetaItem
18
  logger = getLogger("TranscriptionService")
19
 
20
 
21
- def _get_text_separator(language: str) -> str:
22
- """根据语言返回适当的文本分隔符"""
23
- return "" if language == "zh" else " "
24
-
25
-
26
- def _start_thread(target_function) -> threading.Thread:
27
- """启动守护线程执行指定函数"""
28
- thread = threading.Thread(target=target_function)
29
- thread.daemon = True
30
- thread.start()
31
- return thread
32
-
33
 
34
  class WhisperTranscriptionService:
35
  """
36
  Whisper语音转录服务类,处理音频流转录和翻译
37
  """
38
 
39
- SERVER_READY = "SERVER_READY"
40
- DISCONNECT = "DISCONNECT"
41
 
42
  def __init__(self, websocket, pipe: TranslatePipes, language=None, dst_lang=None, client_uid=None):
43
  print('>>>>>>>>>>>>>>>> init service >>>>>>>>>>>>>>>>>>>>>>')
@@ -47,52 +33,37 @@ class WhisperTranscriptionService:
47
  self.client_uid = client_uid
48
  # 转录结果稳定性管理
49
  self.websocket = websocket
50
- self._translate_pipe = pipe
51
-
52
  # 音频处理相关
53
  self.sample_rate = config.SAMPLE_RATE
54
 
55
  self.lock = threading.Lock()
56
  # 文本分隔符,根据语言设置
57
- self.text_separator = _get_text_separator(language)
58
  self.loop = asyncio.get_event_loop()
59
  # 原始音频队列
60
- self._frame_queue = queue.Queue()
61
  # 音频队列缓冲区
62
  self.frames_np = np.array([], dtype=np.float32)
 
63
  self.frames_np_start_timestamp = None
64
  # 完整音频队列
65
  self.full_segments_queue = collections.deque()
66
  # 启动处理线程
67
- self._translate_thread_stop = threading.Event()
68
- self._frame_processing_thread_stop = threading.Event()
69
-
70
- self.translate_thread = _start_thread(self._transcription_processing_loop)
71
- self.frame_processing_thread = _start_thread(self._read_frame_processing_loop)
72
  self.row_number = 0
73
- # for test
74
- self._transcribe_time_cost = 0.
75
- self._translate_time_cost = 0.
76
 
77
- if config.SAVE_DATA_SAVE:
78
- self._save_task_stop = threading.Event()
79
- self._save_queue = queue.Queue()
80
- self._save_thread = _start_thread(self.save_data_loop)
81
-
82
-
83
- def save_data_loop(self):
84
- writer = TestDataWriter()
85
- while not self._save_task_stop.is_set():
86
- test_data = self._save_queue.get()
87
- writer.write(test_data) # Save test_data to CSV
88
 
89
  def add_frames(self, frame_np: np.ndarray) -> None:
90
  """添加音频帧到处理队列"""
91
- self._frame_queue.put(frame_np)
92
 
93
  def _apply_voice_activity_detection(self, frame_np:np.array):
94
  """应用语音活动检测来优化音频缓冲区"""
95
- processed_audio = self._translate_pipe.voice_detect(frame_np.tobytes())
96
  speech_audio = np.frombuffer(processed_audio.audio, dtype=np.float32)
97
  speech_status = processed_audio.speech_status
98
  return speech_audio, speech_status
@@ -100,9 +71,9 @@ class WhisperTranscriptionService:
100
 
101
  def _read_frame_processing_loop(self) -> None:
102
  """从队列获取音频帧并合并到缓冲区"""
103
- while not self._frame_processing_thread_stop.is_set():
104
  try:
105
- frame_np = self._frame_queue.get(timeout=0.1)
106
  frame_np, speech_status = self._apply_voice_activity_detection(frame_np)
107
 
108
  if frame_np is None:
@@ -121,7 +92,7 @@ class WhisperTranscriptionService:
121
  self.full_segments_queue.appendleft(audio_array) # 根据时间是否满足三秒长度 来整合音频块
122
  self.frames_np_start_timestamp = time.time()
123
  self.frames_np = np.array([], dtype=np.float32)
124
-
125
  # 音频结束信号的时候 整合当前缓冲区
126
  # START -- END -- START -- END 通常
127
  # START -- END -- END end块带有音频信息的通常是4096内断的一个短音
@@ -134,7 +105,7 @@ class WhisperTranscriptionService:
134
  self.frames_np = np.array([], dtype=np.float32)
135
  else:
136
  logger.debug(f"🥳 当前时间与上一句的时间差: {time_diff:.2f}s,继续保留在缓冲区")
137
-
138
  except queue.Empty:
139
  pass
140
 
@@ -142,8 +113,8 @@ class WhisperTranscriptionService:
142
  """主转录处理循环"""
143
  frame_epoch = 1
144
 
145
- while not self._translate_thread_stop.is_set():
146
-
147
  if len(self.frames_np) ==0:
148
  time.sleep(0.1)
149
  continue
@@ -155,11 +126,21 @@ class WhisperTranscriptionService:
155
  else:
156
  audio_buffer = self.frames_np[:int(frame_epoch * 1.5 * self.sample_rate)].copy()# 获取 1.5s * epoch 个音频长度
157
  partial = True
158
-
159
  if len(audio_buffer) < int(self.sample_rate):
160
- silence_audio = np.zeros(self.sample_rate, dtype=np.float32)
161
- silence_audio[-len(audio_buffer):] = audio_buffer
 
 
 
 
 
162
  audio_buffer = silence_audio
 
 
 
 
 
163
 
164
  logger.debug(f"audio buffer size: {len(audio_buffer) / self.sample_rate:.2f}s")
165
  meta_item = self._transcribe_audio(audio_buffer)
@@ -169,6 +150,8 @@ class WhisperTranscriptionService:
169
 
170
  if len(segments):
171
  seg_text = self.text_separator.join(seg.text for seg in segments)
 
 
172
  # 整行
173
  if not partial:
174
  translated_content = self._translate_text_large(seg_text)
@@ -187,54 +170,35 @@ class WhisperTranscriptionService:
187
  partial=partial
188
  )
189
  self._send_result_to_client(result)
190
-
191
-
192
 
193
  def _transcribe_audio(self, audio_buffer: np.ndarray)->MetaItem:
194
  """转录音频并返回转录片段"""
195
  log_block("Audio buffer length", f"{audio_buffer.shape[0]/self.sample_rate:.2f}", "s")
196
- start_time = time.perf_counter()
197
-
198
- result = self._translate_pipe.transcribe(audio_buffer.tobytes(), self.source_language)
199
- segments = result.segments
200
- time_diff = (time.perf_counter() - start_time)
201
- logger.debug(f"📝 transcribe Segments: {segments} ")
202
- log_block("📝 transcribe output", f"{self.text_separator.join(seg.text for seg in segments)}", "")
203
- log_block("📝 transcribe time", f"{time_diff:.3f}", "s")
204
- self._transcribe_time_cost = round(time_diff, 3)
205
  return result
206
 
207
  def _translate_text(self, text: str) -> str:
208
  """将文本翻译为目标语言"""
209
  if not text.strip():
210
  return ""
211
-
212
  log_block("🐧 Translation input ", f"{text}")
213
- start_time = time.perf_counter()
214
 
215
- result = self._translate_pipe.translate(text, self.source_language, self.target_language)
216
  translated_text = result.translate_content
217
- time_diff = (time.perf_counter() - start_time)
218
- log_block("🐧 Translation time ", f"{time_diff:.3f}", "s")
219
  log_block("🐧 Translation out ", f"{translated_text}")
220
- self._translate_time_cost = round(time_diff, 3)
221
  return translated_text
222
 
223
  def _translate_text_large(self, text: str) -> str:
224
  """将文本翻译为目标语言"""
225
  if not text.strip():
226
  return ""
227
-
228
  log_block("Translation input", f"{text}")
229
- start_time = time.perf_counter()
230
-
231
- result = self._translate_pipe.translate_large(text, self.source_language, self.target_language)
232
  translated_text = result.translate_content
233
-
234
- time_diff = (time.perf_counter() - start_time)
235
- log_block("Translation large model time ", f"{time_diff:.3f}", "s")
236
  log_block("Translation large model output", f"{translated_text}")
237
- self._translate_time_cost = round(time_diff, 3)
238
  return translated_text
239
 
240
 
@@ -252,8 +216,5 @@ class WhisperTranscriptionService:
252
 
253
  def stop(self) -> None:
254
  """停止所有处理线程并清理资源"""
255
- self._translate_thread_stop.set()
256
- self._frame_processing_thread_stop.set()
257
- if config.SAVE_DATA_SAVE:
258
- self._save_task_stop.set()
259
  logger.info(f"Stopping transcription service for client: {self.client_uid}")
 
7
  import numpy as np
8
  import config
9
  import collections
10
+ from api_model import TransResult, Message
11
 
12
+ from .utils import log_block, start_thread, get_text_separator, filter_words
13
  from .translatepipes import TranslatePipes
14
 
15
  from transcribe.pipelines import MetaItem
 
18
  logger = getLogger("TranscriptionService")
19
 
20
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  class WhisperTranscriptionService:
23
  """
24
  Whisper语音转录服务类,处理音频流转录和翻译
25
  """
26
 
 
 
27
 
28
  def __init__(self, websocket, pipe: TranslatePipes, language=None, dst_lang=None, client_uid=None):
29
  print('>>>>>>>>>>>>>>>> init service >>>>>>>>>>>>>>>>>>>>>>')
 
33
  self.client_uid = client_uid
34
  # 转录结果稳定性管理
35
  self.websocket = websocket
36
+ self.translate_pipe = pipe
 
37
  # 音频处理相关
38
  self.sample_rate = config.SAMPLE_RATE
39
 
40
  self.lock = threading.Lock()
41
  # 文本分隔符,根据语言设置
42
+ self.text_separator = get_text_separator(language)
43
  self.loop = asyncio.get_event_loop()
44
  # 原始音频队列
45
+ self.frame_queue = queue.Queue()
46
  # 音频队列缓冲区
47
  self.frames_np = np.array([], dtype=np.float32)
48
+ # 音频开始的时间点 用于约束最小断句时间
49
  self.frames_np_start_timestamp = None
50
  # 完整音频队列
51
  self.full_segments_queue = collections.deque()
52
  # 启动处理线程
53
+ self._stop = threading.Event()
54
+ self.translate_thread = start_thread(self._transcription_processing_loop)
55
+ self.frame_processing_thread = start_thread(self._read_frame_processing_loop)
56
+ # 行号
 
57
  self.row_number = 0
 
 
 
58
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  def add_frames(self, frame_np: np.ndarray) -> None:
61
  """添加音频帧到处理队列"""
62
+ self.frame_queue.put(frame_np)
63
 
64
  def _apply_voice_activity_detection(self, frame_np:np.array):
65
  """应用语音活动检测来优化音频缓冲区"""
66
+ processed_audio = self.translate_pipe.voice_detect(frame_np.tobytes())
67
  speech_audio = np.frombuffer(processed_audio.audio, dtype=np.float32)
68
  speech_status = processed_audio.speech_status
69
  return speech_audio, speech_status
 
71
 
72
  def _read_frame_processing_loop(self) -> None:
73
  """从队列获取音频帧并合并到缓冲区"""
74
+ while not self._stop.is_set():
75
  try:
76
+ frame_np = self.frame_queue.get(timeout=0.1)
77
  frame_np, speech_status = self._apply_voice_activity_detection(frame_np)
78
 
79
  if frame_np is None:
 
92
  self.full_segments_queue.appendleft(audio_array) # 根据时间是否满足三秒长度 来整合音频块
93
  self.frames_np_start_timestamp = time.time()
94
  self.frames_np = np.array([], dtype=np.float32)
95
+
96
  # 音频结束信号的时候 整合当前缓冲区
97
  # START -- END -- START -- END 通常
98
  # START -- END -- END end块带有音频信息的通常是4096内断的一个短音
 
105
  self.frames_np = np.array([], dtype=np.float32)
106
  else:
107
  logger.debug(f"🥳 当前时间与上一句的时间差: {time_diff:.2f}s,继续保留在缓冲区")
108
+
109
  except queue.Empty:
110
  pass
111
 
 
113
  """主转录处理循环"""
114
  frame_epoch = 1
115
 
116
+ while not self._stop.is_set():
117
+
118
  if len(self.frames_np) ==0:
119
  time.sleep(0.1)
120
  continue
 
126
  else:
127
  audio_buffer = self.frames_np[:int(frame_epoch * 1.5 * self.sample_rate)].copy()# 获取 1.5s * epoch 个音频长度
128
  partial = True
129
+
130
  if len(audio_buffer) < int(self.sample_rate):
131
+ # Add a small buffer (e.g., 10ms worth of samples) to be safe
132
+ padding_samples = int(self.sample_rate * 0.01) # e.g., 160 samples for 10ms at 16kHz
133
+ target_length = self.sample_rate + padding_samples
134
+ silence_audio = np.zeros(target_length, dtype=np.float32)
135
+ # Ensure we don't try to copy more data than exists if audio_buffer is very short
136
+ copy_length = min(len(audio_buffer), target_length)
137
+ silence_audio[-copy_length:] = audio_buffer[-copy_length:] # Copy from the end of audio_buffer
138
  audio_buffer = silence_audio
139
+ elif len(audio_buffer) > self.sample_rate * config.MAX_SPEECH_DURATION_S:
140
+ # If buffer is too long even without padding, truncate it (optional, depends on desired behavior)
141
+ # This case might already be handled elsewhere, but good to consider
142
+ audio_buffer = audio_buffer[:int(self.sample_rate * config.MAX_SPEECH_DURATION_S)]
143
+
144
 
145
  logger.debug(f"audio buffer size: {len(audio_buffer) / self.sample_rate:.2f}s")
146
  meta_item = self._transcribe_audio(audio_buffer)
 
150
 
151
  if len(segments):
152
  seg_text = self.text_separator.join(seg.text for seg in segments)
153
+ if not seg_text.strip(): # 过滤空字符
154
+ continue
155
  # 整行
156
  if not partial:
157
  translated_content = self._translate_text_large(seg_text)
 
170
  partial=partial
171
  )
172
  self._send_result_to_client(result)
 
 
173
 
174
  def _transcribe_audio(self, audio_buffer: np.ndarray)->MetaItem:
175
  """转录音频并返回转录片段"""
176
  log_block("Audio buffer length", f"{audio_buffer.shape[0]/self.sample_rate:.2f}", "s")
177
+ result = self.translate_pipe.transcribe(audio_buffer.tobytes(), self.source_language)
178
+ log_block("📝 transcribe output", f"{self.text_separator.join(seg.text for seg in result.segments)}", "")
179
+
 
 
 
 
 
 
180
  return result
181
 
182
  def _translate_text(self, text: str) -> str:
183
  """将文本翻译为目标语言"""
184
  if not text.strip():
185
  return ""
 
186
  log_block("🐧 Translation input ", f"{text}")
 
187
 
188
+ result = self.translate_pipe.translate(text, self.source_language, self.target_language)
189
  translated_text = result.translate_content
190
+
 
191
  log_block("🐧 Translation out ", f"{translated_text}")
 
192
  return translated_text
193
 
194
  def _translate_text_large(self, text: str) -> str:
195
  """将文本翻译为目标语言"""
196
  if not text.strip():
197
  return ""
 
198
  log_block("Translation input", f"{text}")
199
+ result = self.translate_pipe.translate_large(text, self.source_language, self.target_language)
 
 
200
  translated_text = result.translate_content
 
 
 
201
  log_block("Translation large model output", f"{translated_text}")
 
202
  return translated_text
203
 
204
 
 
216
 
217
  def stop(self) -> None:
218
  """停止所有处理线程并清理资源"""
219
+ self._stop.set()
 
 
 
220
  logger.info(f"Stopping transcription service for client: {self.client_uid}")
transcribe/translatepipes.py CHANGED
@@ -1,5 +1,5 @@
1
- from transcribe.pipelines import WhisperPipe, MetaItem, WhisperChinese, Translate7BPipe, FunASRPipe, VadPipe, TranslatePipe
2
-
3
 
4
  class TranslatePipes:
5
  def __init__(self) -> None:
@@ -26,6 +26,7 @@ class TranslatePipes:
26
  for p in self._process:
27
  p.wait()
28
 
 
29
  def translate(self, text, src_lang, dst_lang) -> MetaItem:
30
  item = MetaItem(
31
  transcribe_content=text,
@@ -34,6 +35,7 @@ class TranslatePipes:
34
  self._translate_pipe.input_queue.put(item)
35
  return self._translate_pipe.output_queue.get()
36
 
 
37
  def translate_large(self, text, src_lang, dst_lang) -> MetaItem:
38
  item = MetaItem(
39
  transcribe_content=text,
@@ -47,6 +49,7 @@ class TranslatePipes:
47
  return self._funasr_pipe
48
  return self._whisper_pipe_en
49
 
 
50
  def transcribe(self, audio_buffer: bytes, src_lang: str) -> MetaItem:
51
  transcription_model = self.get_transcription_model(src_lang)
52
  item = MetaItem(audio=audio_buffer, source_language=src_lang)
 
1
+ from .pipelines import WhisperPipe, MetaItem, WhisperChinese, Translate7BPipe, FunASRPipe, VadPipe, TranslatePipe
2
+ from .utils import timer
3
 
4
  class TranslatePipes:
5
  def __init__(self) -> None:
 
26
  for p in self._process:
27
  p.wait()
28
 
29
+ @timer(name="🐧 Translate")
30
  def translate(self, text, src_lang, dst_lang) -> MetaItem:
31
  item = MetaItem(
32
  transcribe_content=text,
 
35
  self._translate_pipe.input_queue.put(item)
36
  return self._translate_pipe.output_queue.get()
37
 
38
+ @timer(name="🐧 Translate-large")
39
  def translate_large(self, text, src_lang, dst_lang) -> MetaItem:
40
  item = MetaItem(
41
  transcribe_content=text,
 
49
  return self._funasr_pipe
50
  return self._whisper_pipe_en
51
 
52
+ @timer(name="📝 transcribe")
53
  def transcribe(self, audio_buffer: bytes, src_lang: str) -> MetaItem:
54
  transcription_model = self.get_transcription_model(src_lang)
55
  item = MetaItem(audio=audio_buffer, source_language=src_lang)
transcribe/utils.py CHANGED
@@ -8,8 +8,9 @@ import config
8
  import csv
9
  import av
10
  import re
11
- import json
12
-
 
13
  # Compile regex patterns once outside the loop for better performance
14
  p_pattern = re.compile(r"(\s*\[.*?\])")
15
  p_start_pattern = re.compile(r"(\s*\[.*)")
@@ -178,6 +179,32 @@ def pcm_bytes_to_np_array(pcm_bytes: bytes, dtype=np.float32, channels=1):
178
  audio_np = audio_np.reshape(-1, channels)
179
  return audio_np
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  class TestDataWriter:
182
  def __init__(self, file_path='test_data.csv'):
183
  self.file_path = file_path
 
8
  import csv
9
  import av
10
  import re
11
+ from functools import wraps
12
+ import time
13
+ import threading
14
  # Compile regex patterns once outside the loop for better performance
15
  p_pattern = re.compile(r"(\s*\[.*?\])")
16
  p_start_pattern = re.compile(r"(\s*\[.*)")
 
179
  audio_np = audio_np.reshape(-1, channels)
180
  return audio_np
181
 
182
+ def timer(name: str):
183
+ def decorator(func):
184
+ @wraps(func)
185
+ def wrapper(*args, **kwargs):
186
+ start_time = time.perf_counter()
187
+ result = func(*args, **kwargs)
188
+ end_time = time.perf_counter()
189
+ duration = end_time - start_time
190
+ log_block(f"{name} cost:", f"{duration:.2f} s")
191
+ return result
192
+ return wrapper
193
+ return decorator
194
+
195
+ def get_text_separator(language: str) -> str:
196
+ """根据语言返回适当的文本分隔符"""
197
+ return "" if language == "zh" else " "
198
+
199
+
200
+ def start_thread(target_function) -> threading.Thread:
201
+ """启动守护线程执行指定函数"""
202
+ thread = threading.Thread(target=target_function)
203
+ thread.daemon = True
204
+ thread.start()
205
+ return thread
206
+
207
+
208
  class TestDataWriter:
209
  def __init__(self, file_path='test_data.csv'):
210
  self.file_path = file_path