CapCutの高品質なTTSを使いたいからラッパーAPIを作ったお話

# あいさつ
記事を見ていただきありがとうございます！

電子工作したり、サーバーいじったりソフト作ったり...
いろいろしてる大学生です

地味に今回が初記事(いろいろあって消えた)になります！

## 注意事項
この記事、実は2024年2月ごろに書いていたのですが、以前の手法が使えなくなりアップデートに時間がかかっていたため、一部古いURL等があります。
ご了承ください。
# 目次
[・なにこれ](#なにこれ)
└[・昔のお話](#昔のお話)
[・使い方](#使い方)
[・APIドキュメント](#APIドキュメント)
[・終わり](#終わり)


# なにこれ
みなさん、TikTok や YouTube Short でたびたび流れてくる動画に使われている合成音声のクオリティーに驚くことはないでしょうか？
私も初めて見た時、あまりにも自然でかなりびっくりしました。

そんなこんなで検索してみたところ、TikTokのアプリ自体についている読み上げ機能や**CapCut**という編集ソフトに付属している読み上げ機能であの声を作っていることがわかりました。

CapCutの合成音声を知らないよ～って方は以下の動画を見てもらえばわかると思います。

<iframe width="857" height="482" src="https://www.youtube.com/embed/xdWiGrRxlF4" title="CapCut-TTS" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

音声の原稿は[日本語ダミーテキスト生成器](https://tool.stabucky.com/convert/dummy_text_generator.htm)にて400字で生成したものを利用しています。
\*2024/05/30 時点でどうやらサイトが死んでいるみたい

### 昔のお話
以前検索したときにこの方の記事が出てきて、しばらくの間利用させていただいたのですが、APIのドメインが失効してしまったらしくアクセスできなくなりました。

https://note.com/kohnoselami/n/nba3ee14577cc

\*2024/03/30 時点でどうやら記事が削除されたみたい

私の運営している ChatReader という読み上げBOTでもCapCutの高品質な音声を使いたいと思いラッパーAPIを作成しました。

https://kuwa.app/discord/chatreader/

# 使い方
本プログラムは、セルフホスト型となっていますのでAPIが存在しなくなる心配はありません。(CapCut側が仕様を変更することを除いて)

## ソースからコンパイル
まずはGitHubからリポジトリをクローンします。
https://github.com/kuwacom/CapCut-TTS
```bash
git clone https://github.com/kuwacom/CapCut-TTS.git
cd CapCut-TTS
```
`git@github.com:kuwacom/CapCut-TTS.git`でも構いません。

次に必要なパッケージをインストールします。
なお動作の検証はそれぞれ以下のバージョンでしか行っていません。

**Nodejs:** `v20.10.0` `v18.16.1`
**npm:** `10.2.5`
**OS:** `Windows 10` `Windows 11` `Ubuntu 20.04`

```bash
npm i
```

パッケージがインストールできたらコンパイルを行います。
本プロジェクトはTypeScriptで記述していますのでコンパイルが必要です。
もしTypeScriptをまだインストールしていない方は検索して`tsc`をインストールしてください。

```bash
npm run build
```
## .envファイルの作成
`.env.example`ファイルからコピーして`.env`ファイルを作成し、その中に以下の項目があるかを確認してください。
```
DEVICE_TIME=""
SIGN=""
```
それぞれの項目に次の手順で取得した値を入力してください。

## 値の入手
次に[CapCut](https://www.capcut.com/)へ行き、ログインしてください。

![1](https://raw.githubusercontent.com/kuwacom/CapCut-TTS/main/images/1.png)
CapCutへログイン後、新規プロジェクトを空で作成し、適当なテキストを作成します。
その後、テキスト読み上げタブへ移り、DevToolsの`Clear Network log`をクリックして一度ログを消して見やすくします。

![2](https://raw.githubusercontent.com/kuwacom/CapCut-TTS/main/images/2.png)
その後、適当な声を選択して生成させましょう。

すると、いくつかの通信が行われ、ログが出てきます。
最初の`2000ms`程度をフィルタして見てみると画像のような通信ログがあるはずです。(もし数が多い場合は、`Filter`から`token`と検索してください。)

その中から`POST`で通信している`token`を見つけてください。

その通信のリクエストヘッダーから画像の二つの値、`Device-Time`と`Sign`をコピーして先ほど作成した`.env`ファイルの各変数へ記入します。

# APIドキュメント
基本的なAPIの仕様です。
詳細に関しては[GitHubのリポジトリ](https://github.com/kuwacom/CapCut-TTS)にも書いてあります。
## ベースURL
```
http://<host>:<port>/v1/
```
## エンドポイント
### /synthesize
#### リクエスト
```http
GET /v1/synthesize
```
#### クリエパラメーター
| パラメーター | 型 | 必須 | 説明 | デフォルト値 |
|--------------|----|------|------|--------------|
| `text`   | string | はい | 読み上げるテキスト | - |
| `type`   | number | いいえ | 使用する合成音声のタイプ | `0` |
| `pitch`  | number | いいえ | 合成された音声のピッチ | `10` |
| `speed`  | number | いいえ | 合成された音声のスピード | `10` |
| `volume` | number | いいえ | 合成された音声のボリューム | `10` |
| `method` | string | いいえ | 合成された音声のレスポンスに使用するメソッド<br>`buffer` または `stream` のいずれか | `buffer` |

#### レスポンス
| ステータスコード | 状態 | 説明 | 内容 |
|------------------|------|------|------|
| `200 OK` | 成功 | WAV形式の合成された音声を返します | `buffer` メソッドの場合: 完全なバッファとして音声を返します<br>`stream` メソッドの場合: 音声データをストリーム配信します |
| `400 Bad Request` | エラー | クエリパラメータが不足しています | ```json { "error": "Bad Request" } ``` |
| `500 Internal Server Error` | エラー | 音声生成に問題が発生しました | `buffer` メソッドの場合: ```json { "error": "can't get buffer" } ``` <br>`stream` メソッドの場合: ```json { "error": "can't get stream" } ``` |

#### リクエスト例
```http
GET http://localhost:8080/v1/synthesize?text=こんにちは&type=0&pitch=10&speed=10&volume=10&method=buffer
```

#### レスポンス例
| ステータスコード | Content-Type | 内容 |
|------------------|--------------|------|
| `200 OK` | audio/wav | WAV形式の音声バッファ |

## Voice Type List
| type | 声の種類          | スピーカーID            |
|------|------------------|-------------------------|
| 0    | 謎1 男子1        | BV525_streaming         |
| 1    | 謎2 坊や          | BV528_streaming         |
| 2    | カワボ            | BV017_streaming         |
| 3    | お姉さん          | BV016_streaming         |
| 4    | 少女              | BV023_streaming         |
| 5    | 女子              | BV024_streaming         |
| 6    | 男子2             | BV018_streaming         |
| 7    | 坊ちゃん          | BV523_streaming         |
| 8    | 女子              | BV521_streaming         |
| 9    | 女子アナ          | BV522_streaming         |
| 10   | 男性アナ          | BV524_streaming         |
| 11   | 元気ロリ          | BV520_streaming         |
| 12   | 明るいハニー      | VOV401_bytesing3_kangkangwuqu |
| 13   | 優しいレディー    | VOV402_bytesing3_oh     |
| 14   | 風雅メゾソプラノ  | VOV402_bytesing3_aidelizan |
| 15   | Sakura            | jp_005                  |
| その他/入力なし | お姉さん         | BV016_streaming |

# 終わり
今回、CapCutのAPI利用にあたってどのくらい利用したら制限が来るのかなぁと結構心配していましたが、今のところ制限は一度もついたことはありません。
編集もいつも通り普通にできますし、、、
CapCutかなり太っ腹ですねぇ

最後までご覧いただきありがとうございました！
今後もぼちぼち記事を更新していく予定ですのでよろしくお願いします。