前言说明

在数字化浪潮席卷全球的时代,语音交互正以前所未有的速度融入我们的生活与工作场景,从智能客服到有声内容创作,从导航语音播报再到教育场景的语言学习,优质、高效的语音合成技术成为了推动行业创新发展的关键力量。云音工坊深度洞察市场需求,依托 Fish Speech 先进的语音合成技术,致力于为用户提供专业、精准且极具表现力的语音合成功能。我们凭借强大的技术研发实力,基于 Fish Speech 技术开发了专属 API 接口,不仅能满足用户多样化的语音合成需求,还为开发者提供了便捷接入的渠道,助力各行业轻松实现语音交互升级,解锁智能语音应用的无限可能。

使用说明

语音合成

接口地址

https://www.yuntts.com/api/v1/cloning

请求头

// JSON 格式
Content-Type: application/json
Authorization: Bearer API-KEY  // API密钥

注意:秘钥请登录后前往 https://www.yuntts.com/user/api/ 生成,接口秘钥支持访问本站所有接口服务!

请求参数

{
  "model_id": string,  // 必填,模型ID
  "text": string,         // 必填,要转换的文本
  "speed": number,        // 可选,语速,范围:0.5-2.0,默认:1
  "volume": number,       // 可选,音量,范围:-20-20,默认:0
  "version": string,      // 可选,TTS版本,可选值:"v1"或"v2",默认:"v1"
  "cache": boolean        // 可选,是否缓存音频并返回URL,默认:false
}

示例

{
    "reference_id": "25129630-581c-4cd8-9fa1-12199fcc9f0b",
    "text": "云音工坊测试文本",
    "speed": 1,
    "volume": 0,
    "version": "v1",
    "cache": true
}

请求参数说明

参数名称 是否必填 参数类型 参数说明 默认值 取值范围/可选值
model_id 必填 string 模型ID - -
text 必填 string 要转换的文本 - -
speed 可选 number 语速 1 0.5 - 2.0
volume 可选 number 音量 0 -20 - 20
version 可选 string TTS版本 "v1" "v1" 或 "v2"
cache 可选 boolean 是否缓存音频并返回URL false true 或 false

返回数据

如过开启缓存返回

{
"code": 200,
"msg": "合成成功",
"audio_url": "https://www.yuntts.com/wp-content/uploads/2025/05/682724acaaf55_1747395756.mp3",
"format": "mp3",
"characters_used": 8,
"price": 0.01,
"quota_remaining": 184.7715
}

返回参数说明

参数名称 参数类型 参数说明 示例值
code number 状态码 200
success boolean 请求是否成功 true
audio_url string 生成的音频文件URL https://www.yuntts.com/wp-content/uploads/2025/05/6827182c06ce0_1747392556.mp3
format string 音频格式 mp3
characters_used number 本次请求消耗的字符数 40
price number 本次请求的费用 0.05
quota_remaining number 剩余可用额度 184.7815

如过关闭缓存返回

Content-Type: audio/mpeg
<二进制音频数据>

注意:返回二进制音频数据需要自己在客户端处理!

错误处理

HTTP状态码 触发条件 错误代码 响应示例
400 缺少必要参数或参数格式错误 invalid_parameters { "error": "invalid_parameters", "msg": "缺少必要参数" }
400 音量值超出-20~20范围 invalid_volume { "error": "invalid_volume", "msg": "音量值超出范围" }
401 API密钥无效或过期 invalid_key { "code": 401, "msg": "API密钥无效或已过期" }
403 用户权限不足 forbidden { "code": 403, "msg": "操作未授权" }
429 用户余额不足 insufficient_balance { "code": 429, "error": "insufficient_balance", "msg": "用户余额不足" }
500 服务器配置异常 server_config_error { "code": 500, "error": "server_config_error", "msg": "服务端配置异常" }

模型克隆

接口地址

http://www.yuntts.com/wp-json/api/v1/cloning-model

请求头

Content-Type: multipart/form-data
Authorization: Bearer YOUR_API_TOKEN  // API密钥

注意:秘钥请登录后前往 https://www.yuntts.com/user/api/ 生成,接口秘钥支持访问本站所有接口服务!

