返回 ppt-master
backend_minimax.py
根目录 / skills / ppt-master / scripts / tts_backends / backend_minimax.py
1 """MiniMax T2A backend for narration audio generation."""
2
3 from __future__ import annotations
4
5 import binascii
6 import os
7 from pathlib import Path
8
9 from tts_backends.backend_common import (
10 extension_from_format,
11 post_json,
12 publish_audio_bytes,
13 read_api_key,
14 )
15
16
17 DEFAULT_ENDPOINT = "https://api.minimaxi.com/v1/t2a_v2"
18 DEFAULT_MODEL = "speech-2.8-hd"
19
20 # International fallback: set MINIMAX_TTS_BASE_URL=https://api.minimax.io if needed.
21
22
23 def output_extension(audio_format: str) -> str:
24 return extension_from_format(audio_format)
25
26
27 def read_minimax_api_key(env_name: str) -> str:
28 return read_api_key(env_name, label="MiniMax")
29
30
31 def resolve_url(base_url: str | None = None) -> str:
32 base = (base_url or os.environ.get("MINIMAX_TTS_BASE_URL") or DEFAULT_ENDPOINT).rstrip("/")
33 if base.endswith("/t2a_v2"):
34 return base
35 if base.endswith("/v1"):
36 return base + "/t2a_v2"
37 return base + "/v1/t2a_v2"
38
39
40 def generate(
41 text: str,
42 output_path: Path,
43 *,
44 api_key: str,
45 voice_id: str,
46 model: str,
47 audio_format: str,
48 sample_rate: int,
49 bitrate: int,
50 channel: int,
51 speed: float,
52 volume: float,
53 pitch: int,
54 language_boost: str,
55 base_url: str | None,
56 ) -> None:
57 payload = {
58 "model": model,
59 "text": text,
60 "stream": False,
61 "language_boost": language_boost,
62 "output_format": "hex",
63 "voice_setting": {
64 "voice_id": voice_id,
65 "speed": speed,
66 "vol": volume,
67 "pitch": pitch,
68 },
69 "audio_setting": {
70 "sample_rate": sample_rate,
71 "bitrate": bitrate,
72 "format": audio_format,
73 "channel": channel,
74 },
75 }
76 data = post_json(
77 resolve_url(base_url),
78 headers={"Authorization": f"Bearer {api_key}"},
79 payload=payload,
80 timeout=180,
81 )
82 base_resp = data.get("base_resp") or {}
83 if base_resp.get("status_code") not in (None, 0, "0"):
84 raise RuntimeError(f"MiniMax TTS failed: {data}")
85
86 audio_hex = (data.get("data") or {}).get("audio")
87 if not audio_hex:
88 raise RuntimeError(f"MiniMax response missing audio data: {data}")
89 try:
90 audio = binascii.unhexlify(audio_hex)
91 except (binascii.Error, ValueError) as exc:
92 raise RuntimeError("MiniMax response audio is not valid hex data") from exc
93 publish_audio_bytes(audio, output_path)
94
95
96 def print_voices() -> None:
97 print("MiniMax TTS voices are selected by voice_id.")
98 print("Use a system voice ID or a cloned voice_id from MiniMax Voice Clone.")
99 print("Example domestic system voice from MiniMax docs: male-qn-qingse")
100
100 lines PYTHON