広告枠を募集中 ご相談ください

Listnr 音声合成 API による音声ストリーミングとカスタム音声パラメータの設定手順

365Finds Editorial
Wiki 記事 11,430 本収録

あなたの AI で 365 Wiki を使う

下のプロンプトをコピーして、普段使っている AI に貼り付け、そのまま質問してください。

完全版 Skill をダウンロード

まずはプロンプトでお試しください。よく使う場合は完全版 365Wiki Skill をインストールすると、毎回貼り付ける必要がありません。普段使う AI がなければ、Gemini や Microsoft Copilot のウェブ版でも使えます。

現代の Web アプリケーションにおいてリアルタイムなテキスト読み上げ(TTS: Text-to-Speech)を導入する際、最大の課題は「初回バッファ再生までの低レイテンシ」「肉声に近い自然なイントネーション」「API 認証情報の保護」をいかに両立させるかという点にあります。Listnr は開発者向けに 2 つの API パイプラインを提供しています。1 つは Microsoft Azure、Google Cloud、AWS Polly、IBM Watson の音声を一元的に扱える標準 V1 REST API、もう 1 つは Ultra Premium ボイスおよび音声クローン(Cloned Voices)に対応した超低遅延 V2 ストリーミングエンドポイント /stream-voice です。

Web フロントエンドから安全かつ低遅延に音声再生を実現するためのベストプラクティスは、バックエンドに軽量プロキシを配置し、そこで認証トークンを付与して Listnr のストリーミング API を呼び出し、バイナリチャンクをブラウザへ直接パイプ(pipe)転送するアーキテクチャです。

sequenceDiagram
    autonumber
    actor User as ブラウザ(フロントエンド)
    participant Server as アプリケーションバックエンド(プロキシ)
    participant Listnr as Listnr V2 ストリーミング API
    
    User->>Server: POST /api/tts (テキスト, voiceId, パラメータ)
    Note over Server: 安全に x-listnr-token を付与
    Server->>Listnr: POST /api/v2/stream-voice
    Listnr-->>Server: 分割バイナリ音声ストリーム (WAV / MP3)
    Server-->>User: パイプ転送 (Transfer-Encoding: chunked)
    Note over User: Web Audio API / HTML5 Audio で即時バッファ再生

1. 認証方式とセキュアなシステム設計

本番用の API キーをブラウザ側のフロントエンドコードに直接埋め込むことは厳禁です。Listnr は独自ヘッダー(x-listnr-token)を用いてリクエストを認証しており、このキーはアカウントの合成可能文字数(ワードクレジット)および請求プランに直結しています。クライアントサイドでキーが露出すると、不正利用によるクレジット枯渇や予期せぬ課金リスクを招きます。

認証情報の保護とバックエンドプロキシ設計

業界標準の構成では、Next.js API Routes、Express、Fastify、あるいは Python FastAPI などの軽量なバックエンドレイヤーを仲介させます。

API コンポーネントベース URL / パス主な役割セキュリティと呼び出し要件
V2 ストリーミング APIhttps://cloning.listnr.tech/api/v2/stream-voiceUltra Premium 音声とクローン音声の低遅延バイナリストリーミングサーバーサイド専用;x-listnr-token 必須
V2 音声モデル取得https://cloning.listnr.tech/api/v2/available-voices利用可能なプリセット音声および自作クローン音声の一覧取得サーバー側でキャッシュ;UI の選択肢として返却
V1 マルチプロバイダー RESThttps://bff.listnr.tech/api/tts/v1/convert-textAzure や Google など複数クラウドの従来音声を一括生成バッチ処理向け;SSML ルートタグに対応

2. 音声モデル ID の探索と取得

音声合成を実行する前に、対象となる音声モデルの固有識別子(voice_id)を取得しておく必要があります。サーバーの起動時にエンドポイントからモデル一覧を取得し、Redis やインメモリキャッシュに保持しておく運用が効率的です。

# アカウントで利用可能な音声モデル一覧を取得
curl -X GET "https://cloning.listnr.tech/api/v2/available-voices" \
  -H "x-listnr-token: YOUR_LISTNR_API_KEY" \
  -H "Accept: application/json"

レスポンスには、各ボイスの英数字 ID(例: 21m00Tcm4TlvDq8ikWAM)を含むオブジェクト配列が返されます。フロントエンドからこの ID をバックエンドへ渡すことで、意図した声質での合成が行われます。


3. 音声ストリーミング合成とカスタムパラメータの設定

Listnr の V2 ストリーミングエンドポイントは、合成対象テキスト、音声モデル ID、および表現力を微調整するための settings オブジェクトを含む JSON 形式のリクエストを受け付けます。

