o
    Ch|                     @   s  d Z ddlZddlZddlZddlZddlZddlZddl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 zddlmZmZ dZW n eyO   dZY nw zddlZdZW n eyc   dZY nw ddlmZmZmZmZ dd	lmZmZ dd
l m!Z! ddl"Z"zddl#m$Z$ dZ%e&d W n ey   dZ%e&d Y nw ej'ej(d e)e*Z+G dd dZ,G dd dZ-eddZ.e.j/de!dddd e- Z0e.1ddd Z2e.1ddd Z3e.4dd efd!d"Z5e.1d#d$d% Z6e.1d&d'd( Z7d:d+d,Z8e*d-krIddl9Z9ej:;ej:<e=Z>e?e> e9j@dd.ZAeAjBd/d0d1d2 eAjBd3d)d4d5 eAjBd6eCd*d7d8 eAD ZEe8eEjFeEjGeEjHd9 dS dS );zb
Full Working Speech-to-Text Server
Real-time transcription with FastAPI, WebSockets, and Whisper
    N)DictSet)Queue)get_chinese_configCHINESE_TEST_PHRASESTF)FastAPI	WebSocketWebSocketDisconnectRequest)HTMLResponseFileResponse)StaticFiles)WhisperModelu:   ✓ Faster-Whisper available - using real AI transcriptionu;   ✗ Faster-Whisper not available - using mock transcription)levelc                   @   s   e Zd Zdd Zdd ZdedefddZd	efd
dZddede	defddZ
dedefddZddede	defddZdedefddZdede	fddZdede	fddZdedefddZdS )WhisperTranscriptionServicec                 C   s(   d | _ d | _trt nd | _|   d S N)model
model_nameCHINESE_CONFIG_AVAILABLEr   chinese_configinitialize_modelself r   #/var/www/lo01.g77k.com/fw/server.py__init__5   s   z$WhisperTranscriptionService.__init__c                 C   s  t r<ztjddd | jr| jd }td n	g d}td |D ]\}}zd| }| |}|rtd	|  zt|d
dd| _|| _	td| d|  W W  n t
y   zt|ddd| _|| _	td| d|  W Y W  n t
y } ztd| d|  W Y d}~Y W q%d}~ww w td| d| d d| }tj|dd z t|dddd| _|| _	td| d|  | | W W  n< t
y } ztd| d|  W Y d}~W q%d}~ww  t
y } ztd| d|  W Y d}~q%d}~ww | jdu rt
dW dS  t
y; } ztd|  d| _W Y d}~dS d}~ww td dS ) z.Initialize Whisper model optimized for ChinesemodelsT)exist_okmodel_priorityu4   🇨🇳 Using Chinese optimized model configuration))zlarge-v3z Best quality - Chinese optimized)zlarge-v2z#High quality - Good Chinese support)mediumz#Balanced - Good Chinese performance)smallzFast - Decent Chinese support)basezFastest - Basic Chinese supportz"Using fallback model configurationmodels/u   ✓ Found existing model at: cudafloat16)devicecompute_typeu   ✓ Whisper z loaded successfully on GPU - cpuint8z loaded successfully on CPU - zFailed to load existing model : NModel z* not found locally, downloading to models/z/...auto)r%   r&   download_rootz& downloaded and loaded successfully - zFailed to download/load z	Skipping z No Whisper model could be loadedz"Failed to load any Whisper model: z/Whisper not available, using mock transcription)WHISPER_AVAILABLEosmakedirsr   loggerinfo_find_actual_model_pathr   r   r   	Exceptionwarning_organize_downloaded_modelerror)r   model_optionsr   descriptionlocal_model_pathactual_model_pathe	model_dirr   r   r   r   ;   sv   






