You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ali_voice.py 4.0KB

1 kuukausi sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # -*- coding: utf-8 -*-
  2. """
  3. Author: chazzjimel
  4. Email: chazzjimel@gmail.com
  5. wechat:cheung-z-x
  6. Description:
  7. ali voice service
  8. """
  9. import json
  10. import os
  11. import re
  12. import time
  13. from common.log import logger
  14. from voice.audio_convert import get_pcm_from_wav
  15. from voice.voice import Voice
  16. from voice.ali.ali_api import AliyunTokenGenerator, speech_to_text_aliyun, text_to_speech_aliyun
  17. from config import conf
  18. from pypinyin import pinyin, Style
  19. from common.singleton import singleton
  20. @singleton
  21. class AliVoice(Voice):
  22. def __init__(self):
  23. """
  24. 初始化AliVoice类,从配置文件加载必要的配置。
  25. """
  26. try:
  27. curdir = os.path.dirname(__file__)
  28. config_path = os.path.join(curdir, "config.json")
  29. print(config_path)
  30. with open(config_path, "r") as fr:
  31. config = json.load(fr)
  32. self.token = None
  33. self.token_expire_time = 0
  34. # 默认复用阿里云千问的 access_key 和 access_secret
  35. self.api_url_voice_to_text = config.get("api_url_voice_to_text")
  36. self.api_url_text_to_voice = config.get("api_url_text_to_voice")
  37. self.app_key = config.get("app_key")
  38. self.access_key_id = conf().get("qwen_access_key_id") or config.get("access_key_id")
  39. self.access_key_secret = conf().get("qwen_access_key_secret") or config.get("access_key_secret")
  40. except Exception as e:
  41. logger.warn("AliVoice init failed: %s, ignore " % e)
  42. def textToVoice(self, text):
  43. """
  44. 将文本转换为语音文件。
  45. :param text: 要转换的文本。
  46. :return: 返回一个Reply对象,其中包含转换得到的语音文件或错误信息。
  47. """
  48. # 清除文本中的非中文、非英文和非基本字符
  49. text = re.sub(r'[^\u4e00-\u9fa5\u3040-\u30FF\uAC00-\uD7AFa-zA-Z0-9'
  50. r'äöüÄÖÜáéíóúÁÉÍÓÚàèìòùÀÈÌÒÙâêîôûÂÊÎÔÛçÇñÑ,。!?,.]', '', text)
  51. # 提取有效的token
  52. token_id = self.get_valid_token()
  53. fileName = text_to_speech_aliyun(self.api_url_text_to_voice, text, self.app_key, token_id)
  54. if fileName:
  55. logger.info("[Ali] textToVoice text={} voice file name={}".format(text, fileName))
  56. return fileName
  57. # reply = Reply(ReplyType.VOICE, fileName)
  58. # else:
  59. # reply = Reply(ReplyType.ERROR, "抱歉,语音合成失败")
  60. # return reply
  61. def voiceToText(self, voice_file):
  62. """
  63. 将语音文件转换为文本。
  64. :param voice_file: 要转换的语音文件。
  65. :return: 返回一个Reply对象,其中包含转换得到的文本或错误信息。
  66. """
  67. # 提取有效的token
  68. token_id = self.get_valid_token()
  69. logger.debug("[Ali] voice file name={}".format(voice_file))
  70. pcm = get_pcm_from_wav(voice_file)
  71. text = speech_to_text_aliyun(self.api_url_voice_to_text, pcm, self.app_key, token_id)
  72. # print(text)
  73. if text:
  74. return text
  75. # reply = Reply(ReplyType.TEXT, text)
  76. # else:
  77. # reply = Reply(ReplyType.ERROR, "抱歉,语音识别失败")
  78. # return reply
  79. def get_valid_token(self):
  80. """
  81. 获取有效的阿里云token。
  82. :return: 返回有效的token字符串。
  83. """
  84. current_time = time.time()
  85. if self.token is None or current_time >= self.token_expire_time:
  86. get_token = AliyunTokenGenerator(self.access_key_id, self.access_key_secret)
  87. token_str = get_token.get_token()
  88. token_data = json.loads(token_str)
  89. self.token = token_data["Token"]["Id"]
  90. # 将过期时间减少一小段时间(例如5分钟),以避免在边界条件下的过期
  91. self.token_expire_time = token_data["Token"]["ExpireTime"] - 300
  92. logger.debug(f"新获取的阿里云token:{self.token}")
  93. else:
  94. logger.debug("使用缓存的token")
  95. return self.token