Skill: lilei0311/siliconflow-tts-gen (version 1.0.0)

--- name: siliconflow-tts-gen description: Text-to-Speech using SiliconFlow API (CosyVoice2). Supports multiple voices, languages, and dialects. env: - SILICONFLOW_API_KEY files: config: - ~/.openclaw/openclaw.json --- # SiliconFlow TTS Generation Skill Text-to-Speech using SiliconFlow API with CosyVoice2 model. Supports 8 preset voices, multiple languages, and Chinese dialects. ## Features - 🎙️ **8 Preset Voices**: 4 male + 4 female voices - 🌍 **Multilingual**: Chinese, English, Japanese, Korean - 🗣️ **Chinese Dialects**: Cantonese, Sichuan, Shanghai, Tianjin, Wuhan - ⚡ **Ultra Low Latency**: 150ms first packet delay - 🎵 **Voice Cloning**: 3-second rapid voice cloning - 💾 **Auto Download**: Saves audio files locally ## Requirements - **Environment Variable**: `SILICONFLOW_API_KEY` - **Optional Config File**: `~/.openclaw/openclaw.json` (for auto-detect) ## Installation ```bash npx clawhub install siliconflow-tts-gen ``` ## Configuration Set your SiliconFlow API key: ```bash export SILICONFLOW_API_KEY="your-api-key" ``` ## Usage ### List Available Voices ```bash python3 scripts/generate.py --list-voices ``` ### Generate Speech ```bash # Basic usage (default voice: alex) python3 scripts/generate.py "你好，世界" # Specify voice python3 scripts/generate.py "Hello World" --voice bella # Adjust speed python3 scripts/generate.py "你好" --voice claire --speed 0.9 # Save to file python3 scripts/generate.py "欢迎收听" --output welcome.mp3 # Change format python3 scripts/generate.py "Hello" --format wav ``` ## Available Voices ### Male Voices | ID | Name | Characteristic | |----|------|----------------| | alex | 沉稳男声 | Mature and steady | | benjamin | 低沉男声 | Deep and low | | charles | 磁性男声 | Magnetic | | david | 欢快男声 | Cheerful | ### Female Voices | ID | Name | Characteristic | |----|------|----------------| | anna | 沉稳女声 | Mature and elegant | | bella | 激情女声 | Passionate | | claire | 温柔女声 | Gentle and kind | | diana | 欢快女声 | Sweet and happy | ## Parameters | Parameter | Type | Default | Range | Description | |-----------|------|---------|-------|-------------| | `--voice` | string | alex | - | Voice ID | | `--speed` | float | 1.0 | 0.25-4.0 | Speech speed | | `--format` | string | mp3 | mp3/opus/wav/pcm | Output format | | `--output` | string | output.mp3 | - | Output file path | ## Security Notes - This skill requires an API key to call SiliconFlow services - The script reads `~/.openclaw/openclaw.json` only to auto-detect API keys - No sensitive data is transmitted except to `api.siliconflow.cn` - Review the code at `scripts/generate.py` before providing credentials ## Author MaxStorm Team ## License MIT

path: README.md
content: # SiliconFlow TTS Generation Skill

Text-to-Speech using SiliconFlow API with CosyVoice2 model.

## Features

- 🎙️ **8 Preset Voices**: 4 male + 4 female voices
- 🌍 **Multilingual**: Chinese, English, Japanese, Korean
- 🗣️ **Chinese Dialects**: Cantonese, Sichuan, Shanghai, Tianjin, Wuhan
- ⚡ **Ultra Low Latency**: 150ms first packet delay
- 🎵 **Voice Cloning**: 3-second rapid voice cloning

## Quick Start

```bash
# Install
npx clawhub install siliconflow-tts-gen

# Set API key
export SILICONFLOW_API_KEY="your-api-key"

# Generate speech
python3 scripts/generate.py "你好，世界"
```

## Available Voices

| Gender | ID | Name |
|--------|-----|------|
| Male | alex | 沉稳男声 |
| Male | benjamin | 低沉男声 |
| Male | charles | 磁性男声 |
| Male | david | 欢快男声 |
| Female | anna | 沉稳女声 |
| Female | bella | 激情女声 |
| Female | claire | 温柔女声 |
| Female | diana | 欢快女声 |

## Usage Examples

```bash
# List voices
python3 scripts/generate.py --list-voices

# Basic usage
python3 scripts/generate.py "Hello World"

# With voice selection
python3 scripts/generate.py "欢迎收听" --voice claire

# Adjust speed
python3 scripts/generate.py "你好" --speed 0.9

# Save to specific file
python3 scripts/generate.py "Hello" --output greeting.mp3
```

## Author

MaxStorm Team

## License

MIT


path: skill.json
content: {
  "name": "siliconflow-tts-gen",
  "version": "1.0.0",
  "description": "Text-to-Speech using SiliconFlow API (CosyVoice2). Supports multiple voices, languages, and dialects.",
  "author": "MaxStorm Team",
  "license": "MIT",
  "homepage": "https://github.com/maxstorm/siliconflow-tts-gen",
  "keywords": ["tts", "text-to-speech", "siliconflow", "cosyvoice", "voice", "audio"],
  "trigger": {
    "patterns": [
      "文字转语音",
      "语音合成",
      "生成语音",
      "text to speech",
      "tts",
      "语音朗读"
    ]
  },
  "tools": ["exec"],
  "env": {
    "SILICONFLOW_API_KEY": {
      "description": "SiliconFlow API Key for TTS",
      "required": true
    }
  },
  "config": {
    "apiKey": {
      "description": "SiliconFlow API Key",
      "required": true,
      "env": "SILICONFLOW_API_KEY"
    },
    "defaultModel": {
      "description": "Default TTS model",
      "default": "FunAudioLLM/CosyVoice2-0.5B"
    },
    "defaultVoice": {
      "description": "Default voice",
      "default": "alex"
    }
  },
  "files": {
    "config": ["~/.openclaw/openclaw.json"]
  },
  "models": [
    {
      "id": "FunAudioLLM/CosyVoice2-0.5B",
      "name": "CosyVoice 2",
      "description": "Ultra-low latency (150ms), multilingual, dialect support"
    }
  ]
}


path: scripts/generate.py
content: #!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SiliconFlow TTS Generation Script
Compatible with OpenClaw Agent Skills
"""

import os
import sys
import json
import argparse
import subprocess

# API Configuration
API_BASE_URL = "https://api.siliconflow.cn/v1"
DEFAULT_MODEL = "FunAudioLLM/CosyVoice2-0.5B"
DEFAULT_VOICE = "alex"

# Available voices
VOICES = {
    "alex": "沉稳男声",
    "benjamin": "低沉男声",
    "charles": "磁性男声",
    "david": "欢快男声",
    "anna": "沉稳女声",
    "bella": "激情女声",
    "claire": "温柔女声",
    "diana": "欢快女声"
}

def get_api_key():
    """Get API key from environment or OpenClaw config"""
    [REDACTED_SECRET]"SILICONFLOW_API_KEY")
    if [REDACTED_SECRET] api_key
    
    try:
        config_path = os.path.expanduser("~/.openclaw/openclaw.json")
        with open(config_path, 'r', encoding='utf-8') as f:
            config = json.load(f)
        providers = config.get("models", {}).get("providers", {})
        siliconflow = providers.get("siliconflow", {})
        [REDACTED_SECRET]"apiKey")
        if api_key and api_key != "ollama":
            return api_key
    except Exception:
        pass
    
    return None

def generate_speech(text, voice=None, model=None, output_path=None, speed=1.0, response_format="mp3"):
    """Generate speech using SiliconFlow TTS API"""
    [REDACTED_SECRET])
    if not [REDACTED_SECRET]
            "success": False,
            "error": "SILICONFLOW_API_KEY not found. Please set SILICONFLOW_API_KEY environment variable."
        }))
        sys.exit(1)
    
    model = model or DEFAULT_MODEL
    voice = voice or DEFAULT_VOICE
    
    # Prepare request data
    # voice format: "FunAudioLLM/CosyVoice2-0.5B:alex" for system voices
    full_voice = f"{model}:{voice}"
    
    data = {
        "model": model,
        "voice": full_voice,
        "input": text,
        "speed": speed,
        "response_format": response_format
    }
    
    # Determine output file
    if not output_path:
        output_path = f"output.{response_format}"
    
    headers = [
        f"Authorization: Bearer {api_key}",
        "Content-Type: application/json"
    ]
    
    try:
        # Use curl to make request and save directly to file
        curl_cmd = [
            "curl", "-s", "-X", "POST",
            f"{API_BASE_URL}/audio/speech",
            "-H", f"Authorization: Bearer {api_key}",
            "-H", "Content-Type: application/json",
            "-d", json.dumps(data),
            "--max-time", "60",
            "-o", output_path
        ]
        
        result = subprocess.run(curl_cmd, capture_output=True)
        
        if result.returncode != 0:
            print(json.dumps({
                "success": False,
                "error": f"API request failed: {result.stderr.decode('utf-8', errors='ignore')}"
            }))
            sys.exit(1)
        
        # Check if file was created and has content
        if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
            file_size = os.path.getsize(output_path)
            print(json.dumps({
                "success": True,
                "text": text,
                "model": model,
                "voice": voice,
                "voice_name": VOICES.get(voice, voice),
                "speed": speed,
                "format": response_format,
                "output_path": output_path,
                "file_size_bytes": file_size
            }, indent=2, ensure_ascii=False))
        else:
            print(json.dumps({
                "success": False,
                "error": "Output file is empty or not created"
            }))
            sys.exit(1)
        
    except Exception as e:
        print(json.dumps({
            "success": False,
            "error": str(e)
        }))
        sys.exit(1)

def list_voices():
    """List available voices"""
    print(json.dumps({
        "voices": [
            {"id": k, "name": v, "gender": "男" if k in ["alex", "benjamin", "charles", "david"] else "女"}
            for k, v in VOICES.items()
        ]
    }, indent=2, ensure_ascii=False))

def main():
    parser = argparse.ArgumentParser(
        description="Generate speech using SiliconFlow TTS API (CosyVoice2)",
        epilog="Examples:\n"
               "  %(prog)s \"你好，世界\"\n"
               "  %(prog)s \"Hello World\" --voice bella\n"
               "  %(prog)s \"你好\" --voice claire --speed 0.9 --output hello.mp3\n"
               "  %(prog)s --list-voices",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument("text", nargs="?", help="Text to convert to speech")
    parser.add_argument("--voice", "-v", help="Voice to use (default: alex)", default=DEFAULT_VOICE)
    parser.add_argument("--model", "-m", help="Model to use", default=DEFAULT_MODEL)
    parser.add_argument("--output", "-o", help="Output file path")
    parser.add_argument("--speed", "-s", help="Speech speed (0.25-4.0)", type=float, default=1.0)
    parser.add_argument("--format", "-f", help="Output format (mp3, opus, wav, pcm)", default="mp3")
    parser.add_argument("--list-voices", "-l", action="store_true", help="List available voices")
    
    args = parser.parse_args()
    
    if args.list_voices:
        list_voices()
    elif args.text:
        generate_speech(args.text, args.voice, args.model, args.output, args.speed, args.format)
    else:
        parser.print_help()
        sys.exit(1)

if __name__ == "__main__":
    main()


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