From ee53250d002d573a8c596588e261c586e0ec0080 Mon Sep 17 00:00:00 2001 From: HuangHai <10402852@qq.com> Date: Fri, 22 Aug 2025 10:22:27 +0800 Subject: [PATCH] 'commit' --- .../ThemeController.cpython-310.pyc | Bin 4733 -> 4733 bytes .../BackgroundTasks.cpython-310.pyc | Bin 4066 -> 4066 bytes dsLightRag/Routes/XueBanRoute.py | 33 ++- .../__pycache__/XueBanRoute.cpython-310.pyc | Bin 2979 -> 4854 bytes dsLightRag/Util/ObsUtil.py | 2 - .../__pycache__/ASRClient.cpython-310.pyc | Bin 0 -> 4165 bytes .../__pycache__/TTSService.cpython-310.pyc | Bin 0 -> 4525 bytes .../__pycache__/XueBanUtil.cpython-310.pyc | Bin 3174 -> 4362 bytes dsLightRag/static/XueBan.html | 256 ++++++++++++++++-- 9 files changed, 258 insertions(+), 33 deletions(-) create mode 100644 dsLightRag/Util/__pycache__/ASRClient.cpython-310.pyc create mode 100644 dsLightRag/Util/__pycache__/TTSService.cpython-310.pyc diff --git a/dsLightRag/Routes/TeachingModel/api/__pycache__/ThemeController.cpython-310.pyc b/dsLightRag/Routes/TeachingModel/api/__pycache__/ThemeController.cpython-310.pyc index 4ccc318cf69d97cb0a548c70bee2d1746fc3ac6e..81c7b635aa2b0d85e2b462d73f1fd2461300eee0 100644 GIT binary patch delta 81 zcmeyX@>hjBpO=@50SL~XS-z3`C>P_c%@?^gFf!UtZsNJkXt_C#w}6q+a`Jh;c1G9D i;r!DW8LcP36R2f$o17!Ki`yQkvB(ufxJ@<`@&N!@CmARJ delta 81 zcmeyX@>hjBpO=@50SMZ!FWSg`l#4NH^F^)=jEr`Zn|N+BT5OKvEnsA{n0%hEozZ1; hIR7+8Mytv11Zo*wC+7(6;~&JO@N!UbRe diff --git a/dsLightRag/Routes/XueBanRoute.py b/dsLightRag/Routes/XueBanRoute.py index 4ff1ffc0..bdacd486 100644 --- a/dsLightRag/Routes/XueBanRoute.py +++ b/dsLightRag/Routes/XueBanRoute.py @@ -17,6 +17,8 @@ logger = logging.getLogger(__name__) from Util.XueBanUtil import get_xueban_response_async from Util.ASRClient import ASRClient from Util.ObsUtil import ObsUploader +# 新增导入TTSService +from Util.TTSService import TTSService @router.post("/xueban/upload-audio") @@ -49,11 +51,36 @@ async def upload_audio(file: UploadFile = File(...)): os.remove(temp_file_path) logger.info(f"临时文件已删除: {temp_file_path}") - # 返回识别结果 + # 使用大模型生成反馈 + logger.info(f"使用大模型生成反馈,输入文本: {asr_result['text']}") + response_generator = get_xueban_response_async(asr_result['text'], stream=False) + feedback_text = "" + async for chunk in response_generator: + feedback_text += chunk + logger.info(f"大模型反馈生成完成: {feedback_text}") + + # 使用TTS生成语音 + tts_service = TTSService() + tts_temp_file = os.path.join(tempfile.gettempdir(), f"tts_{timestamp}.mp3") + success = tts_service.synthesize(feedback_text, output_file=tts_temp_file) + if not success: + raise Exception("TTS语音合成失败") + logger.info(f"TTS语音合成成功,文件保存至: {tts_temp_file}") + + # 上传TTS音频文件到OBS + tts_audio_url = upload_file_to_obs(tts_temp_file) + os.remove(tts_temp_file) # 删除临时TTS文件 + logger.info(f"TTS文件已上传至OBS: {tts_audio_url}") + + # 返回结果,包含ASR文本和TTS音频URL return JSONResponse(content={ "success": True, - "message": "音频识别成功", - "data": asr_result + "message": "音频处理和语音反馈生成成功", + "data": { + "asr_text": asr_result['text'], + "feedback_text": feedback_text, + "audio_url": tts_audio_url + } }) except Exception as e: diff --git a/dsLightRag/Routes/__pycache__/XueBanRoute.cpython-310.pyc b/dsLightRag/Routes/__pycache__/XueBanRoute.cpython-310.pyc index 28969d32bbf0603670a74e608e413cc7242132a2..d7fe8fcf0569b1a259ca28ae49f00f56dc603286 100644 GIT binary patch literal 4854 zcmZu#TXPi06`t;yot>Q>tyYT=h?}>PBK9UhB)(Q{96N@9u|u#+f)Gzp*;;LnRx9@A zo*4_NW+@wCM@0}|8^=kI&B_Mb#KGW80l^m@@(1#ihj~miLdr|>kcX73uyan&YPG~j zH9gbar%(6k{?0jHZ>_6Km*CI*>${_WTrWxgz)I&|1S&s)$Nn!AOk$)gnc9Cj1ZQv zVk4Awv*gjp6fyf*kF}1ato0)bTg7^hD&_{ZTC}W#mOi!yS~dzDYv%~-x1un19b11? zfw7wy8Im#^mcV*xPlos!%R81+s#qDtk3IJE6N5F^vA7={w4QY>+wqm1rLyJg`|9Od zp5Zr)F`gWHYR{l$*K1YVnpC#t>m^qOeZj?d=0E!+Lw&W*t&!3pUvct98wT_jEhl%# zwTAQ69B+-wne*biGK_e%}R6px&dJd~FkvgnUFdNV#JdGZ`>D30MNEHXt;_BJ9O9QB;^ zgv8WcQbYA3&4j1o9Q&a~krZi4CQ?=Vp=3Wk4z2kA3_M~@QBP^FsM~`hYH5i&YBT96 zVx_ottwRp$F)zyWeyKgSC#3Mvywgh7jrOzT8)&WJ#m82`c!TwT_Aal>zU1_>)D$^FgcYkiqpfMRXH1bs zLaZM^+_JOROSC2W*lN}nt`~GB*qT|Ht%aw5hU}MyV85K+Q)Ge?snJcO$xSfB8n(_^ z>vd1Tidv`F2bOlUvGuc*ZD1Q`=zd9s-DPT{`*8PA>pf1!rOYPRMP#JmZ~oe``Olh5 zXFpzg>*a;t{(An?E5VH>^wotoXN8cv24-G3aem?Sm07=;W?j<5ASim1I?Y|f~z0R-*_Xq_`Ahle>{KflZDr> z+&uF^@cC=mw3sVwYMFNRqhPwZ^!szr_kB<^|M`uZr{4?Cy}R(^Zk|57FnuaG zIkWW6^uInkzWBwf!Hef%yWea0`XPb;a0xlOYTO{(Hv7KSGZoAK1Pp=^4udpGol`xTyM@XGPloWjs>!J+<)Y-)L%=g?BWYs9kH zaK3Obtj5AKaC!NH>_=_4P_S&rItK6#8p0hZ{PTmEDsY8f%MlHKEY5B1ohYD8RDb=ceDvZG5KyywlR~xo@6c-q= zIInSEh9zc_Jb_IyTq@XDsfX6&V3W;+fHy8Mht~NWbzu(~5u0P`cr1`G+_Gb)+KHoR zRV|)(YMl3pNeiQH^&q$mV9pM6h1rFb_9SBK!?yNu`oy{*@rOadm-qiPdw|*dYy2R* zp60bNtKh)b?ox5o8O#?Ch?Hm__@!%Y%U4BZpg!RntxXUb*Mc5<7z+A4jizWqPLTvj z5rZa(K{kAqR1&f-CrK|n3P}>3(65tJmDhokLNsX6WF1N>Q$mSKu~cpuw~~4a`?O?SrF z;Nt7Si`PVd5p0FOe?MA+G$Jh_7s$xG2VTAoPC8OzR<&T6iEt|B0+0aGE()|Ge;AOm z={=b^zYjWi9ES^M%t0hDjb*QK^7cWFk%r%c5>aqA^c8+DHhl|=`>}WcicEw*ir<(B zLR=RF=fO~a$Z3I`{|H48lwt8>{Q3bDzkB7!Ip*g#o7 zCL9Z)aT_EI=tD?shsXXq6qC<55&!|<;0O=^G-w9|NWavKwxB@|%6uK84VlSEh&&mN zU2XtD0?MQSVCVtbh#>LdyPa552kHdGghd2p5fp~0ELx6Nj7GH5)zE4rWfwU%Nhk{bfiTf&^eP-#55BL|cf<_J(HDojUFW zOV9$T=;j}ehSMx7;@!C6%D{O3xyj@%H(xF8%9pl=A!Vz`8lB4u^Ab=4CB5a5G)GDR ztXc=%xuG3{zt}Mtes9~i{bxJ&PHLl$Q@68QxB6t@OY%)^%WxJsGt85%v^jkljc%o= zJrJ@HBLc3z;<_bB6IkBA0&$K>+K-fLLS++!l3S7!$6@**X; zHUg*aZgc9`gaeMF3P!DflO`Q-v=zq@E9zNk6KhL_YZHu`G}OZ?xTkmv_gdw?g4UyZ z&0jkaUjN$6aPfs>!MO|Q2`A16C*KxQD|EWGmFeLcn}ER=K`sq9PCg-cSNa}E8Vl1` z7tWqvyz~~J72Gb<(r^d5EoKT{oe8d=7D9V`eMJ{XPPWs<6y2$A{@Tpq)aT&(H!oc0 z7+OoGz|VLZz68TMaiL%9a!6|wO20O4CA2$GnggIFbC(}Q@>{AF!+7&OXyi{~L80)Y zBYB{a^%9q{339u{k>qgv;lb}|bq*}s*CM1U4}Z>x!6xnwnYES^oHLgb8)i_@% delta 1146 zcmY*XO>7%Q6rQ)c-d(T%){cJ?C8;7P(50z_8d`;_DpI6|LnRIbsbYJujA!ha?s~1+ zH3^YJQYE4hD5BAdpF*GxR6-RJkti)yd+32nuUz+>ILU<*;+Bdx4u`O-dGqFb?|XkU z|Ge~LDea|F2Ep&~v!7Q2TrZ4-SG-7Jl70n@0l0yUrsrq?8zq^Z@| z3fMWCW&B;H2cD;Vi)?9+!oLQrlM<}7FHE>EmD{vRxvyUYheVh7UEdFXyFfB z{uB^$0~XrhkaTy6>NFl?I_e5gW0=qcuH>e?s0C`*>?m6RBp_X&sgCk3`A+JevouXJ z9gUisGR>~TRWd^q668MW0$Iea7fv8!faZdHM_++stp8y&zbVlI9WAa)SBXmABUD|~ zKh|gd+vi}8Sfy}O*_(a^Yu&ZFhtFAsVTKHJ~^;^5BxgC92bzFFPh{$zLU z=e;Lk@B7Vqt^fV?W&r=%B({8 zRBesR4r@j#XRh}lbT-Pp^L?GL!_`J-S-*$os z*ge80!q@b-RFTl13K#X^aY>aR4eFtxnIOp$h(CFlR`W+1D9Ml{lZg zeWE4*{~o|u`^b2L)RQpvuNgp@N@J0(jclvr=y@S7pomNyTFYzt4DX;B zuqH;X&bFJ^qg1W!IAWw|wS30U3X16YSf6Hfwi1-*8o_LNzRljRG~WrYXRj15qnA~R zG{>vg8_hZ&6ReZrpV@0L9G=MyRU@V4Vg2U>F3O4&+NcJ6Qk(_(Se|~y{!sOcu1DJr gyCg2f7wzgq2OW|yC?z2+8*)LqtO)6Wp zsX|LzTD#CJwDqP=ly53bW!iOxY1e48=ozfAO!+9&n|V{e7NQ})>NhsQ>bOdL8qarF5Kc%C~tT5m^((y87eVdMpIRuJK`7i7k~ z-}3B)w=y$dP4XovCfTBJ;$_=snR&$)!fu5NKC`q;i@nx7FThM(M^Xgxj>3nac`$l> z@&b#$7xHCj&hl^x4h!5Fe_>Iaa~3XqSNN?9eG}KCmCUehKk$WZqhG|sKum&vUH(my z?%EpO8|vbbdOti8?n5Hu8^CmwC42}VfkYKSg}SD#E7u64tJ+oCA^h|3wUE;e;Psf& zq2LP|@P(YW^kfH2v~lys#;u$8Z~t-g_dnXW^@nuF<*?<}!9-5X>tHQQONY+arXnAn zsCL?0Nk_V`uImAeuxDr9bIyyygu7nt6noGebj|}!#{zrI^R+oqJA?X7X>BYW&V^=i zMBsXszNPIXDXbmY0Nvz08luo3Mg$FJ?EIq6pJ=@xgkeivW0UI za2z;oFDtrXAiOKWDrTniBiY^D;{|ez3tk;~Ejx}{zJO4e_cG=-cXxU4QdpA%BZU;GrK49@eAWiV)>pGwR86_}2)rmQPh!7&&) zfMF4W-K~6CjESUiE7eTs! zJOaHBLJCmFzT!iD;3m*l!ainpp^Olw0C4!ym+tKYzFCz7Rk!(zU*5m{b|1p`UVd-$ z2R}?F<`BF=D609n1=x7S6ZPuZmgfK>U8mLRev-;OXjSKZ9*a7E8s>!HgH!V_0ZHrM z!BQaihMrv>h3IEKb9^7r{42P?(~lI`!fuZDr%+^cK;(ZyuvN}si>ZbmL{dj0@oXXY z43ZL(XOUngk~-++MyZcc?A;cT%}b~rsl?OpSt7DR4M1cC5NS$8?jxEu^07f6FYehw zP*6bMMaUn?GN@`={SQtlN0?jmm$Hl{DD{3x_VY+-~U-5lx)*@8>6(mLddO9iMg&?Po*UBCC*jlP@x<1atUbH~Q} z@7@34UGTtM&vVjeq$)X@A;H=yH$<-a$!fEgEynuXcv^gM>eQJN$DhdE&*Wnu#>bIJ z;MI_mzg5yG<(* z53vN5n08^k_zOS`C?gE0@(|f39R{0@Cg`~_W^V&;03~DC_?)rZ z*j3TxS6sdA_R|TJ`WE+|Ghp5OT3t8>_ch78B@8Z9@P6 literal 0 HcmV?d00001 diff --git a/dsLightRag/Util/__pycache__/TTSService.cpython-310.pyc b/dsLightRag/Util/__pycache__/TTSService.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edf9329b728975debcfbe7914c77d530c5e1d4d6 GIT binary patch literal 4525 zcmb6cTW}NCb??5kT1mEJNCHWkQB#;iEio{m3FDMD#5f5J<1n#PCYsFb2;H?UBTM4$ zE)JSCgE0j2aGXqlJTSpdXkG=Ilm;AZ;IsYdPe1Q(y|Vm8ra$e#bkcKnC0RK6NOxz? zo_p`P_nvd^dEI<0rVH@!zklA_e!n366C3r942|dDvkm~D0wq}?8T?6-_-!#M`hO`Y z!C%bE{Yp~lSCeXgC>iS4k{S_AsV@wlP9-XjirAirP-T)Nqb~|nrOIJ}D#KzjMnhCP zEF>GuMjGBDvMpxAus~qXPX9~ji@<}>k&t=#rA}k(&Yi~gZM+fDwzl@pPNVCUm)kpd z3_99&yw=&({wj`R^AE3VZ)-QYUf0BRJ* z`?RwHmCi}f4pW&b&?B7{&WRbM(Cx@Xl){WY0#qURD=;Qc5;!Lf1PD70sqpUeKXT6d z{DgP%OpSS;XB?^_&lOTE)gMn43K`lO_pYB>IQ7N$ZMWx6F3x^Xp1Lr9;}&!*9vNM@ zF;zNqbbj{g{LH0=j}F&N;0Ft(({ONxo!?{TTI1!ZTZ`{c&Cgy~ICk#nPMh;)`^4N)DFz69-%jNvNZBeYj99oiu$^EMIT!_5-}#i9Ip6>$j}3LG*x#F z4C4q7RVFaBQm!w_&*k2{W%Cg5W;iU%)m}42O~%!1zNZKNawgZEPbgfr%xpKqh{YlZ zq6lIDz7*I>_}$sKt@RCR?aH$~@Y~7qeP-GQY)7W2*M2qC^Tum-Ci}*c@3s{7bImX^ zxr}WXjj({#1V9h#1Yeajk!JF!SX@yzqe{)C{=!oWKn>4#ze}UfRUgEWN8bmx0Rmov zANWrn1cGsiic~^x>XTg2m0a0Xs64LNvaL+0lfp1@2~{92LNuh|ah2-hGI&;#{`*rVU2+*--h$#nR{};6C6=rSXf)>C9X@ zPcyk5F!A$O7C(7+VeZVr#87Es&YK%sPK%aC4TiQ8*zdvfrRh`iH%}}l+?UTf{brRC z7d|@nC?FhbwWc^Ev@S6D6?8_3wbMmNjnY%@obu`1>hLW+~XmALF!VEszU zp_x1n!J>|7*@@7Pc>tFz8yv*}Ik|#xQ$l4cfHC$Mf`<`2g5YNe9z}p269CBk0&g-3 z%!F7BClzdj6D>?da!e-h{#RDT?`2se!7Ja@wJI(W`HuQs@!@($S+?4p1_(Ju-mwdg z-2%Ro#wbyJ(1+1wUWU*54)j_4hwn6`n`8u6x4lLVE}sZeH}iZhelVda=8oXn>vBsZrJ}75e9W46dwhuMtYy! zOl?Ewq^ z7?&Xrm=3z+x_Ig8NNH%gHO@noia0X^*_X>SWv93}u-l0PS&%ORC3@HX9LO0Q+x*P+ z)_9lm3!r*FWtmTJDu4bdW|fgM0eR(ceKoYkodTX{hJiPnqP1M9eE@KVHl>wHqO&)H4Gi?^IHsgxPSe~&2 z&JEivl{R;$(tCKgz%n`8FyBl=308~tJW^-hTn((3M=R_ZzLChxv|WE#6wMc5*!n#HG2ARZL{>`8M3*%37?Jo0@Lv>V7uvWCb}?V$Lts4VMi{v&HE@5pMy-IYXx!b=uma<5mbYa%-~AszsjgGD7qqpP)}7H$NLoEp(+k{tF^G4A00~HoG4G92F(OFLa68F zXJ);lH>x$DgSopj@^0yaY47sb{EgGz>EjS;%C|m*p845>^WTmvUYtANplGE_pL*k8 zcy$4{HC|j{L#1Kdo3VX0L(SwD6e!-Zg2F)^RYJDES`Y+o&kg-xB#3!1(gDSq2GgLT zLQ7_-`h>(IxHHr~c)?CW0foF^EfumH|5j0VI)3dU_d_}6!dweuo~p=FgKuxu`b51e zYf%yv*{ir0m<7@sMxu#53mxp22%f>A5Z*YT0Oql_e6Bmw(-Qpr>y3Y}@ozH01ttRS zn@I-*T;AUC!Ye!sZoR|5vjlMgMf3M$SlQHZU9%~!{U$KX-(pm;(2_Ml0|(H^D$*qB Oq(Rj7YO8f3fB!$zuhIPg literal 0 HcmV?d00001 diff --git a/dsLightRag/Util/__pycache__/XueBanUtil.cpython-310.pyc b/dsLightRag/Util/__pycache__/XueBanUtil.cpython-310.pyc index 90aa8829c6d2c1912a4144307c3927e655188b08..f385ec8fcb68595c05d029d16aa79df929e7cabf 100644 GIT binary patch delta 1604 zcmZvc-)|E~5XX1-&gb*laZIqPG>U?SN~ue6Tc|<_rL9Cot5(eml_DZlmX$rI)z-%A zJ0T()CpZDr1VUseC?&!`(<)VyKt<&cg8I;>{tNere2()}sZyT$kj|Wc;Lz-8=T_gH znY*3&+*LZi+wD)bwP^%K>aU-_QaY#o-E??*-)jRqxuPrFt-DXjT;-lI*PzNNj5ktJOVMFH{!hYCe%j z#C#dIwxn8|tX#fU3;#Im61%~{+G*%%Bbq*!7>dRdhAvLUhIGpvLm{5DBw;43pyT35 z&wavFyaVxtqPHvOgM}(9k}9dxM}15j0$~VdbI7pr!gQ)vghiuzrwM2GXcp@A5&801 zmVz#2=nrI;Va0}bHR@^54COAaTwz%TnmfZ9J{guPvb!X`|5L)%JiUM^JQzGcQkqN* z>D=d(WF<(}4m+A5XQX`d0R!YD;ohutUP=KRct1sR{75 zM`y}UM#_&b0}>Fn;Q<$I{pRBOy<2^ujZRE*wPa6yU+1B4#a_8yUS5EQ9?#8Fp@74N zA57~$1mYQN$JxF(ZZAGAFR!f4ubAB+Kf661vRe*TJL>w#O!bdT&Ko|Po!rL3{_$b; z(Oh4szfO=ikb`6bk0cOYu?I|8wmc~l$ciTuX-jP^Emi30Ga%_=AG*HLH2ZON5DX?u zV=|S&rT8hMD)Ui44M=Evs5-(n-QxD`nULGOQg0&OQN*vVcrRJ_Hb@cJ(5;YDQ|(Cly%^=<5UefI5dh ztxliYp>GiAbJgkd0)6l+Xaqa-xwEeGu9TZQcZWXri}ba8*y3F{m^h5456p3K1WP8c z&Hds%l#haW-rttc?fd&bhem%J?Tuj47rLv6_fh=-jMX7>^`1sg>j_=NjHD1B;`Zxk zw(B$gK5xQIzY2zpz;C13XPE}5M%kvHZRz(v0%I&S8vQmFPeh|(`bF4pDakW>A{H-{ py@$Q{%W`CTL6g^ z##)9Fh7_h6hS>~rnVK0HK|E$K%~->b!ji(;%T&t<6l1GlgsDhj4`$HhDAfRJ=TZQI zXIr~pte^UH?Xo9(wmjXw^l9t%=d)U#?AZOZeebiW8^B6Rd4P(a?5$t$Y{vQ*8yes5 znP18Q6nQy)-OEKYtQ1NmfSeb7+n@GNgBmlr_vx-FPj;-;)6;X)WGrF>%9rv32`*%L zD+NDIrXnSvaFG#^&}6#BQCON @@ -66,10 +123,56 @@ 正在录音... + +
+
+
+
+
+
+ 学伴正在思考中... +
+
- - + + +
+ + +
+
+
+ + + + + + 你讲的话 +
+
+
+
+ +
+
+
+ +
+
+
+
00:00 / 00:00
+
@@ -83,6 +186,8 @@ // 录音相关变量 let mediaRecorder; let audioChunks = []; let isRecording = false; + // 音频播放相关变量 + let audioElement = null; let isPlaying = false; // 获取URL参数 function getUrlParam(name) { @@ -149,6 +254,9 @@ // 上传音频到服务器 function uploadAudioToServer(audioBlob) { console.log("开始上传音频到服务器"); + // 显示思考中动画 + document.getElementById('thinkingIndicator').style.display = 'flex'; + const formData = new FormData(); formData.append('file', audioBlob, 'recording.wav'); @@ -163,45 +271,137 @@ return response.json(); }) .then(data => { - console.log("ASR识别结果:", data); + console.log("处理结果:", data); + // 隐藏思考中动画 + document.getElementById('thinkingIndicator').style.display = 'none'; + if (data.success) { - showAsrResult(data.data.text); + showResults(data.data); } else { - alert('音频识别失败: ' + data.message); + alert('音频处理失败: ' + data.message); } }) .catch(error => { console.error("上传音频失败:", error); + // 隐藏思考中动画 + document.getElementById('thinkingIndicator').style.display = 'none'; + alert('上传音频失败: ' + error.message); }); } - // 显示ASR识别结果 - function showAsrResult(text) { - // 检查是否已存在结果显示元素 - let resultElement = document.getElementById('asrResult'); - if (!resultElement) { - resultElement = document.createElement('div'); - resultElement.id = 'asrResult'; - resultElement.style.position = 'fixed'; - resultElement.style.bottom = '80px'; - resultElement.style.left = '20px'; - resultElement.style.zIndex = '1000'; - resultElement.style.padding = '10px 15px'; - resultElement.style.backgroundColor = 'rgba(0, 123, 255, 0.9)'; - resultElement.style.color = 'white'; - resultElement.style.borderRadius = '5px'; - resultElement.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)'; - document.body.appendChild(resultElement); + // 显示ASR识别结果和反馈 + function showResults(data) { + // 更新结果显示容器 + const resultContainer = document.getElementById('resultContainer'); + resultContainer.style.display = 'flex'; + + // 显示ASR结果 + document.getElementById('asrResultText').textContent = data.asr_text || '未识别到内容'; + + // 显示反馈文本 + document.getElementById('feedbackResultText').textContent = data.feedback_text || '无反馈内容'; + + // 准备音频播放 + if (data.audio_url) { + if (audioElement) { + audioElement.pause(); + audioElement = null; + } + + audioElement = new Audio(data.audio_url); + audioElement.onloadedmetadata = function() { + updateAudioTimeDisplay(); + // 音频加载完成后自动播放 + try { + audioElement.play(); + isPlaying = true; + updatePlayButton(); + } catch (e) { + console.error("自动播放失败:", e); + } + // 无论自动播放是否成功,都显示播放按钮 + document.getElementById('playAudioBtn').style.display = 'flex'; + }; + + audioElement.ontimeupdate = function() { + updateAudioProgress(); + updateAudioTimeDisplay(); + }; + + audioElement.onended = function() { + isPlaying = false; + updatePlayButton(); + }; + + // 绑定播放按钮事件 + document.getElementById('playAudioBtn').onclick = togglePlayAudio; + + // 绑定进度条点击事件 + document.getElementById('audioProgress').onclick = function(e) { + if (!audioElement) return; + + const progressBar = document.getElementById('audioProgress'); + const rect = progressBar.getBoundingClientRect(); + const clickPosition = (e.clientX - rect.left) / rect.width; + audioElement.currentTime = clickPosition * audioElement.duration; + }; } + } - resultElement.textContent = '识别结果: ' + text; - resultElement.style.display = 'block'; + // 切换音频播放/暂停 + function togglePlayAudio() { + if (!audioElement) return; - // 5秒后自动隐藏 - setTimeout(() => { - resultElement.style.display = 'none'; - }, 5000); + if (isPlaying) { + audioElement.pause(); + } else { + audioElement.play(); + } + isPlaying = !isPlaying; + updatePlayButton(); + } + + // 更新播放按钮状态 + function updatePlayButton() { + const playButton = document.getElementById('playAudioBtn'); + if (isPlaying) { + playButton.innerHTML = ` + + + + `; + } else { + playButton.innerHTML = ` + + + + `; + } + } + + // 更新音频进度条 + function updateAudioProgress() { + if (!audioElement || !audioElement.duration) return; + + const progress = (audioElement.currentTime / audioElement.duration) * 100; + document.getElementById('progressBar').style.width = `${progress}%`; + } + + // 更新音频时间显示 + function updateAudioTimeDisplay() { + if (!audioElement || !audioElement.duration) return; + + const currentTime = formatTime(audioElement.currentTime); + const duration = formatTime(audioElement.duration); + document.getElementById('audioTime').textContent = `${currentTime} / ${duration}`; + } + + // 格式化时间为 MM:SS + function formatTime(seconds) { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; } // 初始化看板娘 - 简化为Sample.html的工作版本