WsParamSynthesizeObject.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import websocket
  2. import datetime
  3. import hashlib
  4. import base64
  5. import hmac
  6. import json
  7. from urllib.parse import urlencode
  8. import ssl
  9. from wsgiref.handlers import format_date_time
  10. from datetime import datetime
  11. from time import mktime
  12. import _thread as thread
  13. import os
  14. """
  15. 调用讯飞模型 文字转语音
  16. """
  17. class WsParamSynthesize:
  18. def __init__(self, APPID, APIKey, APISecret, Text, output_file='demo.pcm'):
  19. self.APPID = APPID
  20. self.APIKey = APIKey
  21. self.APISecret = APISecret
  22. self.Text = Text
  23. self.output_file = output_file
  24. # 初始化其他需要的属性
  25. self.CommonArgs = {"app_id": self.APPID}
  26. self.BusinessArgs = {"aue": "raw", "auf": "audio/L16;rate=16000", "vcn": "xiaoyan", "tte": "utf8"}
  27. self.Data = {"status": 2, "text": str(base64.b64encode(self.Text.encode('utf-8')), "UTF8")}
  28. def create_url(self):
  29. url = 'wss://tts-api.xfyun.cn/v2/tts'
  30. # 生成RFC1123格式的时间戳
  31. now = datetime.now()
  32. date = format_date_time(mktime(now.timetuple()))
  33. # 拼接字符串
  34. signature_origin = "host: " + "ws-api.xfyun.cn" + "\n"
  35. signature_origin += "date: " + date + "\n"
  36. signature_origin += "GET " + "/v2/tts " + "HTTP/1.1"
  37. # 进行hmac-sha256进行加密
  38. signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'),
  39. digestmod=hashlib.sha256).digest()
  40. signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
  41. authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
  42. self.APIKey, "hmac-sha256", "host date request-line", signature_sha)
  43. authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
  44. # 将请求的鉴权参数组合为字典
  45. v = {
  46. "authorization": authorization,
  47. "date": date,
  48. "host": "ws-api.xfyun.cn"
  49. }
  50. # 拼接鉴权参数,生成url
  51. url = url + '?' + urlencode(v)
  52. # print("date: ",date)
  53. # print("v: ",v)
  54. # 此处打印出建立连接时候的url,参考本demo的时候可取消上方打印的注释,比对相同参数时生成的url与自己代码生成的url是否一致
  55. # print('websocket url :', url)
  56. return url
  57. def on_message(self, ws, message):
  58. try:
  59. print("Received message:", message) # 打印接收到的消息
  60. message = json.loads(message)
  61. code = message["code"]
  62. sid = message["sid"]
  63. audio = message["data"]["audio"]
  64. audio = base64.b64decode(audio)
  65. status = message["data"]["status"]
  66. print(message)
  67. if status == 2:
  68. print("WebSocket connection is closed.")
  69. ws.close()
  70. if code != 0:
  71. errMsg = message["message"]
  72. print(f"sid:{sid} call error:{errMsg} code is:{code}")
  73. else:
  74. print("Writing audio data to file.")
  75. with open(self.output_file, 'ab') as f:
  76. f.write(audio)
  77. except Exception as e:
  78. print("Receive message, but parse exception:", e)
  79. # on_error和on_close方法类似地修改,可以访问类实例的属性
  80. def on_error(self, error):
  81. print("### error:", error)
  82. # 收到websocket关闭的处理
  83. def on_close(self):
  84. print("### closed ###")
  85. def on_open(self, ws):
  86. def run(*args):
  87. print("WebSocket connection is open.")
  88. d = {"common": self.CommonArgs, "business": self.BusinessArgs, "data": self.Data}
  89. d = json.dumps(d)
  90. print("Sending text data...")
  91. ws.send(d)
  92. if os.path.exists(self.output_file):
  93. os.remove(self.output_file)
  94. print("Starting new thread for sending data...")
  95. thread.start_new_thread(run, ())
  96. def start(self):
  97. websocket.enableTrace(False)
  98. self.ws = websocket.WebSocketApp(self.create_url(),
  99. on_message=lambda ws, msg: self.on_message(ws, msg),
  100. on_error=lambda msg: self.on_error(msg),
  101. on_close=self.on_close,
  102. on_open=lambda ws: self.on_open(ws)) # 使用 lambda 来确保 ws 参数传递
  103. self.ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})