
    ՙiG?                        U d dl Z d dlZd dlZd dlmZ d dlmZmZ d dlZd dl	Z	d dl
Z
d dlmZmZmZmZ d dlmZ d dlmZ d dlmZ daee   ed<    e j0                  d	d
      j3                         Z e	j6                   ee	ee	j:                                e	j<                  e      Z e jC                   ee	ee	j:                               edefd       Z" edde"      Z# e$ e j0                  dd            Z%de&de$dee&   fdZ'e#jQ                  d       ed      fdedefd       Z)edk(  rd dl*Z* e*jV                  ddd       yy)     N)asynccontextmanager)ListOptional)FastAPIFileHTTPException
UploadFile)JSONResponse)AudioSegment)Qwen3ASRModelMODEL	LOG_LEVELINFO)level_c                  K   t         j                  d       t        j                         }t        j                  j                         st        d      t        j                  ddt        j                  dddddd	t        t        j                  d
      
      at        j                         |z
  }t         j                  d|dd       t         j                  dt        t        dd               d  y w)Nu(   【开始加载 Qwen3-ASR-0.6B 模型】u?   未检测到 GPU（CUDA），请确认容器已正确启用 GPUzQwen/Qwen3-ASR-0.6Bz/app/hf_cachecudaT       zQwen/Qwen3-ForcedAligner-0.6Bzcuda:0)dtype
device_map)		cache_dirtorch_dtyper   low_cpu_mem_usageuse_safetensorsmax_inference_batch_sizemax_new_tokensforced_alignerforced_aligner_kwargsu!   ✅ 模型加载完成！耗时: z.2fu    秒zforced_aligner: r   )loggerinfotimetorchr   is_availableRuntimeErrorr   from_pretrainedfloat16dictbfloat16r   getattr)r   
start_load	load_times      /app/qwen_asr_service.pylifespanr.      s      KK:;J::""$\]]))!MM!"6"..
E 		j(I
KK3Ic?$GH
KK"752BD#I"JKL	s   C7C9zQwen3 ASR APIz1.0.0)titleversionr.   ASR_CHUNK_SECONDS15	file_pathchunk_secondsreturnc                 d   t        j                  |       }t        d|      dz  }g }t        dt	        |      |      D ]d  }||z   }||| }t        j                  dd      5 }|j                  |j                  d       |j                  |j                         d d d        f |S # 1 sw Y   rxY w)	Nr   i  r   F.wavdeletesuffixwav)format)
r   	from_filemaxrangelentempfileNamedTemporaryFileexportnameappend)	r3   r4   audiochunk_mschunksstartendsegmenttmps	            r-   split_audio_to_chunksrM   9   s    ""9-E1m$t+HFq#e*h/hc"((fENN388EN2MM#((# FE 0 M FEs   !9B&&B/	z/transcribe.filec                   K   t         t        dd      t        j                  d       | j                  xs dj                         }|j                  d      s|j                  d      st        dd	      |j                  d      rdnd}t        j                  d
|      5 }|j                  | j                          d {          |j                  }d d d        t        j                  d        	 t        j                         }t        |t              }g }d }t        j                  d|        d}	g }
|D ]  }t        j                  d| d|	        t         j                  |d d      }t        j                  d| d|        	 t        j                  d|t!        j"                  |t$        d
             	 t+        j,                  |      }t/        |      dz  }|r|xs |d   j0                  }|j3                  |d   j4                         t7        |d   dd       xs) t9        |d   t:              r|d   j=                  d      nd }|		 |d   d   }|D ]a  }t9        |t:              rt?        |j=                  d|j=                  d|j=                  dd                        }t?        |j=                  d|j=                  d|j=                  d |                        }|j=                  d!|j=                  d"d            }nt7        |dd       }t7        |dd       }|tA        |d      rt7        |d      }|tA        |d       rt7        |d       }|d}||}	 t?        |      }	 t?        |      }t7        |d!t7        |d"d            }|
j3                  tC        ||	z   d#      tC        ||	z   d#      |d$       d |st        jE                  d%| d&       |	|z  }	 t        j                         |z
  }|st        d'd(      t        j                  d)t/        |       d*tC        |d+              d,tF        t:           d-t$        d.tF        t:           fd/}djI                  |      }d,tF        t:           d-t$        d.tF        t:           fd0} ||
