> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Client 模式 - 預設集 - VOICEVOX for Laravel

> 說明如何在 VOICEVOX for Laravel 的 Client 模式操作官方引擎的預設集,儲存與重用語音合成參數。

使用預設集功能,可將常用的語音合成參數組合儲存於官方 VOICEVOX 引擎並重複使用。在 Client 模式下,Laravel 端不會儲存預設集,而是使用連線目標官方引擎所管理的預設集 API。

## 概觀

Client 模式的預設集透過 `Voicevox` Facade 操作。內部會對官方 VOICEVOX 引擎的 `/presets`、`/add_preset`、`/update_preset`、`/delete_preset`、`/audio_query_from_preset` 發送 HTTP 請求。

官方引擎的預設集以 `presets.yaml` 儲存於各 OS 的使用者區。VOICEVOX 應用(產品版)macOS 的 build 版通常儲存於下列位置。

```text theme={null}
~/Library/Application Support/voicevox-engine/presets.yaml
```

若以 Docker 啟動官方引擎,也會儲存於容器內的使用者區。只要繼續使用同一個容器,即使重啟資料也會維持。但若使用 `docker run --rm` 之類每次建立臨時容器,容器結束時預設集會遺失。若要確實持久化預設集,請以 Docker volume 掛載容器內的使用者區。

與 Native 模式的 `storage/voicevox/presets.json` 為分開管理。Laravel 端的 `config('voicevox.core.presets')` 不會用於 Client 模式。

## 事前準備

啟動官方 VOICEVOX 引擎。

```shell theme={null}
docker pull voicevox/voicevox_engine:cpu-latest
docker run --rm -p '127.0.0.1:50021:50021' voicevox/voicevox_engine:cpu-latest
```

連線目標可透過 `VOICEVOX_URL` 變更。

```env theme={null}
VOICEVOX_URL=http://127.0.0.1:50021
```

## 預設集結構

Client 模式收發的預設集為對應官方引擎 API schema 的陣列。

```php theme={null}
[
    'id' => 1,                // 預設集 ID(整數)
    'name' => 'ゆっくり',      // 預設集名稱
    'speaker_uuid' => 'uuid', // Speaker UUID(字串)
    'style_id' => 1,          // Style ID(整數)
    'speedScale' => 0.8,      // 語速
    'pitchScale' => 0.0,      // 音高
    'intonationScale' => 1.0, // 抑揚
    'volumeScale' => 1.0,     // 音量
    'prePhonemeLength' => 0.1, // 開頭靜音
    'postPhonemeLength' => 0.1, // 結尾靜音
]
```

## 基本用法

### 建立預設集

可透過 `Voicevox::addPreset()` 建立預設集。在官方引擎中,`id` 指定為 `0` 會分配未使用的 ID。

```php theme={null}
use Revolution\Voicevox\Voicevox;

$id = Voicevox::addPreset([
    'id' => 0,
    'name' => 'ゆっくり丁寧',
    'speaker_uuid' => '7ffcb7ce-00ec-4bdc-82cd-45a8889e43ff',
    'style_id' => 1,
    'speedScale' => 0.8,
    'pitchScale' => 0.0,
    'intonationScale' => 1.2,
    'volumeScale' => 1.0,
    'prePhonemeLength' => 0.1,
    'postPhonemeLength' => 0.1,
]);

echo $id; // 例: 1
```

### 取得所有預設集

```php theme={null}
use Revolution\Voicevox\Voicevox;

$presets = Voicevox::presets();

/*
[
    [
        "id" => 1,
        "name" => "ゆっくり丁寧",
        "speaker_uuid" => "7ffcb7ce-00ec-4bdc-82cd-45a8889e43ff",
        "style_id" => 1,
        "speedScale" => 0.8,
        ...
    ],
    ...
]
*/
```

### 更新預設集

```php theme={null}
use Revolution\Voicevox\Voicevox;

$id = Voicevox::updatePreset([
    'id' => 1,
    'name' => 'ゆっくりはっきり',
    'speaker_uuid' => '7ffcb7ce-00ec-4bdc-82cd-45a8889e43ff',
    'style_id' => 1,
    'speedScale' => 0.7,
    'pitchScale' => 0.0,
    'intonationScale' => 1.5,
    'volumeScale' => 1.0,
    'prePhonemeLength' => 0.1,
    'postPhonemeLength' => 0.1,
]);
```

### 刪除預設集

```php theme={null}
use Revolution\Voicevox\Voicevox;

Voicevox::deletePreset(1);
```

## 使用預設集進行語音合成

### talkFromPreset()

`Voicevox::talkFromPreset()` 會使用官方引擎的 `/audio_query_from_preset`,建立已套用預設集的 `TalkAudioQuery`。

```php theme={null}
use Revolution\Voicevox\Voicevox;

$response = Voicevox::talkFromPreset('使用預設集', presetId: 1)
    ->generate(id: 1);

$response->storeAs('client', 'preset-talk.wav');
```

### audioQueryFromPreset()

若只想取得合成前的 audio query 陣列,可使用 `audioQueryFromPreset()`。

```php theme={null}
use Revolution\Voicevox\Voicevox;

$audioQuery = Voicevox::audioQueryFromPreset(
    text: '只建立預設集的 query',
    presetId: 1,
);

$audioQuery['speedScale'] = 1.1;
```

