tts_help.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. from datetime import timedelta
  2. import requests
  3. import json
  4. import random
  5. import re
  6. import time
  7. class TTS:
  8. @classmethod
  9. def get_pw_zm(cls, text, voice):
  10. max_retries = 3
  11. for attempt in range(max_retries):
  12. url = "http://api.piaoquantv.com/produce-center/speechSynthesis"
  13. payload = json.dumps({
  14. "params": {
  15. "text": text,
  16. "voice": voice,
  17. # "vocie": "zhiyuan",
  18. "format": "pcm",
  19. "volume": 90,
  20. "speechRate": 80,
  21. "pitchRate": 0
  22. }
  23. })
  24. headers = {
  25. 'Content-Type': 'application/json'
  26. }
  27. wait_time = random.uniform(1, 10)
  28. time.sleep(wait_time)
  29. try:
  30. response = requests.request("POST", url, headers=headers, data=payload, timeout=60)
  31. response = response.json()
  32. code = response["code"]
  33. if code == 0:
  34. mp3 = response["data"]
  35. return mp3
  36. except Exception:
  37. if attempt == max_retries - 1:
  38. return None
  39. return None
  40. """
  41. 音频下载到本地
  42. """
  43. @classmethod
  44. def download_mp3(cls, pw_url, file_path):
  45. pw_mp3_path = file_path +'pw_video.mp3'
  46. for i in range(3):
  47. payload = {}
  48. headers = {}
  49. response = requests.request("GET", pw_url, headers=headers, data=payload, timeout= 30)
  50. if response.status_code == 200:
  51. # 以二进制写入模式打开文件
  52. with open(f"{pw_mp3_path}", "wb") as file:
  53. # 将响应内容写入文件
  54. file.write(response.content)
  55. return pw_mp3_path
  56. return None
  57. @classmethod
  58. def get_srt_format(cls, pw_srt_text, pw_url_sec):
  59. segments = re.split(r'(,|。|!|?)', pw_srt_text)
  60. segments = [segments[i] + segments[i + 1] for i in range(0, len(segments) - 1, 2)]
  61. pw_url_sec = int(pw_url_sec) + 1
  62. # 确定每段显示时间
  63. num_segments = len(segments)
  64. duration_per_segment = pw_url_sec / num_segments
  65. srt_content = ""
  66. start_time = 0.0
  67. for i, segment in enumerate(segments):
  68. end_time = start_time + duration_per_segment
  69. srt_content += f"{i + 1}\n"
  70. 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} --> "
  71. 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"
  72. srt_content += f"{segment.strip()}\n\n"
  73. start_time = end_time
  74. print(srt_content)
  75. return srt_content
  76. @classmethod
  77. def process_srt(cls, srt):
  78. lines = srt.strip().split('\n')
  79. processed_lines = []
  80. for line in lines:
  81. if re.match(r'^\d+$', line):
  82. processed_lines.append(line)
  83. elif re.match(r'^\d{2}:\d{2}:\d{2}\.\d{1,3}-->\d{2}:\d{2}:\d{2}\.\d{1,3}$', line):
  84. processed_lines.append(line.replace('-->', ' --> '))
  85. else:
  86. line = re.sub(r'[,。!?;、]$', '', line)
  87. # 添加换行符
  88. processed_lines.append(line + '\n')
  89. return '\n'.join(processed_lines)
  90. @classmethod
  91. def parse_timecode(cls, timecode):
  92. h, m, s = map(float, timecode.replace(',', '.').split(':'))
  93. return timedelta(hours=h, minutes=m, seconds=s)
  94. @classmethod
  95. def format_timecode(cls, delta):
  96. total_seconds = delta.total_seconds()
  97. hours, remainder = divmod(total_seconds, 3600)
  98. minutes, seconds = divmod(remainder, 60)
  99. return f"{int(hours):02}:{int(minutes):02}:{seconds:06.3f}".replace('.', ',')
  100. @classmethod
  101. def split_subtitle(cls, subtitle_string):
  102. max_len = 14
  103. lines = subtitle_string.strip().split('\n')
  104. subtitles = []
  105. for i in range(0, len(lines), 4):
  106. sub_id = int(lines[i].strip())
  107. timecode_line = lines[i + 1].strip()
  108. start_time, end_time = timecode_line.split(' --> ')
  109. text = lines[i + 2].strip()
  110. if re.search(r'[a-zA-Z]', text):
  111. text = re.sub(r'[a-zA-Z]', '', text)
  112. start_delta = cls.parse_timecode(start_time)
  113. end_delta = cls.parse_timecode(end_time)
  114. total_duration = (end_delta - start_delta).total_seconds()
  115. char_duration = total_duration / len(text)
  116. current_start = start_delta
  117. for j in range(0, len(text), max_len):
  118. segment = text[j:j + max_len]
  119. current_end = current_start + timedelta(seconds=char_duration * len(segment))
  120. subtitles.append((sub_id, current_start, current_end, segment))
  121. current_start = current_end
  122. sub_id += 1
  123. return subtitles
  124. @classmethod
  125. def generate_srt(cls, subtitles):
  126. srt_content = ''
  127. for idx, sub in enumerate(subtitles, start=1):
  128. srt_content += f"{idx}\n"
  129. srt_content += f"{cls.format_timecode(sub[1])} --> {cls.format_timecode(sub[2])}\n"
  130. srt_content += f"{sub[3]}\n\n"
  131. return srt_content.strip()
  132. @classmethod
  133. def getSrt(cls, mp3_id):
  134. url = "http://api.piaoquantv.com/produce-center/srt/get/content"
  135. payload = json.dumps({
  136. "params": {
  137. "resourceChannel": "outer",
  138. "videoPath": mp3_id
  139. }
  140. })
  141. headers = {
  142. 'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
  143. 'Content-Type': 'application/json',
  144. 'Accept': '*/*',
  145. 'Host': 'api-internal.piaoquantv.com',
  146. 'Connection': 'keep-alive'
  147. }
  148. response = requests.request("POST", url, headers=headers, data=payload, timeout=30)
  149. time.sleep(1)
  150. data_list = response.json()
  151. code = data_list["code"]
  152. if code == 0:
  153. srt = data_list["data"]
  154. if srt:
  155. srt = srt.replace("/n", "\n")
  156. new_srt = cls.process_srt(srt)
  157. result = cls.split_subtitle(new_srt)
  158. # 生成SRT格式内容
  159. srt_content = cls.generate_srt(result)
  160. return srt_content
  161. else:
  162. return None
  163. else:
  164. return None
  165. if __name__ == '__main__':
  166. # text = "真是太实用了,分享给身边的准妈妈们吧!这些孕期禁忌一定要记住,赶紧转发给更多人,帮助更多的宝妈们。一起为宝宝的健康加油!"
  167. # mp3 = TTS.get_pw_zm(text)
  168. # print(mp3)
  169. # command = [
  170. # 'ffmpeg',
  171. # '-i', mp3,
  172. # '-q:a', '0',
  173. # '-map', 'a',
  174. # # '-codec:a', 'libmp3lame', # 指定 MP3 编码器
  175. # "/Users/tzld/Desktop/video_rewriting/path/pw_video.mp3"
  176. # ]
  177. # subprocess.run(command)
  178. # print("完成")
  179. video_file = 'http://clipres.yishihui.com/longvideo/crawler/voice/pre/20240821/37fbb8cfc7f1439b8d8a032a1d01d37f1724219959925.mp3'
  180. TTS.getSrt(video_file)
  181. # result = subprocess.run(
  182. # ["ffprobe", "-v", "error", "-show_entries", "format=duration",
  183. # "-of", "default=noprint_wrappers=1:nokey=1", video_file],
  184. # capture_output=True, text=True)
  185. # print(float(result.stdout))