test_stt_xjp.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import logging
  2. import os
  3. import base64
  4. import signal
  5. import sys
  6. import time
  7. import dashscope
  8. from dashscope.audio.qwen_omni import *
  9. from dashscope.audio.qwen_omni.omni_realtime import TranscriptionParams
  10. def setup_logging():
  11. """配置日志输出"""
  12. logger = logging.getLogger('dashscope')
  13. logger.setLevel(logging.DEBUG)
  14. handler = logging.StreamHandler(sys.stdout)
  15. handler.setLevel(logging.DEBUG)
  16. formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  17. handler.setFormatter(formatter)
  18. logger.addHandler(handler)
  19. logger.propagate = False
  20. return logger
  21. def init_api_key():
  22. """初始化 API Key"""
  23. # 新加坡和北京地域的API Key不同。获取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
  24. # 若没有配置环境变量,请用百炼API Key将下行替换为:dashscope.api_key = "sk-xxx"
  25. dashscope.api_key = "sk-28defb4cde1c440c9f26191b0c781aaf"
  26. #dashscope.api_key = "sk-92f2fec23dc94de49a31c9945d04e5f7"
  27. if dashscope.api_key == 'YOUR_API_KEY':
  28. print('[Warning] Using placeholder API key, set DASHSCOPE_API_KEY environment variable.')
  29. class MyCallback(OmniRealtimeCallback):
  30. """实时识别回调处理"""
  31. def __init__(self, conversation):
  32. self.conversation = conversation
  33. self.handlers = {
  34. 'session.created': self._handle_session_created,
  35. 'conversation.item.input_audio_transcription.completed': self._handle_final_text,
  36. 'conversation.item.input_audio_transcription.text': self._handle_stash_text,
  37. 'input_audio_buffer.speech_started': lambda r: print('======Speech Start======'),
  38. 'input_audio_buffer.speech_stopped': lambda r: print('======Speech Stop======'),
  39. 'response.done': self._handle_response_done
  40. }
  41. def on_open(self):
  42. print('Connection opened')
  43. def on_close(self, code, msg):
  44. print(f'Connection closed, code: {code}, msg: {msg}')
  45. def on_event(self, response):
  46. try:
  47. handler = self.handlers.get(response['type'])
  48. if handler:
  49. handler(response)
  50. except Exception as e:
  51. print(f'[Error] {e}')
  52. def _handle_session_created(self, response):
  53. print(f"Start session: {response['session']['id']}")
  54. def _handle_final_text(self, response):
  55. print(f"Final recognized text: {response['transcript']}")
  56. def _handle_stash_text(self, response):
  57. print(f"Got stash result: {response['stash']}")
  58. def _handle_response_done(self, response):
  59. print('======RESPONSE DONE======')
  60. print(f"[Metric] response: {self.conversation.get_last_response_id()}, "
  61. f"first text delay: {self.conversation.get_last_first_text_delay()}, "
  62. f"first audio delay: {self.conversation.get_last_first_audio_delay()}")
  63. def read_audio_chunks(file_path, chunk_size=3200):
  64. """按块读取音频文件"""
  65. with open(file_path, 'rb') as f:
  66. while chunk := f.read(chunk_size):
  67. yield chunk
  68. def send_audio(conversation, file_path, delay=0.1):
  69. """发送音频数据"""
  70. if not os.path.exists(file_path):
  71. raise FileNotFoundError(f"Audio file {file_path} does not exist.")
  72. print("Processing audio file... Press 'Ctrl+C' to stop.")
  73. for chunk in read_audio_chunks(file_path):
  74. audio_b64 = base64.b64encode(chunk).decode('ascii')
  75. conversation.append_audio(audio_b64)
  76. time.sleep(delay)
  77. # enable_turn_detection为False时需要手动提交
  78. conversation.commit()
  79. print("Audio commit sent.")
  80. def main():
  81. setup_logging()
  82. init_api_key()
  83. audio_file_path = "./asr_example.pcm"
  84. conversation = OmniRealtimeConversation(
  85. model='qwen3-asr-flash-realtime',
  86. # 以下为新加坡地域url,若使用北京地域的模型,需将url替换为:wss://dashscope.aliyuncs.com/api-ws/v1/realtime
  87. url='wss://dashscope-intl.aliyuncs.com/api-ws/v1/realtime',
  88. callback=MyCallback(conversation=None) # 暂时传None,稍后注入
  89. )
  90. # 注入自身到回调
  91. conversation.callback.conversation = conversation
  92. def handle_exit(sig, frame):
  93. print('Ctrl+C pressed, exiting...')
  94. conversation.close()
  95. sys.exit(0)
  96. signal.signal(signal.SIGINT, handle_exit)
  97. conversation.connect()
  98. transcription_params = TranscriptionParams(
  99. language='zh',
  100. sample_rate=16000,
  101. input_audio_format="pcm"
  102. # 输入音频的语料,用于辅助识别
  103. # corpus_text=""
  104. )
  105. conversation.update_session(
  106. output_modalities=[MultiModality.TEXT],
  107. enable_input_audio_transcription=True,
  108. transcription_params=transcription_params,
  109. enable_turn_detection=False # 禁用VAD,手动提交音频
  110. )
  111. try:
  112. send_audio(conversation, audio_file_path)
  113. time.sleep(3) # 等待响应
  114. except Exception as e:
  115. print(f"Error occurred: {e}")
  116. finally:
  117. conversation.close()
  118. print("Audio processing completed.")
  119. if __name__ == '__main__':
  120. main()