fish_reference_audio_sync.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import logging
  2. from io import BytesIO
  3. import pandas as pd
  4. import requests
  5. logger = logging.getLogger(__name__)
  6. from typing import Dict, Any
  7. def build_common_header_map():
  8. return {
  9. "Authorization": "Bearer 0891f3f93a2640428f9988e267aa57e1",
  10. "Content-Type": "application/json"
  11. }
  12. def get_model_info(reference_id: str) -> Dict[str, Any]:
  13. api_url = f"https://api.fish.audio/model/{reference_id}"
  14. headers = build_common_header_map()
  15. response = requests.get(
  16. api_url,
  17. headers=headers,
  18. timeout=(10, 1800) # connect timeout, read timeout
  19. )
  20. return response.json()
  21. def add_reference(
  22. base_url: str,
  23. reference_id: str,
  24. audio_url: str,
  25. text: str,
  26. timeout: int = 30,
  27. download_timeout: int = 60,
  28. ) -> Dict[str, Any]:
  29. """
  30. 从 URL 下载音频并调用添加参考音频的接口
  31. Args:
  32. base_url: 服务端基础地址,例如 "http://localhost:8000"
  33. reference_id: 参考音频唯一标识
  34. audio_url: 音频文件的 URL(支持 http/https)
  35. text: 音频对应的文本内容
  36. timeout: 上传请求的超时时间(秒)
  37. download_timeout: 下载音频文件的超时时间(秒)
  38. Returns:
  39. 服务端返回的 JSON 响应(字典)
  40. Raises:
  41. requests.RequestException: 下载或上传请求失败
  42. ValueError: 服务端返回错误响应或下载内容为空
  43. """
  44. # 1. 从 URL 下载音频内容
  45. try:
  46. resp = requests.get(audio_url, timeout=download_timeout)
  47. resp.raise_for_status() # 检查 HTTP 错误
  48. audio_content = resp.content
  49. if not audio_content:
  50. raise ValueError("从 URL 下载的音频文件为空")
  51. except requests.exceptions.RequestException as e:
  52. raise requests.RequestException(f"下载音频失败: {e}") from e
  53. # 2. 构造请求 URL
  54. url = f"{base_url.rstrip('/')}/v1/references/add"
  55. # 3. 准备表单数据和文件(从内存中的字节构造文件)
  56. data = {
  57. "id": reference_id,
  58. "text": text,
  59. }
  60. # 从 URL 中提取文件名(如果 URL 没有明确文件名,可以自定义)
  61. file_name = audio_url.split('/')[-1] or "audio.wav"
  62. # 使用 BytesIO 包装音频内容
  63. files = {
  64. "audio": (file_name, BytesIO(audio_content), "audio/wav"),
  65. }
  66. headers = {
  67. "Accept": "application/json",
  68. }
  69. # 4. 发送上传请求
  70. try:
  71. response = requests.post(url, data=data, files=files, headers=headers, timeout=timeout)
  72. resp_json = response.json()
  73. except requests.exceptions.RequestException as e:
  74. raise requests.RequestException(f"上传请求失败: {e}") from e
  75. finally:
  76. # 关闭 BytesIO(可选,因为内存对象会自动回收)
  77. files["audio"][1].close()
  78. # 5. 检查响应
  79. if response.status_code != 200:
  80. raise ValueError(f"服务端返回错误 (HTTP {response.status_code}): {resp_json.get('message', '未知错误')}")
  81. if not resp_json.get("success", False):
  82. raise ValueError(f"业务失败: {resp_json.get('message', '未知错误')}")
  83. return resp_json
  84. def _main():
  85. df = pd.read_csv("/Users/zhao/Desktop/aigc_admin_prod_ai_model_tts.csv")
  86. base_url = "http://192.168.245.146:8080/"
  87. for row in df.itertuples():
  88. reference_id = row.speaker_id
  89. audio_url = row.audio_url
  90. if reference_id in ['6e2d9e58b26c424db6d564ea56983f4d']:
  91. continue
  92. model_info = get_model_info(reference_id)
  93. text = model_info['samples'][0]['text']
  94. add_reference(
  95. base_url=base_url,
  96. reference_id=reference_id,
  97. audio_url=audio_url,
  98. text=text,
  99. timeout=30,
  100. )
  101. if __name__ == '__main__':
  102. _main()