Skill: skydream9527-ctrl/minimax-tts-gyh (version 1.0.0)

--- name: minimax-tts-gyh description: MiniMax TTS 文字转语音模型，支持 speech-02/speech-01 系列，生成高质量语音。使用 MINIMAX_API_KEY 环境变量。 metadata: {"openclaw":{"emoji":"🎙️","requires":{"bins":["python3"]}}} --- # MiniMax TTS 文字转语音 使用 MiniMax TTS API 将文本转换为语音。 ## 支持的模型 | 模型 | 说明 | |------|------| | `speech-02-hd` | 高清语音，情感丰富 | | `speech-02-turbo` | 高速语音 | | `speech-01-hd` | 标准高清 | | `speech-01-turbo` | 标准高速 | ## 前置要求 - Python 3 - `pip3 install requests` - 设置环境变量 `MINIMAX_API_KEY` ## 使用方法 ```bash # 基本语音生成 python3 {baseDir}/scripts/tts.py --text "你好，欢迎使用MiniMax语音合成" --output hello.mp3 # 指定模型和声音 python3 {baseDir}/scripts/tts.py \ --model speech-02-hd \ --text "今天天气真不错" \ --voice_id female_healthy \ --output weather.mp3 # 英文语音 python3 {baseDir}/scripts/tts.py \ --model speech-02-hd \ --text "Hello, this is a test of MiniMax text to speech" \ --voice_id male_tianmei \ --output hello.mp3 ``` ## 参数说明 | 参数 | 说明 | 默认值 | |------|------|--------| | `--model` | 模型名称 | `speech-02-hd` | | `--text` | 要转换的文本 | - | | `--voice_id` | 声音 ID | `female_tianmei` | | `--speed` | 语速 (0.5-2.0) | 1.0 | | `--pitch` | 音调调整 | 0 | | `--volume` | 音量 (0.5-2.0) | 1.0 | | `--emotion` | 情感风格 | `neutral` | | `--language` | 语言 | `auto` | | `--output` | 输出文件路径 | `output.mp3` |

path: _meta.json
content: ownerId: gyh
slug: minimax-tts-gyh
version: 1.0.0
publishedAt: 1744394400000
name: minimax-tts
description: MiniMax TTS 文字转语音技能，支持 speech-02/speech-01 系列。

path: scripts/tts.py
content: #!/usr/bin/env python3
"""
MiniMax TTS 文字转语音脚本
"""

import os
import sys
import time
import argparse
import requests

[REDACTED_SECRET]"MINIMAX_API_KEY")
if not [REDACTED_SECRET]"Error: MINIMAX_API_KEY environment variable not set")
    print("Please set it with: export MINIMAX_API_KEY=\"your-api-key\"")
    sys.exit(1)

HEADERS = {"Authorization": f"Bearer {API_KEY}"}
API_HOST = "https://api.minimaxi.com"


def tts_speech(model: str, text: str, voice_id: str = "female_tianmei",
               speed: float = 1.0, pitch: float = 0, volume: float = 1.0,
               emotion: str = "neutral", language: str = "auto",
               output_path: str = "output.mp3") -> str:
    """
    调用 MiniMax TTS API 生成语音
    返回本地文件路径
    """
    url = f"{API_HOST}/v1/t2a_v2"

    payload = {
        "model": model,
        "text": text,
        "voice_setting": {
            "voice_id": voice_id,
            "speed": speed,
            "pitch": pitch,
            "vol": volume,
            "emotion": emotion,
        },
        "audio_setting": {
            "sample_rate": 32000,
            "bitrate": 128000,
            "format": "mp3",
            "channel": 1,
        },
        "language": language,
    }

    print(f"🎙️ 正在生成语音...")
    print(f"   模型: {model} | 声音: {voice_id} | 语速: {speed}x")
    print(f"   文本: {text[:50]}{'...' if len(text) > 50 else ''}")

    resp = requests.post(url, headers=HEADERS, json=payload, timeout=60)
    resp.raise_for_status()
    data = resp.json()

    base_resp = data.get("base_resp", {})
    if base_resp.get("status_code") != 0:
        # 可能是异步任务
        task_id = data.get("task_id")
        if task_id:
            print(f"⏳ 异步任务 ID: {task_id}，开始轮询...")
            file_id = poll_tts_task(task_id)
            if file_id:
                download_file(file_id, output_path)
                return output_path
        raise Exception(f"API Error: {base_resp.get('status_msg', 'unknown')}")

    # 同步返回，直接是音频数据
    audio_data = data.get("data")
    if audio_data:
        with open(output_path, "wb") as f:
            f.write(audio_data.encode('latin1'))
        print(f"✅ 语音已保存: {output_path}")
        return output_path

    raise Exception("未获取到音频数据")


