Fish Audio APIでイーロンマスク風の音声でtext to speech
する際の備忘メモです
尚、個人アカウントでFree版を使用しています。実装は基本的にpythonです。
準備
実行環境:Macbook Pro macOS Monterey 12.5.1, Apple M1 Max, 32GB memory
pythonバージョン:
$ python --version
Python 3.12.5
こちらを参考にvenv
環境を構築
$ python3 -m venv venvtest
$ source venvtest/bin/activate
こちらを参考にfish audio python library
をインストール
$ pip install fish-audio-sdk
APIコールに必要な準備をする
- APIキーを作成
- text-to-speechを参照してAPIの使用例を確認(pythonの例)
- チャージ(例えばお試しで$1以下を課金)
実行
実際にtext to speech API
コール
ポイント
- "your_api_key";ここは"FISHAUDIO API KEY"を指定するように変更
- "MODEL_ID_UPLOADED_OR_CHOSEN_FROM_PLAYGROUND": ここは期待する"reference_id"を指定するように変更(イーロンマスク風音声の場合はこちらからモデルIDをコピーする)
from fish_audio_sdk import Session, TTSRequest, ReferenceAudio
# ここは"FISHAUDIO API KEY"を指定するように変更
session = Session("your_api_key")
# Option 1: Using a reference_id
with open("output1.mp3", "wb") as f:
for chunk in session.tts(TTSRequest(
# ここは期待する"reference_id"を指定するように変更
reference_id="MODEL_ID_UPLOADED_OR_CHOSEN_FROM_PLAYGROUND",
text="Hello, world!"
)):
f.write(chunk)
出力ファイル確認
$ python example.py
## "output1.mp3" というファイルが出力されていればOK
$ ls
output1.mp3
音声ファイルを再生(今回はmp3だが他にもフォーマット指定が可能)
## 例えばQuick Playerを使ってコマンドラインから再生する場合はqmanageを使えばOK
$ qlmanage -p output1.mp3
→ 指定したテキストファイルが読み上げられたら動作OK(今回はHello, world!
と言えばOK)
Hello World!
だと分かりづらいので、サンプルと同じ文章を与える
Elon Musk(Noise reduction)
text="So, the key to effective noise reduction is... um... understanding signal processing at a fundamental level. We're basically teaching AI to distinguish between what humans want to hear and what they don't. It's like teaching a computer to be really good at selective hearing."
275文字
だと大体変換に4sec掛かる
$ time python example.py
python3 example.py 0.22s user 0.04s system 6% cpu 3.981 total
フォーマットをmp3
-->wav
に変える場合は以下をオプション指定
...
with open("output1.mp3", "wb") as f:
...
format="wav"
wav
に変えた場合は変換時間が若干伸びている気がする
% time python example.py
python3 example.py 0.23s user 0.05s system 5% cpu 4.663 total
この場合は、 約17sec, 1.4MB
のWAVデータになる
% ls -lh output1.wav
-rw-r--r--@ 1 xxx xxx 1.4M 2 4 00:00 output1.wav
C言語
の場合
こちらを参考にlibcurl
をインストール
以下はMacOSの場合
brew install curl
コード
- "your_api_key";ここは"FISHAUDIO API KEY"を指定するように変更
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
// 書き込みコールバック関数
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) {
size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
int main(void) {
CURL *curl;
CURLcode res;
FILE *fp;
const char *output_filename = "output2.wav";
// APIエンドポイントのURL(例)
const char *url = "https://api.fish.audio/v1/tts";
// APIキー
// "your_api_key";ここは"FISHAUDIO API KEY"を指定するように変更
const char *api_key = "your_api_key";
// JSON形式のリクエストデータを組み立てる(例)
// 実際のフォーマットはAPI仕様に合わせてください
const char *json_data = "{"
"\"reference_id\": \"03397b4c4be74759b72533b663fbd001\","
"\"text\": \"So, the key to effective noise reduction is... um... understanding signal processing at a fundamental level. We're basically teaching AI to distinguish between what humans want to hear and what they don't. It's like teaching a computer to be really good at selective hearing.\","
"\"format\": \"wav\""
"}";
// libcurlの初期化
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
// 出力ファイルをバイナリ書き込みでオープン
fp = fopen(output_filename, "wb");
if (!fp) {
fprintf(stderr, "ファイルを開けません: %s\n", output_filename);
return 1;
}
// URL設定
curl_easy_setopt(curl, CURLOPT_URL, url);
// HTTP POSTを行う設定
curl_easy_setopt(curl, CURLOPT_POST, 1L);
// POSTフィールドとしてJSONデータを送信
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
// APIキーをヘッダに設定(例:Authorizationヘッダとして)
struct curl_slist *headers = NULL;
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "Authorization: Bearer %s", api_key);
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, auth_header);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// レスポンスデータの書き込み先を設定
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
// リクエストの実行
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() 失敗: %s\n", curl_easy_strerror(res));
}
// 後始末
fclose(fp);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
コンパイル
$ gcc -o tts example.c -lcurl
実行
$ ./tts
以下データが取得できていれば&再生できればOK
"output2.wav"
C++
の場合
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <curl/curl.h>
// 書き込みコールバック関数
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) {
return fwrite(ptr, size, nmemb, static_cast<FILE*>(stream));
}
int main() {
CURL *curl;
CURLcode res;
FILE *fp;
const char *output_filename = "output2.wav";
// APIエンドポイントのURL
const char *url = "https://api.fish.audio/v1/tts";
// APIキー ("FISHAUDIO API KEY"に置き換えてください)
const char *api_key = "your_api_key";
// JSON形式のリクエストデータを生文字列リテラルで宣言
// R"(...)" の形式を使うと、内部に " や \n をそのまま書けます
const char *json_data = R"({
"reference_id": "03397b4c4be74759b72533b663fbd001",
"text": "So, the key to effective noise reduction is... um... understanding signal processing at a fundamental level. We're basically teaching AI to distinguish between what humans want to hear and what they don't. It's like teaching a computer to be really good at selective hearing.",
"format": "wav"
})";
// libcurlの初期化
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
// 出力ファイルをバイナリ書き込みでオープン
fp = fopen(output_filename, "wb");
if (!fp) {
std::cerr << "ファイルを開けません: " << output_filename << std::endl;
curl_easy_cleanup(curl);
curl_global_cleanup();
return 1;
}
// URL設定
curl_easy_setopt(curl, CURLOPT_URL, url);
// HTTP POSTを行う設定
curl_easy_setopt(curl, CURLOPT_POST, 1L);
// POSTフィールドとしてJSONデータを送信
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
// APIキーをヘッダに設定
struct curl_slist *headers = nullptr;
{
// Authorizationヘッダを用意
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "Authorization: Bearer %s", api_key);
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, auth_header);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
}
// レスポンスデータの書き込み先を設定
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
// リクエストの実行
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "curl_easy_perform() 失敗: "
<< curl_easy_strerror(res) << std::endl;
}
// 後始末
fclose(fp);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
コンパイル
g++ -std=c++11 -o tts example.cpp -lcurl
実行
$ time ./tts
./tts 0.04s user 0.03s system 1% cpu 4.588 total
$ ls -l output2.wav
-rw-r--r-- 1 xxx xxx 1208364 x xx xx:xx output2.wav
テキストを"300m ahead, turn right on Test Street."にすると、
"text": "300m ahead, turn right on Test Street.",
おおよそ3秒ほど(200kByte程)のデータになる
ls -l output2.wav
xxx204844 xxx output2.wav
time ./tts
./tts 0.02s user 0.01s system 1% cpu 1.813 total
トラブルシューティング
fish_audio_sdk.exceptions.HttpCodeErr: 402 Payment Required
→ この機能を利用するには課金が必要です(課金してください)というエラー、一旦課金すると解決する
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/402
The HTTP 402 Payment Required client error response status code is a nonstandard response status code reserved for future use.
fish_audio_sdk.exceptions.HttpCodeErr: 500 Internal Server Error
→ サーバ側でエラー、例えばAPIパラメータのうちreference_id
が間違っているとこのような結果が返ることがある
以上です