z,WhisperTranscriptionService.initialize_model
model_pathreturnc              
   C   s   z<t j|d}t j|r|W S t |D ]#\}}}d|v r9t j|d}t j|r9td|  |  W S qW dS  tyW } ztd|  W Y d}~dS d}~ww )z2Find the actual path where model files are located	model.binzconfig.jsonz'Found model files in nested structure: NzError finding model path: )	r.   pathjoinexistswalkr0   r1   r3   r4   )r   r=   	model_binrootdirsfilesconfig_jsonr;   r   r   r   r2      s"   
z3WhisperTranscriptionService._find_actual_model_pathr   c              
   C   s   zCd| }|  |}|sW dS tj|d}tj|r)td| d W dS ||krAtd|  td| d W dS W dS  tya } ztd| d	|  W Y d}~dS d}~ww )
zPOrganize downloaded model files to the correct structure (optional optimization)r"   Nr?   r*   z is already organizedz*Model files found in nested structure at: z& will be loaded from existing locationz$Model organization check failed for r)   )	r2   r.   r@   rA   rB   r0   r1   r3   r4   )r   r   r<   actual_pathtarget_model_binr;   r   r   r   r5      s"   

$z6WhisperTranscriptionService._organize_downloaded_modelT
audio_datais_first_chunkc                 C   sf  z|r
t |dk rtd|rt |nd d W dS | ||}|du r.td W dS zWtj|tjd}t |dkr{tt	|
td	 }tt|}t|}t |}|d
 }	td|dd| d| d| d|	ddt |  n	td W W dS W n ty }
 ztd|
  W Y d}
~
nd}
~
ww | jdu r| |W S tjdddT}t|jd}|d |d	 |d
 || W d   n1 sw   Y  zxt|jd4}| }| }| }| }|t| }td| d| d| d| d|dd W d   n	1 sw   Y  d }t j!"|sVddl#}|$|j| td!| d" |dtd#t | }td$|%   W n tyr }
 ztd%|
  W Y d}
~
nd}
~
ww | j&r| j&d& }td'| j'  nd(d(d)d*dd+d,d-d.d/t(d0d1d2}| jj)|jfi |\}}td3|j* d4|j+d g }t,|D ])\}}td5| d6|j-dd7|j.dd8|j/ d9|j0dd: |1|j/2  qd;3|}td<| d=t | d: t 4|j |2 W  d   W S 1 sw   Y  W dS  ty2 }
 ztd>|
  | |W  Y d}