### 使用 tap() 進行額外調整

從預設集建立的 `TalkAudioQuery` 也可以像一般的 `Voicevox::talk()` 一樣,透過 `tap()` 調整。

```php theme={null}
use Revolution\Voicevox\Client\TalkAudioQuery;
use Revolution\Voicevox\Voicevox;

$response = Voicevox::talkFromPreset('稍微快一點朗讀', presetId: 1)
    ->tap(function (TalkAudioQuery $talk) {
        $talk->audioQuery['speedScale'] = 1.2;
    })
    ->generate(id: 1);
```

## 與 Engine API 的對應

`Voicevox` Facade 的各方法對應於官方引擎的 API。

| Laravel                            | 官方引擎 API                                            |
| ---------------------------------- | --------------------------------------------------- |
| `Voicevox::presets()`              | `GET /presets`                                      |
| `Voicevox::addPreset()`            | `POST /add_preset`                                  |
| `Voicevox::updatePreset()`         | `POST /update_preset`                               |
| `Voicevox::deletePreset()`         | `POST /delete_preset`                               |
| `Voicevox::audioQueryFromPreset()` | `POST /audio_query_from_preset`                     |
| `Voicevox::talkFromPreset()`       | `POST /audio_query_from_preset` + `POST /synthesis` |

## 與 Native 模式的差異

| 項目             | Client 模式                                                    | Native 模式                       |
| -------------- | ------------------------------------------------------------ | ------------------------------- |
| 使用方式           | `Voicevox` Facade                                            | `preset()` / `talk()` helper    |
| 儲存格式           | 官方引擎的 `presets.yaml`                                         | Laravel 的 `presets.json`        |
| macOS 範例       | `~/Library/Application Support/voicevox-engine/presets.yaml` | `storage/voicevox/presets.json` |
| Audio query 生成 | 官方引擎的 `/audio_query_from_preset`                             | Laravel 端的 Native 實作            |
| 引擎程序           | 需要                                                           | 不需要(需要 FFI)                     |

## 實用範例

### 旁白用

```php theme={null}
use Revolution\Voicevox\Voicevox;

Voicevox::addPreset([
    'id' => 0,
    'name' => 'ナレーション',
    'speaker_uuid' => '7ffcb7ce-00ec-4bdc-82cd-45a8889e43ff',
    'style_id' => 1,
    'speedScale' => 1.0,
    'pitchScale' => -0.05,
    'intonationScale' => 0.8,
    'volumeScale' => 1.0,
    'prePhonemeLength' => 0.15,
    'postPhonemeLength' => 0.15,
]);
```

### 快速對話用

```php theme={null}
Voicevox::addPreset([
    'id' => 0,
    'name' => '早口',
    'speaker_uuid' => '388f246b-8c41-4ac1-8e2d-5d79f3ff56d9',
    'style_id' => 3,
    'speedScale' => 1.5,
    'pitchScale' => 0.05,
    'intonationScale' => 1.3,
    'volumeScale' => 1.0,
    'prePhonemeLength' => 0.05,
    'postPhonemeLength' => 0.05,
]);
```

## 參數詳解

* `speedScale`: 0.5 \~ 2.0(語速)
* `pitchScale`: -0.15 \~ 0.15(音高)
* `intonationScale`: 0.0 \~ 2.0(抑揚)
* `volumeScale`: 0.0 \~ 2.0(音量)
* `prePhonemeLength`: 0.0 \~ 1.5(開頭靜音,秒)
* `postPhonemeLength`: 0.0 \~ 1.5(結尾靜音,秒)

## 注意事項

<Warning>
  在 Client 模式下更新的是官方引擎端的 `presets.yaml`。不會儲存於 Laravel 專案的 `storage`。
</Warning>

* 若使用 `docker run --rm` 每次建立臨時容器,容器結束時預設集會遺失。
* 請同時包含 `speaker_uuid` 與 `style_id`。
* 使用 `talkFromPreset()` 建立的 query 進行 `generate(id:)` 時,通常指定與預設集的 `style_id` 相同的 ID。

## 疑難排解

### 無法取得預設集

1. 確認官方 VOICEVOX 引擎是否已啟動。
2. 確認 `VOICEVOX_URL` 指向正確的連線目標。
3. 確認是否在 Docker 中重新啟動了不同的容器。

### 找不到預設集檔案位置

macOS 的 build 版請確認以下位置。

```text theme={null}
~/Library/Application Support/voicevox-engine/presets.yaml
```

Docker 中會儲存於官方引擎的使用者區(容器內)。若需持久化,請將容器內的使用者區以 Docker volume 掛載。

### 不知道 speaker\_uuid

可從 speaker 清單取得 UUID。

```php theme={null}
use Revolution\Voicevox\Voicevox;

$speakers = Voicevox::speakers();

foreach ($speakers as $speaker) {
    echo $speaker['name'].': '.$speaker['speaker_uuid'].PHP_EOL;
}
```


## Related topics

- [Native 模式 - 預設集 - VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/native-presets.md)
- [Client 模式 - 使用者字典 - VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/client-user-dict.md)
- [Client 模式:Song(歌聲語音合成)- VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/client-song.md)
- [Client 模式:Talk(文字語音合成)- VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/client-talk.md)
- [入門 - VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/getting-started.md)
