ANTIGRAVITY LABEN
記事一覧/連携・プラグイン
連携・プラグイン/2026-05-04中級

ElevenLabs × Antigravity でリアルな音声AIアプリを開発する実践ガイド

ElevenLabsのAPIをAntigravityで組み込み、テキスト→音声・音声→テキスト変換を実装する実践チュートリアル。個人開発者が音声AIアプリを最短で完成させるための具体的なコード例と費用感を解説します。

ElevenLabs音声AI2TTSSTTAPI連携2個人開発90

「自分のアプリに人間らしい声を追加したい」と思ったことはありませんか? テキスト読み上げ(TTS)機能を実装しようとすると、ブラウザのネイティブ音声は機械的すぎる、かといってGoogle TTSやAmazon Pollyは設定が複雑で費用感が掴みにくい、という壁にぶつかりがちです。

私がいくつかのアプリで試した中で、ElevenLabs はその問題を最もシンプルに解決してくれました。APIの設計がきれいで、Antigravity に依頼すれば基本実装まで数時間で仕上がります。ここでは実際に動いたコードをそのままお見せしながら、音声AIアプリ開発の入り口をご案内します。

ElevenLabsとAntigravityの相性が良い理由

ElevenLabsは「人間らしい音声合成」を武器にしたAI音声プラットフォームです。2026年現在、無料プランでも月10,000文字まで使えるため、個人開発の試作フェーズは費用ゼロで進められます。

Antigravityとの相性が良い点は、ElevenLabsの公式PythonおよびTypeScript SDKのドキュメントが整備されていることです。Antigravity に「ElevenLabsのPython SDKでストリーミングTTSを実装して」と依頼すると、SDKの最新バージョンに合ったコードをほぼ一発で生成してくれます。

費用の目安をまとめておきます(2026年5月時点):

  • Starter: $5/月、30,000文字/月
  • Creator: $22/月、100,000文字/月
  • Pro: $99/月、500,000文字/月

アプリのコアに音声機能を組み込む場合、ユーザー1人あたりの文字数を試算しておくと計画が立てやすいです。1回の会話が平均200文字なら、Creatorプランで月500会話まで対応できる計算です。

プロジェクトのセットアップ

まずはAntigravityに次のプロンプトで初期構成を依頼します。

ElevenLabs APIを使ったPython + FastAPIのバックエンドを作成してください。
機能: テキスト→音声変換(TTS)のストリーミングエンドポイント
環境変数: ELEVENLABS_API_KEY
依存関係のrequirements.txtも含めてください

Antigravityが生成した構成をベースに、次のディレクトリ構成で進めます。

voice-app/
├── backend/
│   ├── main.py
│   ├── requirements.txt
│   └── .env
└── frontend/
    ├── app/
    │   └── page.tsx
    └── package.json

依存関係のインストールは Antigravity のターミナルで直接実行できます。

# バックエンド
pip install elevenlabs fastapi uvicorn python-dotenv
 
# フロントエンド(Next.js)
npm install

テキスト→音声変換(TTS)の実装

ElevenLabs Python SDK を使ったバックエンドの実装です。ポイントはストリーミング対応にすることで、長いテキストでも最初の音声が即座に再生されます。

# backend/main.py
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from elevenlabs.client import ElevenLabs
from pydantic import BaseModel
import os
from dotenv import load_dotenv
 
load_dotenv()
 
app = FastAPI()
 
# CORS設定(開発環境用)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000"],
    allow_methods=["*"],
    allow_headers=["*"],
)
 
client = ElevenLabs(api_key=os.getenv("ELEVENLABS_API_KEY"))
 
class TTSRequest(BaseModel):
    text: str
    voice_id: str = "JBFqnCBsd6RMkjVDRZzb"  # "George" - デフォルト音声
 
@app.post("/api/tts")
async def text_to_speech(request: TTSRequest):
    """
    テキストをストリーミング音声に変換するエンドポイント。
    フロントエンドはAudio APIでこのストリームを再生する。
    """
    def audio_stream():
        # generate()はジェネレーターを返す。チャンク単位で音声データが届く
        audio_generator = client.generate(
            text=request.text,
            voice=request.voice_id,
            model="eleven_turbo_v2_5",  # 低遅延モデル(個人開発に最適)
            stream=True,
        )
        for chunk in audio_generator:
            if chunk:
                yield chunk
 
    return StreamingResponse(
        audio_stream(),
        media_type="audio/mpeg",
        headers={"Transfer-Encoding": "chunked"},
    )

実行して動作確認します。

uvicorn main:app --reload
# → http://localhost:8000 で起動
 
# 動作テスト(curl)
curl -X POST http://localhost:8000/api/tts \
  -H "Content-Type: application/json" \
  -d '{"text": "こんにちは、Antigravity Labです"}' \
  --output test.mp3
 
# test.mp3 を再生して音声が生成されていれば成功

期待する結果は、日本語テキストが自然な英語アクセントで読み上げられたMP3ファイルです。日本語ネイティブ発音が必要な場合は voice_id を日本語音声に変更します。

フロントエンドでの音声再生

Next.js フロントエンドで、バックエンドのストリームをリアルタイム再生する実装です。

// app/page.tsx
"use client";
 
import { useState } from "react";
 