~
S d}
~
ww )?zTranscribe audio data to text  zAudio too short: r    bytes NzFailed to decode audio datadtype   >  zProcessed audio - RMS: z.2fz, Max: z, Min: z, Samples: z, Duration: z.3fzs, Data bytes: z Empty audio array after decodingzAudio analysis failed: .wavFsuffixdeletewb   rbzWAV file created - Frames: z, Rate: zHz, Channels: z	, Width: szdebug_audio_sample.wavzSaved audio sample to z for debugging   zFirst 20 audio samples: zWAV file check failed: transcription_paramsu;   🇨🇳 Using Chinese optimized transcription with model:    zh
transcribeg333333@g      g333333?u   以下是中文语音转录:T  )min_silence_duration_ms)	beam_sizebest_oflanguagetaskcondition_on_previous_textcompression_ratio_thresholdlog_prob_thresholdno_speech_thresholdinitial_prompt
vad_filtervad_parameterszWhisper info: language=z, probability=zSegment z: [-zs] 'z	' (prob: ) zFinal transcription: 'z' (length: zTranscription error: )5lenr0   r1   _decode_audio_datar6   np
frombufferint16sqrtmeanastypefloatmaxabsminr4   r3   r   _mock_transcriptiontempfileNamedTemporaryFilewaveopennamesetnchannelssetsampwidthsetframeratewriteframes
getnframesgetframerategetnchannelsgetsampwidthr.   r@   rB   shutilcopy2tolistr   r   dictr`   re   language_probability	enumeratestartendtextavg_logprobappendstriprA   unlink)r   rK   rL   processed_audioaudio_arrayrmsmax_amplitudemin_amplitudeduration_samplesduration_secondsr;   	temp_filewav_file	wav_checkframessample_ratechannelssample_widthduration
debug_filer   first_samplestranscribe_paramssegmentsr1   segment_textsisegmenttranscriptionr   r   r   transcribe_audio   s   








8
*Iz,WhisperTranscriptionService.transcribe_audioc                 C   s   z?t j|t jd}t|dkrW dS t t |td }|dk r&W dS tr-t	r-t	}ng d}t
|d t| }|| W S  tyI   Y dS w )	zMock transcription for testingrP   r   rO   rR   ra   )u*   这是一个语音识别系统的测试。u!   实时转录功能运行正常。u$   检测到语音活动并已处理。u   音频成功转换为文字。u$   语音转文字系统运行正常。u!   中文语音识别正在工作。u$   智能语音处理系统已激活。rM   zAudio processing completed)rs   rt   ru   rq   rv   rw   rx   ry   r   r   intr3   )r   rK   r   r   mock_phrasesphrase_indexr   r   r   r}   *  s   

z/WhisperTranscriptionService._mock_transcriptionc              
   C   s|   z!t r| |}|r|W S | |rtd |W S td |W S  ty= } ztd|  |W  Y d}~S d}~ww )z'Decode compressed audio data to raw PCMz+Data appears to be raw PCM - using directlyz.Could not decode audio - assuming raw PCM datazAudio decoding failed: N)FFMPEG_AVAILABLE_decode_with_ffmpeg_looks_like_raw_pcmr0   r1   r4   r3   r6   )r   rK   rL   decodedr;   r   r   r   rr   J  s   



z.WhisperTranscriptionService._decode_audio_datac           
      C   s  zt jddd}|| |  |j}W d   n1 sw   Y  t jddd}|j}W d   n1 s9w   Y  zz\tj|ddj|dd	d
ddd j	dddd}t
|d}|| }W d   n1 spw   Y  tdt| dt| d |W W zt| t| W W S    Y W S  tjy   | | Y W zt| t| W W S    Y W S w zt| t| W w    Y w  ty }	 ztd|	  W Y d}	~	dS d}	~	ww )zDecode Opus audio frames to PCMz.opusFrU   NrT   opusf	pcm_s16lerY   rS   zloudnorm=I=-16:LRA=11:TP=-1.5wav)acodecacarafr   Tcapture_stdoutcapture_stderrquietrZ   zFFmpeg Opus decoded:  -> rN   zOpus decoding failed: )r~   r   writeflushr   ffmpeginputoutputoverwrite_outputrunr   r   
readframesr   r0   r1   rq   r.   r   Errorr   r3   r6   )
r   rK   
input_file
input_pathoutput_fileoutput_pathresultr   pcm_datar;   r   r   r   _decode_with_ffmpeg_opus_  sh   
 


z4WhisperTranscriptionService._decode_with_ffmpeg_opusc                 C   s   t |dk rdS |dS )z.Check if audio data starts with WebM signature   F   Eߣ)rq   
startswith)r   rK   r   r   r   _looks_like_webm  s   
z,WhisperTranscriptionService._looks_like_webmc                 C   s   t |dk rdS |dd }|drdS |dr!td dS d|dd v s.|d	r0dS |d
r7dS |dr>dS td dS )z=Check if audio data looks like raw PCM rather than compressed   FNr      Cuz5Detected MediaRecorder container format - NOT raw PCM   ftyp   s         OggSs   RIFFz;No compressed format signatures detected - assuming raw PCMT)rq   r   r0   r1   )r   rK   headerr   r   r   r     s    





z/WhisperTranscriptionService._looks_like_raw_pcmc                 C   s  zt dt| d t|dkr|dd n|}t ddd |D   d}|d	r7d
}t d nd|dd v rBd}n|drId}tj|dd}|| |  |j}W d   n1 sgw   Y  d}t	j
|s|drt|d}|| W d   n1 sw   Y  t d| d tjddd}|j}	W d   n1 sw   Y  zzzt|j|	ddddd jdddd}
W nG tjy   ztj|d d!j|	ddddd jdddd}
W n" tjy   tj|d"d!j|	ddddd jdddd}
Y nw Y nw t|	d#}|| }W d   n	1 s0w   Y  t d$t| d%t| d |W W zt	| t	|	 W W S    Y W S  tjy } z.t d&|j  t d'|j  W Y d}~W zt	| t	|	 W W dS    Y W dS d}~ww zt	| t	|	 W w    Y w  ty } zt d(|  d)dl}t d*|   W Y d}~dS d}~ww )+z,Use FFmpeg to decode compressed audio to PCMzFFmpeg input: rN   r   NzAudio header bytes: c                 S   s   g | ]}t |qS r   )hex).0br   r   r   
<listcomp>  s    zCWhisperTranscriptionService._decode_with_ffmpeg.<locals>.<listcomp>rO   r   z.webmzDetected WebM formatr   r   z.mp4r   z.oggFrU   zdebug_failing_chunk.binr   rX   zSaved failing chunk to z for analysisrT   r   rY   rS   r   )r   r   r   r   Tr   webmr   matroskarZ   zFFmpeg decoded: r   zFFmpeg error - stdout: zFFmpeg error - stderr: zFFmpeg decoding failed: r   zFull traceback: )r0   r1   rq   r   r~   r   r   r   r   r.   r@   rB   r   r   r   r   r   r   r   r   r   r   r   r6   stdoutstderrr3   	traceback
format_exc)r   rK   r   file_extr   r   debug_chunk_pathr   r   r   r   r   r   r;   r   r   r   r   r     s   


 	


z/WhisperTranscriptionService._decode_with_ffmpegN)T)__name__
__module____qualname__r   r   strr2   r5   bytesboolr   r}   rr   r   r   r   r   r   r   r   r   r   4   s    Nq /!r   c                   @   sT   e Zd Zdd ZdefddZdefddZdedefd	d
Zde	defddZ
dS )ConnectionManagerc                 C   s    t  | _t | _i | _i | _d S r   )setactive_connectionsr   transcription_servicerecording_sessionschunk_countsr   r   r   r   r   "  s   
zConnectionManager.__init__	websocketc                    s6   |  I d H  | j| tdt| j  d S )Nz%Client connected. Total connections: )acceptr   addr0   r1   rq   r   r   r   r   r   connect*  s   zConnectionManager.connectc                 C   sB   | j | | j|d  | j|d  tdt| j   d S )Nz(Client disconnected. Total connections: )r   discardr   popr   r0   r1   rq   r   r   r   r   
disconnect/  s   zConnectionManager.disconnectmessagec              
      s`   z| t|I d H  W d S  ty/ } ztd|  | | W Y d }~d S d }~ww )NzError sending message: )	send_textjsondumpsr3   r0   r6   r   )r   r   r   r;   r   r   r   send_personal_message5  s   z'ConnectionManager.send_personal_messagerK   c           
   
      s   zF| j |d}|dk}|d | j |< t }|d| jj||I dH }|rEd|t  d}| ||I dH  t	
d|  W dS W dS  tyu } z"t	d|  dd	t| d
}	| |	|I dH  W Y d}~dS d}~ww )z)Process audio data and send transcriptionr   rY   Nr   )typer   	timestampzTranscribed: zAudio processing error: r6   zAudio processing failed: r  r   )r   getasyncioget_event_looprun_in_executorr   r   timer  r0   r1   r3   r6   r   )
r   rK   r   chunk_countrL   loopr   responser;   error_responser   r   r   process_audio<  s8   

	 zConnectionManager.process_audioN)r   r   r   r   r   r   r   r   r  r   r  r   r   r   r   r   !  s    r   zSpeech-to-Text Server)titlez/staticstatic)	directory)r   /c                      
   t dS )zServe main pageztemplates/index.htmlr   r   r   r   r   	get_indexg     r  z/testc                      r  )zServe test pageztemplates/test.htmlr  r   r   r   r   get_testl  r  r  z/wsr   c           	   
      s  t | I d H  z	 |  I d H }d|v rzct|d }|dd}|dkr?|dd}|r>t|}t || I d H  n9|dkr\dt j	| < dt j
| < d	d
d}t || I d H  n|dkrxdt j	| < dt j
| < d	dd}t || I d H  W n7 tjy } zddt| d}t || I d H  W Y d }~nd }~ww d|v r|d }t || I d H  q ty   t |  Y d S  ty } ztd|  t |  W Y d }~d S d }~ww )NTr   r  rO   audiodatastart_recordingr   statuszRecording startedr  stop_recordingFzRecording stoppedr6   zInvalid JSON: r   zWebSocket error: )managerr   receiver  loadsr  base64	b64decoder  r   r   r  JSONDecodeErrorr   r	   r   r3   r0   r6   )	r   r  r   message_type	audio_b64rK   r  r;   r  r   r   r   websocket_endpointq  sT   






