# doubaotts2 **Repository Path**: doc5/doubaotts2 ## Basic Information - **Project Name**: doubaotts2 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-25 - **Last Updated**: 2026-05-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # DoubaoTTS2 — 火山引擎豆包语音合成 PHP SDK 火山引擎豆包语音合成 & 声音复刻 PHP SDK,支持语音合成大模型 2.0、双向流式、声音复刻 V3、音色槽管理。 ## 功能概览 | 模块 | 客户端 | 协议 | 说明 | | :--- | :--- | :--- | :--- | | 语音合成 | `TTSClient` | WebSocket | 单向流式,一键合成 / 流式收发 | | 双向流式 | `TTSBidirectionalClient` | WebSocket | 双向流式,完整 session 生命周期 | | 声音复刻 | `VoiceCloneClient` | HTTP REST | 上传音频 → 训练音色 → 查询状态 | | 音色管理 | `SpeakerManager` | HTTP (AKSK) | 购买 / 续费 / 查询音色槽 | | 连接池 | `ConnectionPool` | — | 统一管理 TTS 连接,心跳保活、自动重连 | --- ## 安装 ```bash composer require conglei/doubaotts2 # 直接使用源码 composer install ``` **依赖**:PHP >= 7.4, `ext-json`, `ext-openssl`, `guzzlehttp/guzzle` ^7.0 --- ## 鉴权体系 项目涉及三套鉴权方式,对应不同的应用场景: | 鉴权方式 | Header | 适用场景 | 凭据获取 | | :--- | :--- | :--- | :--- | | 新控制台 | `X-Api-Key` | TTS / 声音复刻 V3 | [新控制台](https://console.volcengine.com/speech/new) → API Key 管理 | | 旧控制台 | `X-Api-App-Key` + `X-Api-Access-Key` | TTS / 声音复刻 V3 | [旧控制台](https://console.volcengine.com/speech/app) → 应用详情 | | AKSK | `Authorization: HMAC-SHA256 ...` | 音色槽管理 | [访问控制 → API访问密钥](https://console.volcengine.com/iam/keymanage/) | --- ## 一、语音合成 TTSClient 单向流式 WebSocket 连接,一次输入全部文本,流式返回音频数据。 ### 基本用法 ```php use Conglei\DoubaoTTS2\Client\TTSClient; $client = new TTSClient( resourceId: 'seed-tts-2.0', // TTS 2.0 apiKey: 'your-api-key' // 新鉴权 ); $client->connect(); $client->synthesize('你好,欢迎使用豆包语音合成。', 'zh_female_vv_uranus_bigtts', 'output.mp3'); $client->close(); ``` ### 旧版鉴权 ```php $client = new TTSClient( appId: '5881412157', accessToken: 'lET1cEej...', resourceId: 'seed-tts-2.0' ); ``` ### 流式模式 ```php $client->connect(); $client->setEncoding('mp3'); $client->voiceType = 'zh_female_shuangkuaisisi_mars_bigtts'; $client->sendText('你好,这是流式模式示例。'); $audioData = ''; while ($chunk = $client->receiveAudio()) { $audioData .= $chunk; } file_put_contents('streaming.mp3', $audioData); $client->finishConnection(); $client->close(); ``` ### 合成参数 ```php $client->synthesize($text, $voiceType, 'output.mp3', [ 'audio_params' => [ 'format' => 'mp3', // mp3 / pcm / ogg_opus / wav 'sample_rate' => 24000, // 8000 ~ 48000 'bit_rate' => 32000, // 比特率 'emotion' => 'happy', // 情感:happy / sad / angry / fearful / neutral 'emotion_scale'=> 4, // 情感强度 0-10 'speech_rate' => 10, // 语速 -50 ~ 100 'loudness_rate'=> 5, // 音量 -50 ~ 50 'enable_timestamp' => false, 'enable_subtitle' => false, ], 'req_params' => [ 'additions' => [ // 附加功能 'disable_markdown_filter' => true, 'disable_emoji_filter' => false, 'silence_duration' => 500, ], 'mix_speaker' => [ // 多音色混音 'speakers' => [ ['source_speaker' => 'zh_male_bvlazysheep', 'mix_factor' => 0.3], ['source_speaker' => 'zh_female_shuangkuaisisi_moon_bigtts', 'mix_factor' => 0.7], ], ], ], 'timeout' => 120, ]); ``` ### 常用音色 | 音色 ID | 描述 | | :--- | :--- | | `zh_female_vv_uranus_bigtts` | 女声,明快活泼 | | `zh_female_shuangkuaisisi_moon_bigtts` | 女声,爽朗自然 | | `zh_female_shuangkuaisisi_mars_bigtts` | 女声,火星风格 | | `zh_male_wennuanahu_mars_bigtts` | 男声,温暖 | | `zh_male_bvlazysheep` | 男声,慵懒 | | `zh_female_qingchejingling_mars_bigtts` | 女声,清脆精灵 | | `zh_male_binlangqingnian_mars_bigtts` | 男声,青年 | --- ## 二、双向流式 TTSBidirectionalClient 完整的双向流式生命周期管理,适合实时交互场景。 ### 基本用法 ```php use Conglei\DoubaoTTS2\Client\TTSBidirectionalClient; $client = new TTSBidirectionalClient( appId: '5881412157', accessToken: 'lET1cEej...', resourceId: 'seed-tts-2.0' ); // 一键合成(管理完整的 connection → session → finish 流程) $client->synthesize('你好,欢迎使用双向流式合成。', 'zh_female_vv_uranus_bigtts', 'output.mp3'); $client->close(); ``` ### 手动控制流程 ```php $client->connect(); $client->startConnection(); // 建立连接 $sessionId = $client->startSession([ // 开始会话 'audio_params' => ['format' => 'mp3', 'sample_rate' => 24000], ]); $client->sendText('你好,这是第一条消息。'); // 发送文本 $client->sendText('这是第二条消息。'); $client->finishSession(); // 结束会话 // 接收音频 $audioData = ''; while ($chunk = $client->receiveAudio()) { $audioData .= $chunk; } $client->close(); ``` ### 流式回调 ```php $client->synthesizeStreaming( '你好,这是流式回调测试。', 'zh_female_vv_uranus_bigtts', function ($chunk) { // 实时处理每个音频块 fwrite($streamHandle, $chunk); }, ['audio_params' => ['format' => 'mp3', 'sample_rate' => 24000]] ); ``` ### 方法一览 | 方法 | 说明 | | :--- | :--- | | `connect()` | 建立 WebSocket 连接 | | `startConnection()` | 发送 StartConnection,等待 ConnectionStarted | | `startSession(array $options)` | 开始会话,返回 session_id | | `sendText(string $text)` | 发送合成文本 | | `finishSession()` | 结束当前会话 | | `finishConnection()` | 优雅关闭连接 | | `receiveAudio(?int $timeout)` | 接收音频 / 事件消息 | | `synthesize(...)` | 一键合成(完整流程) | | `synthesizeStreaming(...)` | 流式回调合成 | | `close()` | 关闭连接 | --- ## 三、声音复刻 VoiceCloneClient 基于 HTTP REST API,上传音频样本训练专属音色。支持**预付费**和**后付费**两种模式,训练完成后音色 ID 可直接用于 TTS 合成。 ### 后付费模式(推荐) 无需购买音色槽,首次 TTS 合成时计费。speaker_id 固定为 `custom_speaker_id`,实际名称通过 `custom_speaker_id` 参数传入。训练立即完成。 ```php use Conglei\DoubaoTTS2\Client\VoiceCloneClient; $clone = new VoiceCloneClient( appId: '5881412157', accessToken: 'lET1cEej...' ); // 后付费:训练立即成功 $response = $clone->cloneVoice('ignored', 'demo.wav', [ 'language' => 0, 'custom_speaker_id' => 'MyCloneVoice', // 8-256位,字母开头,仅含数字字母-_ ]); // 查询状态(后付费也需要传 custom_speaker_id) $status = $clone->getVoice('ignored', 'MyCloneVoice'); // 训练完成后用 TTS 合成 $tts = new TTSClient( appId: '5881412157', accessToken: '...', resourceId: 'seed-icl-2.0' // 声音复刻 2.0 ); $tts->synthesize('你好,这是我的克隆声音。', 'MyCloneVoice', 'output.mp3'); ``` ### 预付费模式 需要先在控制台购买音色槽,speaker_id 为 `S_` 开头。提交后需轮询等待训练完成。 ```php $clone = new VoiceCloneClient( appId: '5881412157', accessToken: 'lET1cEej...' ); // 提交训练 $response = $clone->cloneVoice('S_myvoice', 'demo.wav', [ 'language' => 0, ]); // 轮询等待(最多 120s,不传 custom_speaker_id) $result = $clone->waitForTraining('S_myvoice', maxWaitSeconds: 120, intervalSeconds: 3); // 合成 $tts = new TTSClient( appId: '5881412157', accessToken: '...', resourceId: 'seed-icl-2.0' ); $tts->synthesize('你好,这是我的克隆声音。', 'S_myvoice', 'output.mp3'); ``` ### 两种模式对比 | 特性 | 预付费 | 后付费 | | :--- | :--- | :--- | | 前置条件 | 控制台购买音色槽 | 控制台开通后付费音色服务 | | speaker_id | `S_` 开头(槽位 ID) | `custom_speaker_id`(固定值) | | 自定义名称 | 不支持 | `custom_speaker_id` 参数 | | 训练时间 | 需要轮询等待 | 立即完成(status=2) | | 训练次数 | 每槽 15 次 | 15 次 | | 计费 | 按槽位月付 | 首次 TTS 合成时收费 | ### 进阶选项 ```php $clone->cloneVoice('S_myvoice', 'demo.wav', [ 'language' => 0, // 语种枚举 'text' => '音频对应的文本', // 用于 ASR 对齐 'demo_text' => '这是一段试听文本4-80字', // 试听文本 'enable_audio_denoise' => true, // 开启降噪 'enable_audio_denoise_with_snr' => true, // 信噪比阈值降噪 'denoise_max_snr_thresh' => 50, // 降噪阈值 0-100 'reject_min_snr_thresh' => 5.0, // 最低信噪比 'voice_clone_denoise_model_id' => '', // 人声美化模型 'voice_clone_enable_mss' => false, // 音源分离去背景音 'enable_crop_by_asr' => true, // ASR 精确截断 'enable_check_prompt_text_quality' => true, // 文本质量检测 'enable_check_audio_quality' => true, // 音频质量检测 ]); ``` ### 状态查询 ```php // 预付费 $status = $clone->getVoice('S_myvoice'); // 后付费:第二个参数传 custom_speaker_id $status = $clone->getVoice('ignored', 'MyCloneVoice'); ``` ### 轮询等待 ```php // 预付费 $result = $clone->waitForTraining('S_myvoice', maxWaitSeconds: 120, intervalSeconds: 3); // 后付费 $result = $clone->waitForTraining('ignored', 120, 3, 'MyCloneVoice'); ``` ### 升级音色 ```php $clone->upgradeVoice('S_myvoice'); ``` ### 训练状态枚举 | 状态 | 值 | 说明 | | :--- | :--- | :--- | | `STATUS_NOT_FOUND` | 0 | 未找到 | | `STATUS_TRAINING` | 1 | 训练中 | | `STATUS_SUCCESS` | 2 | 成功,可合成 | | `STATUS_FAILED` | 3 | 失败 | | `STATUS_ACTIVE` | 4 | 已激活 | ### 模型类型 | 代码 | 模型 | TTS Resource ID | | :--- | :--- | :--- | | 1 | ICL V1 | `seed-icl-1.0` | | 2 | DiT 标准版 | `seed-icl-1.0` | | 3 | DiT 还原版 | `seed-icl-1.0` | | 4 | ICL V2 | `seed-icl-2.0` | | 5 | ICL V3 | `seed-icl-2.0` | --- ## 四、音色槽管理 SpeakerManager 管理预付费音色槽的购买、续费、查询。使用火山引擎标准 AKSK 签名鉴权。 ### 初始化 ```php use Conglei\DoubaoTTS2\Client\SpeakerManager; $manager = new SpeakerManager( accessKey: 'your-access-key', secretKey: 'your-secret-key', appId: 'your-app-id' ); ``` ### 查询音色 ```php // 分页查询(支持多种筛选) $result = $manager->listSpeakers([ 'State' => 'Success', // 按状态筛选 'PageSize' => 50, // 每页条数 1-100 'ExpireTimeStart' => time() * 1000, // 到期时间范围 ]); // 自动翻页获取全部 $all = $manager->listAllSpeakers(); // 查询指定音色 $result = $manager->listSpeakers(['SpeakerIDs' => ['S_xxx', 'S_yyy']]); // 按状态查找 $active = $manager->findSpeakersByState('Active'); $expired = $manager->findSpeakersByState('Expired'); // 查询即将到期音色 $deadline = (time() + 30 * 86400) * 1000; $expiring = $manager->findExpiringSpeakers($deadline); ``` ### 音色概览 ```php $summary = $manager->getExpirationSummary(); /* [ 'total' => 10, 'active' => 3, 'success' => 5, 'expired' => 2, 'expiring_soon' => 1, 'slots' => [ ['speaker_id' => 'S_xxx', 'state' => 'Success', 'expire_time' => '2026-12-31', ...], ... ], ] */ ``` ### 购买音色槽 ```php // 购买 5 个音色槽,每个 12 个月 $result = $manager->purchaseSlots(times: 12, quantity: 5); // $result['OrderIDs'] = ['Order2001000...'] ``` ### 续费音色槽 ```php // 续费指定音色 6 个月 $result = $manager->renewSlots(['S_xxx', 'S_yyy'], times: 6); // 自动续费 30 天内到期的音色 $result = $manager->autoRenewExpiring(renewMonths: 1, expiringWithinDays: 30); ``` ### 音色状态枚举 | 状态 | 说明 | | :--- | :--- | | `Unknown` | 尚未训练 | | `Training` | 训练中 | | `Success` | 训练成功,可合成 | | `Active` | 已激活(固定,无法再训练) | | `Expired` | 实例已过期 | | `Reclaimed` | 实例已回收 | --- ## 五、连接池 ConnectionPool 统一管理 TTS WebSocket 连接,支持空闲回收、心跳保活、自动重连。 ### 基本用法 ```php use Conglei\DoubaoTTS2\Client\ConnectionPool; $pool = new ConnectionPool( appId: '5881412157', accessToken: '...', resourceId: 'seed-tts-2.0', config: [ 'mode' => 'unidirectional', // unidirectional / bidirectional 'max_connections' => 5, 'idle_timeout' => 300, 'connect_timeout' => 30, 'heartbeat_interval'=> 30, 'max_retries' => 3, ] ); // 批量合成 $texts = ['文本1', '文本2', '文本3']; foreach ($texts as $i => $text) { $pool->synthesize($text, 'zh_female_vv_uranus_bigtts', "output_{$i}.mp3"); } // 自定义操作 $pool->execute(function ($client) { $client->sendText('你好'); $audio = ''; while ($chunk = $client->receiveAudio()) { $audio .= $chunk; } return $audio; }); echo json_encode($pool->getStatus(), JSON_PRETTY_PRINT); $pool->close(); ``` ### 配置说明 | 参数 | 说明 | 默认 | | :--- | :--- | :--- | | `mode` | 连接模式:`unidirectional` / `bidirectional` | `unidirectional` | | `max_connections` | 最大连接数 | 10 | | `idle_timeout` | 空闲超时(秒) | 300 | | `connect_timeout` | 连接超时(秒) | 30 | | `heartbeat_interval` | 心跳间隔(秒) | 30 | | `max_retries` | 建连重试次数 | 3 | --- ## 目录结构 ``` doubaotts2/ ├── composer.json ├── README.md ├── api_doc.md # TTS 接口文档 ├── api_doc2.md # TTS 接口文档 V2 ├── api_v3.md # 声音复刻 V3 接口文档 ├── src/ │ ├── Auth/ │ │ └── VolcengineSigner.php # AKSK 签名器 │ ├── Client/ │ │ ├── WebSocketClient.php # 底层 WebSocket │ │ ├── TTSClient.php # 单向流式 TTS │ │ ├── TTSBidirectionalClient.php # 双向流式 TTS │ │ ├── VoiceCloneClient.php # 声音复刻 V3 │ │ ├── SpeakerManager.php # 音色槽管理 │ │ └── ConnectionPool.php # 连接池 │ └── Protocol/ │ ├── Message.php # 二进制协议编解码 │ ├── MsgType.php # 消息类型 │ ├── MsgTypeFlagBits.php # 消息标志位 │ ├── EventType.php # 事件类型 │ ├── VersionBits.php # 协议版本 │ ├── HeaderSizeBits.php # 头部大小 │ ├── SerializationBits.php # 序列化方式 │ └── CompressionBits.php # 压缩方式 ├── examples/ │ ├── tts_example.php # TTS 全功能示例 │ ├── test_bidirectional.php # 双向流式测试 │ ├── voice_clone_example.php # 声音复刻示例 │ ├── test_voice_clone_e2e.php # 声音复刻端到端测试 │ ├── speaker_example.php # 音色槽管理示例 │ ├── benchmark_pool.php # 连接池性能基准 │ └── benchmark_v2.php # 双向 vs 单向性能对比 └── vendor/ ``` --- ## 运行示例 ```bash # TTS 合成 export DOUBAO_API_KEY=your-api-key php examples/tts_example.php # 双向流式 php examples/test_bidirectional.php # 声音复刻(后付费端到端测试) export DOUBAO_APP_ID=your-app-id export DOUBAO_ACCESS_TOKEN=your-access-token php examples/test_voice_clone_e2e.php # 声音复刻(手动) php examples/voice_clone_example.php demo.wav # 音色槽管理 export VOLC_ACCESS_KEY=your-ak export VOLC_SECRET_KEY=your-sk export VOLC_APP_ID=your-app-id php examples/speaker_example.php summary # 概览 php examples/speaker_example.php list # 全部音色 php examples/speaker_example.php purchase 12 5 # 买 5 个音色,每个 12 月 php examples/speaker_example.php renew 6 S_xxx # 续费 S_xxx 6 个月 php examples/speaker_example.php auto-renew 1 30 # 自动续费 30 天内到期音色 ``` --- ## 错误处理 所有客户端在以下情况抛出 `RuntimeException`: - 连接失败 / WebSocket 握手失败 - 鉴权失败 - 合成返回服务端错误 - 未收到音频数据 - 文件读写失败 - 连接池已满 建议始终包裹 try-catch: ```php try { $client->synthesize($text, $voice, 'output.mp3'); } catch (\RuntimeException $e) { error_log("TTS failed: " . $e->getMessage()); } ``` --- ## 许可证 MIT