0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Fish Audio APIでイーロンマスク風の音声で`text to speech`する際のメモ

Last updated at Posted at 2025-02-24

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コールに必要な準備をする

実行

実際にtext to speech APIコール

ポイント

example.py
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"を指定するように変更
example.c
#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++の場合

example.cpp
#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が間違っているとこのような結果が返ることがある


以上です

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?