def poll_tts_task(task_id: str, max_wait: int = 300) -> str:
    """轮询 TTS 任务状态"""
    url = f"{API_HOST}/v1/query/t2a_async_query_v2"
    params = {"task_id": task_id}

    for i in range(max_wait // 10):
        time.sleep(10)
        resp = requests.get(url, headers=HEADERS, params=params, timeout=30)
        resp.raise_for_status()
        data = resp.json()

        status = data.get("status", "")
        print(f"  状态: {status}")
        if status == "Success":
            return data.get("file_id", "")
        elif status == "Fail":
            raise Exception(f"TTS 任务失败: {data.get('error_message', 'unknown')}")
    raise Exception("TTS 任务超时")


def download_file(file_id: str, output_path: str):
    """下载音频文件"""
    url = f"{API_HOST}/v1/files/retrieve"
    params = {"file_id": file_id}
    resp = requests.get(url, headers=HEADERS, params=params, timeout=30)
    resp.raise_for_status()
    download_url = resp.json()["file"]["download_url"]

    with open(output_path, "wb") as f:
        vr = requests.get(download_url, timeout=60)
        vr.raise_for_status()
        f.write(vr.content)
    print(f"✅ 文件已下载: {output_path}")


def list_voices(model: str = "speech-02-hd"):
    """列出可用声音"""
    url = f"{API_HOST}/v1/voices"
    params = {"model": model}
    resp = requests.get(url, headers=HEADERS, params=params, timeout=10)
    print(resp.text)


def main():
    parser = argparse.ArgumentParser(description="MiniMax TTS 文字转语音")
    parser.add_argument("--model", default="speech-02-hd",
                        help="模型: speech-02-hd, speech-02-turbo, speech-01-hd, speech-01-turbo")
    parser.add_argument("--text", required=True, help="要转换的文本")
    parser.add_argument("--voice_id", default="female_tianmei",
                        help="声音 ID: female_tianmei, male_tianmei, female_healthy, male_healthy 等")
    parser.add_argument("--speed", type=float, default=1.0, help="语速 (0.5-2.0)")
    parser.add_argument("--pitch", type=float, default=0, help="音调调整")
    parser.add_argument("--volume", type=float, default=1.0, help="音量 (0.5-2.0)")
    parser.add_argument("--emotion", default="neutral",
                        help="情感: neutral, happy, sad, angry, fearful, disgusted")
    parser.add_argument("--language", default="auto", help="语言: auto, zh, en, ja, ko 等")
    parser.add_argument("--output", default="output.mp3", help="输出文件路径")

    args = parser.parse_args()

    try:
        result = tts_speech(
            model=args.model,
            text=args.text,
            voice_id=args.voice_id,
            speed=args.speed,
            pitch=args.pitch,
            volume=args.volume,
            emotion=args.emotion,
            language=args.language,
            output_path=args.output,
        )
        print(f"\n📎 输出文件: {result}")
    except Exception as e:
        print(f"❌ 错误: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector:  ()