请求参数

{
    "name": "解说大神",
    "description": "云音工坊测试",
    "audioFile": "default.mp3"
}

请求参数说明

字段名 类型 必填性 说明
name string 必填 模型名称
description string 可选 模型描述(非必填,可留空或填写简要说明)
audioFiles File 必填 音频文件,支持格式:wav/mp3(需上传文件,文件名为具体路径或文件名)

返回参数

{
    "code": 200,
    "msg": "模型创建成功",
    "modelId": "7ef46f62-fe18-4c47-9948-d8861134e649",
    "title": "解说大神",
    "createdAt": "2025-05-17 04:43:50",
    "quota_remaining": 184.6015
}

参考代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>语音模型创建</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .file-upload {
            border: 2px dashed #dee2e6;
            border-radius: 0.375rem;
            padding: 2rem;
            text-align: center;
        }
        .progress {
            height: 1.5rem;
            margin-top: 1rem;
        }
    </style>
</head>
<body>
<div class="container py-5">
    <div class="row justify-content-center">
        <div class="col-md-8 col-lg-6">
            <h2 class="mb-4">创建语音克隆模型</h2>
            
            <!-- 错误提示 -->
            <div class="alert alert-danger d-none" id="errorAlert"></div>
            
            <form id="modelForm">
                <!-- 模型名称 -->
                <div class="mb-3">
                    <label class="form-label">模型名称 *</label>
                    <input type="text" class="form-control" name="name" required>
                </div>

                <!-- 模型描述 -->
                <div class="mb-3">
                    <label class="form-label">模型描述</label>
                    <textarea class="form-control" name="description" rows="3"></textarea>
                </div>

                <!-- 文件上传 -->
                <div class="mb-3">
                    <label class="form-label">音频文件 *</label>
                    <div class="file-upload">
                        <input type="file" class="form-control" name="audioFiles" accept=".wav,.mp3" required>
                        <small class="text-muted d-block mt-2">支持格式:WAV/MP3,最大4MB</small>
                        <div class="invalid-feedback" id="fileError"></div>
                    </div>
                </div>

                <button type="submit" class="btn btn-primary w-100">
                    <span class="spinner-border spinner-border-sm d-none" role="status"></span>
                    提交创建
                </button>
            </form>

            <!-- 结果展示 -->
            <div class="mt-4 card d-none" id="resultCard">
                <div class="card-body">
                    <h5 class="card-title">创建成功</h5>
                    <ul class="list-unstyled">
                        <li>模型ID: <span id="modelId"></span></li>
                        <li>创建时间: <span id="createdAt"></span></li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>

<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
<script>
document.getElementById('modelForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    
    const form = e.target;
    const submitBtn = form.querySelector('button[type="submit"]');
    const spinner = submitBtn.querySelector('.spinner-border');
    const fileInput = form.querySelector('input[type="file"]');
    
    // 重置状态
    document.getElementById('errorAlert').classList.add('d-none');
    spinner.classList.remove('d-none');
    submitBtn.disabled = true;

    try {
        // 前端验证
        if (!fileInput.files[0]) {
            throw new Error('请选择音频文件');
        }

        const file = fileInput.files[0];
        if (!['audio/wav', 'audio/mpeg', 'audio/mp3'].includes(file.type)) {
            throw new Error('仅支持WAV/MP3格式');
        }

        if (file.size > 4 * 1024 * 1024) {
            throw new Error('文件大小超过4MB限制');
        }

        // 构建FormData
        const formData = new FormData();
        formData.append('name', form.name.value);
        formData.append('description', form.description.value);
        formData.append('audioFiles', file);

        // 添加请求参数日志
        console.log('提交表单参数:', {
            name: form.name.value,
            description: form.description.value,
            audioFile: file.name
        });

        // 发送请求
        const response = await fetch('/wp-json/api/v1/cloning-model', {
            method: 'POST',
            headers: {
                'Authorization': `Bearer 68985a242e655fb2d0194dfb478f1f76`,
                // 移除手动设置的Content-Type头,浏览器会自动生成正确的boundary
            },
            body: formData
        });

        const result = await response.json();

        if (!response.ok) {
            throw new Error(result.msg || '请求失败');
        }

        // 显示结果
        document.getElementById('resultCard').classList.remove('d-none');
        document.getElementById('modelId').textContent = result.modelId;
        document.getElementById('createdAt').textContent = result.createdAt;
        form.reset();
    } catch (error) {
        const errorAlert = document.getElementById('errorAlert');
        errorAlert.textContent = error.message;
        errorAlert.classList.remove('d-none');
    } finally {
        spinner.classList.add('d-none');
        submitBtn.disabled = false;
    }
});

</script>
</body>
</html>
curl -X POST "http://yourdomain.com/wp-json/api/v1/cloning-model" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "name=示例模型" \
  -F "description=模型描述信息" \
  -F "audioFiles=@/path/to/audio.wav"
import requests

url = "http://yourdomain.com/wp-json/api/v1/cloning-model"
headers = {
    "Authorization": "Bearer YOUR_API_KEY"
}
files = {
    "audioFiles": open("/path/to/audio.wav", "rb")
}
data = {
    "name": "示例模型",
    "description": "模型描述信息"
}

response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())

获取模型

接口地址

https://www.yuntts.com/api/v1/fetch-model

请求头

Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN  // API密钥

请求参数

 {
  "page": 1,//页面
  "page_size": 20,//每页条数
  "includePersonal": false//是否包含个人模型
}

返回参数

{
    "total": 65,
    "page": 1,
    "pageSize": 70,
    "totalPages": 1,
    "data": [
        {
            "modelId": "fb215435-9cf1-4141-a938-d05e85c064ee",
            "modelName": "奶龙",
            "description": "小朋友们,准备好迎接奶龙的魔法了吗?",
            "gender": "male",
            "scene_type": "general",
            "demoAudioUrl": "https://www.yuntts.com/audio/nailong.mp3",
            "avatarUrl": "/wp-content/themes/360mb-v5/assets/tts/avatar/nailong.webp",
            "createdAt": "2024-10-09 02:44:08",
            "updatedAt": "2025-05-09 22:25:53",
            "isPersonal": false
        },
        {
            "modelId": "ff66d8d5-818f-43a8-9b6b-7936b6e75900",
            "modelName": "女主播大白兔",
            "description": "大家好,我是大白兔,欢迎进入我的直播间!",
            "gender": "male",
            "scene_type": "general",
            "demoAudioUrl": "https://www.yuntts.com/audio/nvzhubodabaitu.mp3",
            "avatarUrl": "/wp-content/themes/360mb-v5/assets/tts/avatar/dabaitu.webp",
            "createdAt": "2025-01-16 12:28:39",
            "updatedAt": "2025-05-09 22:24:57",
            "isPersonal": true
        }
    ]
}

返回参数说明

克隆语音模型接口响应参数说明
字段名 类型 描述 示例值
total int 总记录数 65
page int 当前页码 1
pageSize int 每页记录数 70
totalPages int 总页数 1
data[].modelId string 模型唯一标识(UUID格式) fb215435-9cf1-4141-a938-d05e85c064ee
data[].modelName string 模型显示名称 奶龙
data[].description string 模型描述文本 小朋友们,准备好迎接奶龙的魔法了吗?
data[].gender string 语音性别类型(male/female) male
data[].demoAudioUrl string 演示音频URL地址 mp3地址
data[].avatarUrl string 模型头像路径(相对/绝对) 头像地址
data[].isPersonal bool 是否个人模型 false

参考代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>模型查询接口调试</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4">
    <h3 class="mb-4">克隆模型查询接口调试</h3>
    
    <form id="queryForm" class="mb-4">
        <div class="row g-3">
            <div class="col-md-3">
                <label class="form-label">页码</label>
                <input type="number" class="form-control" id="page" name="page" min="1" value="1" required>
                <div class="invalid-feedback">页码必须≥1</div>
            </div>
            
            <div class="col-md-3">
                <label class="form-label">每页条数</label>
                <input type="number" class="form-control" id="page_size" name="page_size" min="1" max="100" value="20" required>
                <div class="invalid-feedback">1-100之间</div>
            </div>
            
            <div class="col-md-6">
                <div class="form-check form-switch mt-4 pt-2">
                    <input class="form-check-input" type="checkbox" role="switch" id="includePersonal">
                    <label class="form-check-label" for="includePersonal">包含个人模型</label>
                </div>
            </div>
        </div>
        
        <button type="submit" class="btn btn-primary mt-3">查询</button>
    </form>

    <div class="card">
        <div class="card-header">响应结果</div>
        <div class="card-body p-0">
            <textarea id="responseArea" class="form-control" style="height:400px; font-family: monospace" readonly></textarea>
        </div>
    </div>
</div>

<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
<script>
document.getElementById('queryForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    
    const formData = {
        page: parseInt(document.getElementById('page').value),
        page_size: parseInt(document.getElementById('page_size').value),
        includePersonal: document.getElementById('includePersonal').checked
    };
    console.log('请求参数:', JSON.stringify(formData, null, 2));

    try {
        const response = await fetch('https://www.yuntts.com/api/v1/fetch-model', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer 68985a242e655fb2d0194dfb478f1f76`,
            },
            body: JSON.stringify(formData)
        });

        const result = await response.json();
        document.getElementById('responseArea').value = JSON.stringify(result, null, 4);
        
        if (!response.ok) {
            alert(`请求失败: ${result.error || result.msg}`);
        }
    } catch (error) {
        console.error('请求失败:', error);
        document.getElementById('responseArea').value = `网络错误: ${error.message}`;
    }
});
</script>
</body>
</html>
curl -X POST "https://www.yuntts.com/api/v1/fetch-model" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key_here" \
-d '{
    "page": 2,
    "pageSize": 30,
    "includePersonal": true
}'

 

删除模型

接口地址

http://www.yuntts.com/wp-json/api/v1/cloning-delete

请求头

Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN  // API密钥

请求参数

{
  "modelId": string  // 必填,要删除的模型ID
}

返回数据

{
    "code": 200,
    "msg": "模型删除成功",
    "modelId": "7ef46f62-fe18-4c47-9948-d8861134e649",
    "quota_remaining": 184.6015
}

参考代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>删除语音模型</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body class="bg-light">
    <div class="container py-5">
        <div class="card shadow-sm">
            <div class="card-header bg-danger text-white">
                <h3 class="mb-0">删除语音模型</h3>
            </div>
            <div class="card-body">
                <form id="deleteForm">
                    <div class="mb-3">
                        <label for="modelId" class="form-label">模型ID</label>
                        <input type="text" class="form-control" id="modelId" required>
                        <div class="form-text text-muted">请输入要删除的模型ID</div>
                    </div>
                    <button type="submit" class="btn btn-danger">删除模型</button>
                </form>
                
                <div id="resultAlert" class="mt-4 d-none">
                    <div class="alert alert-dismissible fade show">
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                        <span class="alert-message"></span>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
    $(document).ready(function() {
        $('#deleteForm').submit(function(e) {
            e.preventDefault();
            
            const modelId = $('#modelId').val().trim();
            if (!modelId) {
                showAlert('请输入有效的模型ID', 'danger');
                return;
            }

            $.ajax({
                url: '/wp-json/api/v1/cloning-delete',
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer 68985a242e655fb2d0194dfb478f1f76`,
                },
                data: JSON.stringify({ modelId: modelId }),
                success: function(response) {
                    if (response.code === 200) {
                        showAlert(`${response.message} 剩余额度:${response.quota_remaining}`, 'success');
                    } else {
                        showAlert(response.msg || '操作失败', 'warning');
                    }
                },
                error: function(xhr) {
                    const error = xhr.responseJSON || {};
                    showAlert(error.msg || '服务器错误,请稍后再试', 'danger');
                }
            });
        });

        function showAlert(message, type) {
            const $alert = $('#resultAlert').removeClass('d-none').find('.alert');
            $alert.removeClass('alert-success alert-danger alert-warning')
                 .addClass(`alert-${type}`)
                 .find('.alert-message').text(message);
        }
    });
    </script>
</body>
</html>
curl -X POST https://fishspeech.net/api/open/delete-model \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
    "modelId": "your_model_id"
  }

 

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。