|      }d1tF        t:           d.tF        t:           fd2} ||      }tK        |d3jI                  |      jM                         tC        |d+      t/        |      |d4      	 tO        jP                  |       	 tU               j=                  d5g       D ]  }	 tO        jP                  |        S 7 # 1 sw Y   xY w# t&        $ r$ t        j                  d|t)        |             Y w xY w# t&        $ r
 t        }Y w xY w# t&        $ r g }Y Ww xY w# t&        $ r d}Y Xw xY w# t&        $ r |}Y ^w xY w# tR        $ r Y w xY w# tR        $ r Y w xY w# t&        $ r Y S w xY w# 	 tO        jP                  |       n# tR        $ r Y nw xY w	 tU               j=                  d5g       D ]'  }	 tO        jP                  |       # tR        $ r Y %w xY w w # t&        $ r Y w w xY wxY ww)6Ni  u   模型尚未加载完成)status_codedetailu   /transcribe 请求开始 r7   z.mp3i  u   仅支持 wav 或 mp3 文件Fr8   u   上传临时文件: u   分块文件:         u   开始转写分块: z, start_offset=T)rF   languagereturn_time_stampszraw results for z: zresults json for %s: %s)defaultensure_asciizresults repr for %s: %sg     @@r   time_stampsrI   begin
start_timerJ   finishend_timetextword   rI   rJ   r]   u   分块 u     未返回 time_stamps 或为空i  u   识别失败u   转写完成: chunks=z, time_sec=   segments	full_textr5   c           	      F   | sg S t        t        d            }g }g }d }d }d}|D ]  }|j                         r|j                  |       %||v r`|j                  |       |F|j                  t	        |d      t	        |d      dj                  |      j                         d       g }d }d }|t        |       k  rV| |   }	|dz  }|	j                  dd      }
|j                  |
r|
n|       ||	j                  d      }|	j                  d	      }|j                  |        |H|rF|j                  t	        |d      t	        |d      dj                  |      j                         d       |t        |       k  r|r|d
   }| |   j                  d      }| d
   j                  d	      }t	        |d      |d	<   dj                  | |d  D cg c]  }|j                  dd       c}      }|j                  dd      |z   j                         |d<   |S dj                  | |d  D cg c]  }|j                  dd       c}      }|j                  t	        | |   j                  dd      d      t	        | d
   j                  d	d      d      |d       |S c c}w c c}w )N   。.!?！？r   r_   rR   r`   r   r]   rI   rJ   )	setlistisspacerE   roundjoinstripr@   get)rb   rc   sentence_end_charsmergedcur_text_parts	cur_startcur_end	token_idxchseg