&r'  z/healthc                      s   dt ttjdS )zHealth check endpointhealthy)r  whisper_availabler   )r-   rq   r  r   r   r   r   r   health_check  s
   r*  z/model-infoc                     sT   t ttjjdutjjddd} tjjr(tjjd tjjd tjjd d| d	< | S )
z&Get information about the loaded modelNzChinese (zh)zChinese language optimized)r)  chinese_config_availablemodel_loadedr   re   optimizationr]   audio_configchinese_settings)r]   r.  r/  configuration)r-   r   r  r   r   r   r   )
model_infor   r   r   r1    s   
	



r1  0.0.0.0@  c                 C   s   |rdnd}|r
dnd}d}t r"tjjdur"tjjpd}d| d	}td
| d|r+dnd d| d|  d| d| d|  d| d| d|  d| d t| |ddd}|r^|ddd tj	di | dS )zRun the serverhttpshttpwsswsz2Mock transcription (install faster-whisper for AI)NunknownzWhisper Model: u    (中文模式)u   
🎤 中文语音识别服务器 / Chinese Speech-to-Text Server
====================================================

✓ FastAPI backend with WebSocket support
✓ uq   
✓ Real-time Chinese audio processing
✓ Browser microphone integration
✓ Production-ready architecture
✓ zHTTPS enabled (SSL/TLS)z	HTTP modez


Server: z://:z
WebSocket: z/ws
Health: z5/health
Language: Chinese (zh)

Press Ctrl+C to stop
r1   T)apphostport	log_level
access_logzkey.pemzcert.pem)ssl_keyfilessl_certfiler   )
r-   r  r   r   r   printr:  updateuvicornr   )r;  r<  sslprotocolws_protocolr1  r   uvicorn_configr   r   r   
run_server  sR   
	
rH  __main__)r8   z--ssl
store_truezEnable HTTPS/SSL)actionhelpz--hostzHost to bind to)defaultrL  z--portzPort to bind to)r  rM  rL  )r;  r<  rD  )r2  r3  F)I__doc__r  r  loggingr"  ior   numpyrs   typingr   r   r.   r~   	threadingqueuer   r   r   r   r   ImportErrorr   r   fastapir   r   r	   r
   fastapi.responsesr   r   fastapi.staticfilesr   rC  faster_whisperr   r-   rA  basicConfigINFO	getLoggerr   r0   r   r   r:  mountr  r  r  r  r   r'  r*  r1  rH  argparser@   dirnameabspath__file__
script_dirchdirArgumentParserparseradd_argumentr   
parse_argsargsr;  r<  rD  r   r   r   r   <module>   s   
   p
>

0



.
