tts_help.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. from datetime import timedelta
  2. import requests
  3. import json
  4. import random
  5. import re
  6. import time
  7. from utils.long_tts_client import AliyunTTS
  8. from utils.aliyun_oss import Oss
  9. from loguru import logger
  10. class TTS:
  11. @classmethod
  12. def get_pw_zm(cls, text, voice):
  13. max_retries = 3
  14. for attempt in range(max_retries):
  15. url = "http://api.piaoquantv.com/produce-center/speechSynthesis"
  16. payload = json.dumps({
  17. "params": {
  18. "text": text,
  19. "voice": voice,
  20. # "vocie": "zhiyuan",
  21. "format": "pcm",
  22. "volume": 90,
  23. "speechRate": 80,
  24. "pitchRate": 0
  25. }
  26. })
  27. headers = {
  28. 'Content-Type': 'application/json'
  29. }
  30. wait_time = random.uniform(1, 10)
  31. time.sleep(wait_time)
  32. try:
  33. response = requests.request("POST", url, headers=headers, data=payload, timeout=60)
  34. response = response.json()
  35. print(response)
  36. code = response["code"]
  37. if code == 0:
  38. mp3 = response["data"]
  39. return mp3
  40. except Exception:
  41. if attempt == max_retries - 1:
  42. return None
  43. return None
  44. """
  45. 音频下载到本地
  46. """
  47. @classmethod
  48. def download_mp3(cls, pw_url, file_path):
  49. pw_mp3_path = file_path +'pw_video.mp3'
  50. for i in range(3):
  51. payload = {}
  52. headers = {}
  53. response = requests.request("GET", pw_url, headers=headers, data=payload, timeout= 30)
  54. if response.status_code == 200:
  55. # 以二进制写入模式打开文件
  56. with open(f"{pw_mp3_path}", "wb") as file:
  57. # 将响应内容写入文件
  58. file.write(response.content)
  59. return pw_mp3_path
  60. return None
  61. @classmethod
  62. def get_srt_format(cls, pw_srt_text, pw_url_sec):
  63. segments = re.split(r'(,|。|!|?)', pw_srt_text)
  64. segments = [segments[i] + segments[i + 1] for i in range(0, len(segments) - 1, 2)]
  65. pw_url_sec = int(pw_url_sec) + 1
  66. # 确定每段显示时间
  67. num_segments = len(segments)
  68. duration_per_segment = pw_url_sec / num_segments
  69. srt_content = ""
  70. start_time = 0.0
  71. for i, segment in enumerate(segments):
  72. end_time = start_time + duration_per_segment
  73. srt_content += f"{i + 1}\n"
  74. srt_content += f"{int(start_time // 3600):02}:{int((start_time % 3600) // 60):02}:{int(start_time % 60):02},{int((start_time % 1) * 1000):03} --> "
  75. srt_content += f"{int(end_time // 3600):02}:{int((end_time % 3600) // 60):02}:{int(end_time % 60):02},{int((end_time % 1) * 1000):03}\n"
  76. srt_content += f"{segment.strip()}\n\n"
  77. start_time = end_time
  78. print(srt_content)
  79. return srt_content
  80. @classmethod
  81. def process_srt(cls, srt):
  82. lines = srt.strip().split('\n')
  83. processed_lines = []
  84. for line in lines:
  85. if re.match(r'^\d+$', line):
  86. processed_lines.append(line)
  87. elif re.match(r'^\d{2}:\d{2}:\d{2}\.\d{1,3}-->\d{2}:\d{2}:\d{2}\.\d{1,3}$', line):
  88. processed_lines.append(line.replace('-->', ' --> '))
  89. else:
  90. line = re.sub(r'[,。!?;、]$', '', line)
  91. # 添加换行符
  92. processed_lines.append(line + '\n')
  93. return '\n'.join(processed_lines)
  94. @classmethod
  95. def parse_timecode(cls, timecode):
  96. h, m, s = map(float, timecode.replace(',', '.').split(':'))
  97. return timedelta(hours=h, minutes=m, seconds=s)
  98. @classmethod
  99. def format_timecode(cls, delta):
  100. total_seconds = delta.total_seconds()
  101. hours, remainder = divmod(total_seconds, 3600)
  102. minutes, seconds = divmod(remainder, 60)
  103. return f"{int(hours):02}:{int(minutes):02}:{seconds:06.3f}".replace('.', ',')
  104. @classmethod
  105. def split_subtitle(cls, subtitle_string):
  106. max_len = 14
  107. lines = subtitle_string.strip().split('\n')
  108. subtitles = []
  109. for i in range(0, len(lines), 4):
  110. sub_id = int(lines[i].strip())
  111. timecode_line = lines[i + 1].strip()
  112. start_time, end_time = timecode_line.split(' --> ')
  113. text = lines[i + 2].strip()
  114. if re.search(r'[a-zA-Z]', text):
  115. text = re.sub(r'[a-zA-Z]', '', text)
  116. start_delta = cls.parse_timecode(start_time)
  117. end_delta = cls.parse_timecode(end_time)
  118. total_duration = (end_delta - start_delta).total_seconds()
  119. char_duration = total_duration / len(text)
  120. current_start = start_delta
  121. for j in range(0, len(text), max_len):
  122. segment = text[j:j + max_len]
  123. current_end = current_start + timedelta(seconds=char_duration * len(segment))
  124. subtitles.append((sub_id, current_start, current_end, segment))
  125. current_start = current_end
  126. sub_id += 1
  127. return subtitles
  128. @classmethod
  129. def generate_srt(cls, subtitles):
  130. srt_content = ''
  131. for idx, sub in enumerate(subtitles, start=1):
  132. srt_content += f"{idx}\n"
  133. srt_content += f"{cls.format_timecode(sub[1])} --> {cls.format_timecode(sub[2])}\n"
  134. srt_content += f"{sub[3]}\n\n"
  135. return srt_content.strip()
  136. @classmethod
  137. def getSrt(cls, mp3_id):
  138. url = "http://api.piaoquantv.com/produce-center/srt/get/content"
  139. payload = json.dumps({
  140. "params": {
  141. "resourceChannel": "outer",
  142. "videoPath": mp3_id
  143. }
  144. })
  145. headers = {
  146. 'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
  147. 'Content-Type': 'application/json',
  148. 'Accept': '*/*',
  149. 'Host': 'api-internal.piaoquantv.com',
  150. 'Connection': 'keep-alive'
  151. }
  152. response = requests.request("POST", url, headers=headers, data=payload, timeout=30)
  153. time.sleep(1)
  154. data_list = response.json()
  155. code = data_list["code"]
  156. if code == 0:
  157. srt = data_list["data"]
  158. if srt:
  159. srt = srt.replace("/n", "\n")
  160. new_srt = cls.process_srt(srt)
  161. result = cls.split_subtitle(new_srt)
  162. # 生成SRT格式内容
  163. srt_content = cls.generate_srt(result)
  164. return srt_content
  165. else:
  166. return None
  167. else:
  168. return None
  169. # 长文本语音生成
  170. @classmethod
  171. def get_lone_pw_zm(cls, text, voice, file_path):
  172. # 阿里云根据文本生成语音
  173. mps_url = AliyunTTS().synthesize(text, voice)
  174. if not mps_url:
  175. return
  176. pw_mp3_path = TTS.download_mp3(mps_url, file_path)
  177. if not pw_mp3_path:
  178. return
  179. return Oss.upload_to_aliyun(pw_mp3_path)
  180. if __name__ == '__main__':
  181. # text = "真是太实用了,分享给身边的准妈妈们吧!这些孕期禁忌一定要记住,赶紧转发给更多人,帮助更多的宝妈们。一起为宝宝的健康加油!"
  182. # mp3 = TTS.get_pw_zm(text)
  183. # print(mp3)
  184. # command = [
  185. # 'ffmpeg',
  186. # '-i', mp3,
  187. # '-q:a', '0',
  188. # '-map', 'a',
  189. # # '-codec:a', 'libmp3lame', # 指定 MP3 编码器
  190. # "/Users/tzld/Desktop/video_rewriting/path/pw_video.mp3"
  191. # ]
  192. # subprocess.run(command)
  193. # print("完成")
  194. # video_file = 'http://clipres.yishihui.com/longvideo/crawler/voice/pre/20240821/37fbb8cfc7f1439b8d8a032a1d01d37f1724219959925.mp3'
  195. # TTS.getSrt(video_file)
  196. # result = subprocess.run(
  197. # ["ffprobe", "-v", "error", "-show_entries", "format=duration",
  198. # "-of", "default=noprint_wrappers=1:nokey=1", video_file],
  199. # capture_output=True, text=True)
  200. # print(float(result.stdout))
  201. voice = "zhifeng_emo"
  202. localpath = "/Users/zhangliang/Downloads/47f26a"
  203. # pw_srt_text = "讲述张鹏程校长爷爷的故事,不仅让人感动,更让我们看到教育的力量和责任。这样的故事值得让更多人知道,您可以通过下方黄色按钮,把这段感人的视频分享至您的家庭群、老乡群、朋友群,让身边的人一同感受这份温暖和感动。每一次转发,都是在传递这份爱与责任。也请您点击下方绿色按钮,发给三五个好友,尤其是那些有孩子的朋友们,让他们也了解到这位校长爷爷的无私奉献。张鹏程用自己的行动告诉我们,教育不仅仅是知识的传授,更是心灵的关怀,让孩子们在爱的环境中健康成长。您分享一次,可能会启发更多人,让我们共同传递这份爱心,让更多孩子在爱的阳光下茁壮成长。请立即行动起来,分享这个故事,让更多的人加入到关心教育、关爱孩子的行列中来。每一次转发,都是在为孩子们的未来贡献一份力量。让我们一起把这份美好传播开去!"
  204. pw_srt_text = "生活中总有一些故事能让我们感受到温暖和智慧,赵元任的传奇经历就是这样一个值得分享的好故事。各位朋友,看到这里请您立即点击下方的黄色按钮,把这个视频分享至您所在的家庭群、邻里群和兴趣群,让更多人了解这位天才的事迹,激励我们每一个人追求更好的生活。同时,也请您点击绿色按钮,直接发给您身边的朋友们,让他们一起感受这份智慧。每一次分享,都是在传播正能量,鼓励更多人去探索和学习。赵元任不仅是一位语言天才,更是教育的先行者,他用自己的方式告诉我们,学习不仅要有趣,更要通过实践来获得真正的成长。您觉得这条视频内容对您有帮助吗?如果有,请不要犹豫,赶紧分享给更多的朋友和群组,让这些感人的故事温暖每一个人的心。您的每一次分享,都是在让更多人了解到知识的力量和爱的深沉。让我们一起在这个温暖的秋季,传播智慧,分享爱,携手共进,创造更美好的未来!"
  205. # pw_srt_text = "在这个充满温情与希望的故事中,张鹏程老师用自己的行动改变了无数孩子的命运,您是否也想为这样的善举点赞呢?请您现在就点击下方黄色按钮,分享到您的家庭群、同学群和社区群,让更多人看到张老师的感人故事,感受到教育的力量。同时,别忘了点击绿色按钮,将这份感动分享给您的好友,让他们也能一起传递这份爱与责任。每一次转发,都是对张鹏程老师的支持,也是对无数孩子未来的关注。您知道吗?这样的故事值得让更多人听到,让更多人感受到教育的温暖和希望。每一个孩子都值得被关爱,他们的未来需要我们共同的努力和关心。转发这个视频,或许就能激励更多人加入到关爱贫困儿童的行列中来,赶紧分享给更多的朋友和群组"
  206. # pw_srt_text="每一句老话都蕴含着深深的智慧,想必大家看完这个视频后也有很多感触。请您马上点击下方黄色按钮,把这段珍贵的内容分享给您的微信群,让更多的人一起感受这些老祖宗的智慧,让我们的社区更加和谐。也别忘了点击绿色按钮,选几个亲密的朋友,单独发给他们,让大家都来思考一下这些道理。生活中,有些真理是我们需要时刻铭记的,尤其是对于我们的晚年生活来说,能帮助我们更好地面对生活的挑战。每一个分享,都是在传递这份智慧,让更多的人受益。您想想,如果大家都能明白这些道理,生活会变得多么美好。现在就动手,让这段视频在您的朋友圈传开,转发到家庭群、邻里群、老友群,让每个人都能感受到这份智慧的力量。您转发一次,就是在为大家的生活添砖加瓦,让我们共同努力,让这份智慧传播得更远。"
  207. # TTS.get_pw_zm(pw_srt_text, voice)
  208. # pw_srt = TTS.get_lone_pw_zm(pw_srt_text, voice,localpath)
  209. # print(pw_srt)
  210. # print(len(pw_srt_text))
  211. # {'code': 0, 'msg': 'success',
  212. # 'data': 'http://clipres.yishihui.com/longvideo/crawler/voice/prod/20250516/7bb5e293a0af43b38701419e28a5e3c11747364158315.mp3',
  213. # 'redirect': None, 'success': True}
  214. # mp3_id = "http://clipres.yishihui.com/longvideo/crawler/voice/prod/20250516/7bb5e293a0af43b38701419e28a5e3c11747364158315.mp3"
  215. # # mp3_id = "http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/jupiter-flow/tmp/f02e0751b96b4f4ea03d877e11fee4ae.wav?Expires=1747970050&OSSAccessKeyId=LTAI4G588hXC7P47wauY5e2K&Signature=u8Cn2WKpSv7xlmMWDy4Vzos1nV0%3D"
  216. # mp3_id = "http://clipres.yishihui.com/longvideo/crawler/longvoice/prod/20250516/47e9c7a769ac4a44a3e14d73ded2e49f.mp3"
  217. # print(TTS.getSrt(mp3_id))