token_textlastremaining_startremaining_endsrem_texts                   r-   %merge_time_stamps_by_text_punctuationz?transcribe_audio.<locals>.merge_time_stamps_by_text_punctuation   s   	!$T.%9!:!#F(*NIGI::<"))"-++"))"- ,i0CERY[\L]gigngno}g~  hE  hE  hG  'H  I%'N $I"G s8},"9-CNI!$!4J"))
*K ($'GGG$4	!ggenG #))"-=  B $i(;E'STDU_a_f_fgu_v_|_|_~  A3x=(!":D&.y&9&=&=g&FO$,RL$4$4U$;M"'q"9DK!ww8IJCW'XCWafb(9CW'XYH$(HHVR$88$C#J#J#LDL
 M  "ww8IJCW'XCWafb(9CW'XYHMME(92E2I2I'ST2UWX,Ybghpqshthxhxy~  AB  iC  EF  cG  QY  #Z  [M (Y (Ys   J(Jc                    |s| S t        t        d            }g }d}d}d}t        |      }||k  r||   }|j                         r|dz  }!||v r/|j	                  t        |d      t        |d      |d       |dz  }T|t        |       k  r| |   }	|	j                  dd      }
|
r|j                  |
|      }n|}|d	k(  r.|j	                  |	       |	j                  d
|      }|dz  }|dz  }n||k  rI||   }|j                         s)|j	                  t        |d      t        |d      |d       |dz  }||k  rI|j	                  |	       |	j                  d
|      }|dz  }|t        dt        |
            z   }n>|j                         s)|j	                  t        |d      t        |d      |d       |dz  }||k  rt        |t        |             D ]  }|j	                  | |           |S )Nu   。.!?！？.,，、r   rS   r   r_   r`   r]   rR   rf   rJ   )
rg   rh   r@   ri   rE   rj   rm   findr>   r?   )rb   rc   rn   	augmentedrs   ilast_endnrt   ru   rv   jch2ks                 r-   !insert_punctuations_into_segmentsz;transcribe_audio.<locals>.insert_punctuations_into_segments   s   !$T*@%A!B$&IIAHIAa%q\::<FA ++$$uXq/A%PXZ[J\fh%ijFA s8},"9-C!$!4J!%NN:q9Bw!((-#&775(#;!Q	Q  !e"+A,C#&;;= ) 0 051;MV[\dfgVhru1v wFA	  !e "((-#&775(#;!Q	As: 77 ::<!((513EeT\^_N`jl)mnFAY a%^ 9c(m4  !- 5     tokensc           
      x   t        t        d            }g }g }d }d }| D ]  }|j                  dd      }|st        |      dk(  rt||v rp|j	                  |       |V|j	                  t        |d      t        |j                  d|      d      dj                  |      j                         d       g }d }d }||j                  d      }|j                  d      }|j	                  |        |H|rF|j	                  t        |d      t        |d      dj                  |      j                         d       |S )	Nre   r]   rR   r   r_   rJ   r`   rI   )rg   rh   rm   r@   rE   rj   rk   rl   )r   rn   ro   rp   rq   rr   ttxts           r-   merge_sentences_from_tokensz5transcribe_audio.<locals>.merge_sentences_from_tokens/  s[   !$T.%9!:!#F(*NIGeeFB's8q=S,>%>"))#. ,i0CERSRWRWX]_fRgijLkuwu|u|  ~L  vM  vS  vS  vU  'V  W%'N $I"G $ !gI%%,%%c*' , $i(;E'STDU_a_f_fgu_v_|_|_~  AMr    )rT   r]   time_secrH   rX   chunk_paths)+r   r   r    r!   filenamelowerendswithrA   rB   writereadrD   r"   rM   CHUNK_SECONDS
transcribejsondumpsstr	Exceptionreprr   r=   r@   rT   rE   r]   r*   
isinstancer(   rm   floathasattrrj   warningr   rk   r
   rl   osremoveOSErrorlocals)rN   r   r:   rL   tmp_pathstart_inferr   textsrT   start_offsetall_time_stamps
chunk_pathresultsru   chunk_durationts_listtsrI   rJ   text_seg
start_attrend_attr
infer_timer|   rc   r   time_stamps_tokensr   merged_time_stampss                                r-   transcribe_audior   F   sO    }4NOO
KK*+#**,Hf%):):6)B4RSS((0VfF		$	$E&	AS				#$88 
B KK&xj12Qiik+HmD"&n[M23 &(%JKK.zl/,XY&&Z$[_&`GKK*:,b	BCR5z4::g_bqvCwx/",,Z8!$SF!2 #:wqz':':WQZ__-!'!*mTB  Phrsz{|s}  @D  iEwqz~~VcGd  KO?%")!*]"; "B!"d+ %bffWbffWbff\[\F]6^&_ `#BFF5"&&266*V[C\2]$^_#%66&"&&2D#E &-R$%?
#*2ud#;%-'"l2K)0\)BJ#+J0G'.r:'>H%-),J#+'1H($)*$5E("'/C $+2vwr627N#O#**!&u|';Q!?$S<%7; (, ; "D NNWZL8X#YZN*LE &H YY[;.
CGG+C,<+=[zZ[I\H]^_<	DJ <	SV <	[_`d[e <	| GGEN	<	T
 <	s <	W[\`Wa <	| ?PYZ 	T
  	tDz  	D 99KL$--/!*a0k*1
	IIh	$hll="=
IIj) >_ $ 
B	A.  R5z4=QR  /!./ % %"$%0  ) ($'E(  ) ("'C(N  		   			IIh 			$hll="=
IIj)  >
  		s  B"Z$UU
U Z9BX 1U$#V'A1X V*!DX 'V<3W>F	X W W><W/W>ZUU!Z$)VX VX V'#X &V''X *V95X 8V99X <WX 
WX WX WX  	W,)Z+W,,Z/	W;8W>:W;;W>>	X
Z	X

ZZ	X%$Z	%	X1.Z	0X11Z	5Y:Y)(Y:)	Y5	2Y:4Y5	5Y:9Z	:	ZZ	ZZ		Z__main__zqwen_asr_service:appz0.0.0.0i@  )hostport),r   r"   rA   
contextlibr   typingr   r   r#   loggingr   fastapir   r   r   r	   fastapi.responsesr
   pydubr   qwen_asrr   r   __annotations__getenvupperr   basicConfigr*   r   	getLogger__name__r    setLevelr.   appintr   r   rM   postr   uvicornrun r   r-   <module>r      s]   	   * !    < < *  "!%x % BIIk6*002	   ''9gllC D			8	$ GLL9 : 
g 
 
6 OWxHIBII1489
S 
 
c 
 -.23i a aL a aH	 zGKK&YTB r   