{
  "voice_id": "21m00Tcm4TlvDq8ikWAM",
  "text": "システム警告: データベースのレプリケーションが遅延しています。<break time=\"0.4s\"/><break strength=\"strong\"/>フェイルオーバー処理を開始します。",
  "settings": {
    "stability": 0.71,
    "similarity_boost": 0.50,
    "style": 0.05,
    "use_speaker_boost": false
  }
}

パラメータチューニングの指針

各設定値が音声特性に与える影響を理解することで、用途に応じた最適な音質設計が可能になります。

SSML ポーズとリズム制御タグ

V2 /stream-voice エンドポイントでは、<speak> ルートタグで囲むことなく、テキスト内に直接 SSML のブレークタグを挿入できます。


4. Web アプリケーションの実装コード例

以下に、Node.js/Express によるストリーミング中継サーバーと、Fetch API を用いて受信した音声を即時再生するブラウザ側クライアントの実装例を示します。

サーバーサイド・プロキシ実装(server.js)

import express from 'express';
import fetch from 'node-fetch';

const app = express();
app.use(express.json());

const LISTNR_API_KEY = process.env.LISTNR_API_KEY;
const STREAM_URL = 'https://cloning.listnr.tech/api/v2/stream-voice';

app.post('/api/tts/stream', async (req, res) => {
  try {
    const { text, voiceId, settings } = req.body;

    if (!text || !voiceId) {
      return res.status(400).json({ error: 'テキストまたは voiceId が指定されていません。' });
    }

    const payload = {
      voice_id: voiceId,
      text: text,
      settings: {
        stability: settings?.stability ?? 0.71,
        similarity_boost: settings?.similarity_boost ?? 0.50,
        style: settings?.style ?? 0.0,
        use_speaker_boost: settings?.use_speaker_boost ?? false
      }
    };

    const upstreamResponse = await fetch(STREAM_URL, {
      method: 'POST',
      headers: {
        'x-listnr-token': LISTNR_API_KEY,
        'Content-Type': 'application/json',
        'Accept': '*/*'
      },
      body: JSON.stringify(payload)
    });

    if (!upstreamResponse.ok) {
      const errorText = await upstreamResponse.text();
      return res.status(upstreamResponse.status).json({
        error: `Listnr API エラー: ${upstreamResponse.statusText}`,
        details: errorText
      });
    }

    // ストリーミング再生用のレスポンスヘッダーを設定
    res.setHeader('Content-Type', 'audio/wav');
    res.setHeader('Transfer-Encoding', 'chunked');

    // 受信ストリームをクライアントへ直接パイプ転送
    upstreamResponse.body.pipe(res);
  } catch (err) {
    console.error('TTS ストリーミングエラー:', err);
    res.status(500).json({ error: '内部サーバープロキシエラーが発生しました。' });
  }
});

app.listen(3000, () => console.log('音声プロキシサーバーがポート 3000 で起動しました'));

クライアントサイドでの受信と再生(client.js)

/**
 * バックエンドから音声ストリームを取得し即時再生
 */
async function streamAndPlayAudio(text, voiceId) {
  const response = await fetch('/api/tts/stream', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      text: text,
      voiceId: voiceId,
      settings: {
        stability: 0.65,
        similarity_boost: 0.60,
        style: 0.0
      }
    })
  });

  if (!response.ok) {
    throw new Error(`音声データの取得に失敗しました: ${response.status}`);
  }

  // 受信したバイナリデータを Blob に変換し HTML5 Audio で再生
  const audioBlob = await response.blob();
  const audioUrl = URL.createObjectURL(audioBlob);
  const audio = new Audio(audioUrl);
  
  audio.onended = () => URL.revokeObjectURL(audioUrl);
  await audio.play();
}

5. 本番運用のアーキテクチャ設計と留意点

Listnr TTS を商用環境へデプロイする際は、以下の技術的トレードオフを検討してください。

  1. V1 REST と V2 ストリーミングの使い分け: Azure Neural などの使い慣れたクラウド音色を利用する場合や、字幕表示のために単語単位のタイムスタンプ(Word Timestamps)が不可欠な場合は V1 を選択します。会話型 AI など超低遅延なリアルタイム発話や高品質なクローン声質を優先する場合は V2 ストリーミングを採用します。
  2. クレジット消費防止とリクエストのデバウンス: 文字数に応じた課金が発生するため、検索サジェストやチャット入力中の連打を防ぐデバウンス処理を導入し、ユーザーが再入力した際は AbortController で直前のリクエストを即座に中断させます。
  3. 定型音声のアセットキャッシュ: システムエラーメッセージやガイダンス案内などの固定文言は、初回生成時に Amazon S3 などのオブジェクトストレージへ保存し、CDN 経由でキャッシュ配信します。高価な動的ストリーミング API の呼び出しは LLM 生成などの動的メッセージに限定するのが効果的です。

参考文献