export default function VoiceApp() {
  const [text, setText] = useState("");
  const [isPlaying, setIsPlaying] = useState(false);
  const [error, setError] = useState<string | null>(null);
 
  const handlePlay = async () => {
    if (!text.trim()) return;
    setIsPlaying(true);
    setError(null);
 
    try {
      const response = await fetch("/api/tts", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ text }),
      });
 
      if (!response.ok) {
        throw new Error(`API エラー: ${response.status}`);
      }
 
      // ReadableStream → ArrayBuffer → Blob → Audio
      const audioData = await response.arrayBuffer();
      const audioBlob = new Blob([audioData], { type: "audio/mpeg" });
      const audioUrl = URL.createObjectURL(audioBlob);
 
      const audio = new Audio(audioUrl);
      audio.play();
      audio.onended = () => {
        setIsPlaying(false);
        URL.revokeObjectURL(audioUrl); // メモリ解放を忘れずに
      };
    } catch (err) {
      setError(err instanceof Error ? err.message : "エラーが発生しました");
      setIsPlaying(false);
    }
  };
 
  return (
    <main className="max-w-xl mx-auto p-8">
      <h1 className="text-2xl font-bold mb-4">音声AIデモ</h1>
      <textarea
        className="w-full border rounded p-2 mb-4 h-32"
        placeholder="読み上げるテキストを入力..."
        value={text}
        onChange={(e) => setText(e.target.value)}
      />
      <button
        onClick={handlePlay}
        disabled={isPlaying}
        className="bg-blue-600 text-white px-6 py-2 rounded disabled:opacity-50"
      >
        {isPlaying ? "再生中..." : "▶ 音声再生"}
      </button>
      {error && <p className="text-red-500 mt-2">{error}</p>}
    </main>
  );
}

この実装では URL.revokeObjectURL() でのメモリ解放が重要です。Antigravityに最初に依頼したコードではこの処理が抜けることがありますので、確認してください。

音声→テキスト変換(STT)の実装

ElevenLabs にはScribe(音声→テキスト)機能もあります。マイクで録音したデータをそのまま送れます。

# backend/main.py に追加
from fastapi import UploadFile, File
import tempfile
import os
 
@app.post("/api/stt")
async def speech_to_text(audio: UploadFile = File(...)):
    """
    アップロードされた音声ファイルをテキストに変換する。
    フロントエンドからは MediaRecorder で録音したBlobを送信する。
    """
    # 一時ファイルに保存(ElevenLabs SDKはファイルパスを要求するため)
    with tempfile.NamedTemporaryFile(
        delete=False, suffix=".webm"
    ) as tmp_file:
        content = await audio.read()
        tmp_file.write(content)
        tmp_path = tmp_file.name
 
    try:
        with open(tmp_path, "rb") as f:
            result = client.speech_to_text.convert(
                file=f,
                model_id="scribe_v1",
                language_code="ja",  # 日本語指定で精度が上がる
            )
        return {"text": result.text}
    finally:
        os.unlink(tmp_path)  # 一時ファイルを必ず削除

フロントエンドでは MediaRecorder APIでマイク入力を録音し、このエンドポイントに送信します。Antigravityに「MediaRecorder でマイク録音して /api/stt に送信するReactコンポーネントを作って」と依頼すると、この部分もすぐに実装してもらえます。

APIキーの管理とコスト可視化

個人開発で一番注意したいのは APIキーの漏洩予期しない課金 です。

まず、.env ファイルに書いたAPIキーを絶対にGitにコミットしないようにします。

# .gitignore に追加(Antigravity が自動で提案してくれる場合も多い)
.env
.env.local

ElevenLabsのダッシュボードには使用量モニタリング機能があります。月初にAntigravityに「今月の文字数消費を試算して」と依頼してアラート設定をしておくと、予算超過を事前に防げます。

また、開発中は eleven_turbo_v2_5 モデル(低遅延・低コスト)を使い、本番リリース前に eleven_multilingual_v2(最高品質)に切り替える、という段階的なアプローチが費用を抑えるコツです。

音声UIは画面UIと設計原則が根本的に異なるため、実装と並行して読んでおくと方向性が定まります。

全体を振り返って — まず動くものを作ってみる

今日試せる最初のステップは、「自分のアプリの通知文を音声で読み上げる」という最小構成から始めることです。/api/tts エンドポイントを1つ立ち上げて、ユーザーへのメッセージを音声で届けるところまで実装してみてください。

Antigravityを使えば、ここで紹介したコードをベースに「日本語音声に変更して」「ストリーミングではなくファイル保存に変更して」といった追加依頼で機能を拡張できます。音声AIの可能性は、まずシンプルな実装から体感するのが一番の近道だと思います。

音声とAPIの組み合わせ方については、Antigravity の Gemini Live API 音声エージェント実装ガイド外部APIとのカスタムエージェント連携も参考にしてみてください。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

連携・プラグイン2026-06-09
壁紙アプリの画像配信を解像度バケット方式で組み直す — Antigravity エージェントに変換と検証を任せた運用設計
端末解像度が増えるたびに壁紙アプリの配信は重くなります。1枚の原画を全端末へ配る方式をやめ、解像度バケット+WebP/AVIF+エッジリダイレクトに組み直し、変換と検証を Antigravity エージェントに任せた運用設計を、実際のコードと閾値ごと残しました。
連携・プラグイン2026-05-29
Copilot Studio の Computer-Using Agent を Claude in Chrome の日常運用と並べて見る
Microsoft が Copilot Studio の Computer-Using Agent を一般提供しました。私が AdMob と Crashlytics の毎日の点検に Claude in Chrome を使っている運用と並べて、UI 操作型 AI エージェントの選び方を考えてみます。
連携・プラグイン2026-05-28
Antigravity Background Agent で iOS dSYM 欠落を 6 アプリ分まとめて自動回復した運用記録
Firebase の CocoaPods から SPM への移行後、6 本の iOS 壁紙アプリで Crashlytics の解析率が 0% まで落ちた問題を、Antigravity Background Agent で 4 週間かけて自動回復させた実運用記録です。dSYM の所在追跡から Crashlytics への再アップロードまでを並列処理にまとめた設計を共有します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →