メインコンテンツまでスキップ

音声の文字起こしと音声生成

AIモデルを使用して音声ファイルをテキストに文字起こしし、テキストから読み上げ音声を生成します。

AI Audio を使う理由

アプリケーションで音声を扱う必要があることがあります。要約したい会議の録音、検索したいボイスメモ、あるいは読み上げたい文章の回答などです。これをゼロから構築する場合、音声プロバイダーとの直接連携、APIキー管理、ファイルアップロード処理、フォーマット変換コードの実装が必要になります。

Squid AI Audio は、文字起こし(transcription)とテキスト読み上げ(text-to-speech)の両方を、単一のバックエンド呼び出しで提供します。

Backend code
// 音声ファイルをテキストに文字起こし
const text = await this.squid.ai().audio().transcribe(audioFile, {
modelName: 'whisper-1',
});

// テキストから音声を生成
const speechFile = await this.squid.ai().audio().createSpeech('Welcome to Squid', {
modelName: 'tts-1',
voice: 'nova',
});

概要

Squid AI Audio は、OpenAI の Whisper(speech-to-text)および TTS(text-to-speech)モデルを単一の API の背後でラップします。バックエンドからメソッドを呼び出すだけで、Squid が認証、ファイルアップロード、フォーマット変換、レスポンスのデコードを処理します。

AI Audio を使うべきとき

ユースケース推奨
話し言葉の音声を検索可能なテキストに変換するtranscribe()
合成音声でテキストを読み上げるcreateSpeech()
AI agent のチャット体験に音声入力を組み込むAI chat widgetenable-transcription フラグを使用
AI agent 用のカスタム音声voice options 付き agents を使用

仕組み

  1. バックエンドサービスから this.squid.ai().audio().transcribe() または .createSpeech() を呼び出します
  2. Squid バックエンドがリクエストを認証し、アプリケーション設定から OpenAI API key を参照して呼び出しを転送します
  3. 文字起こしでは、音声ファイルがモデルにストリーミングされ、文字起こし結果がテキストとして返ります
  4. 音声生成では、モデルがバイナリ音声を返し、Squid がそれを File オブジェクト(TypeScript)または bytes(Python)にラップします

クイックスタート

前提条件

  • squid init で初期化された Squid backend プロジェクト
  • @squidcloud/backend パッケージ(TypeScript)または squidcloud-backend パッケージ(Python)
  • Squid Console で、アプリケーションの AI provider として OpenAI が設定済みであること

ステップ 1: 音声呼び出しをラップする executable を作成する

音声操作には Squid リソースに対する admin アクセスが必要なため、バックエンドで実行する必要があります。クライアントが安全に呼び出せるように、executable にラップしてください。

Backend code
import { executable, SquidFile, SquidService } from '@squidcloud/backend';

export class AudioService extends SquidService {
@executable()
async transcribeAudio(audio: SquidFile): Promise<string> {
this.assertIsAuthenticated();

// SquidFile には、クライアントからの元のファイル名と MIME type が含まれます。
// audio client が OpenAI にストリーミングできるよう、ネイティブの File に変換します。
const file = new File([audio.data], audio.originalName, { type: audio.mimetype });

return this.squid.ai().audio().transcribe(file, {
modelName: 'whisper-1',
});
}
}

ステップ 2: バックエンドをデプロイする、またはローカルで実行する

squid start

クラウドにデプロイする場合は、deploying your backend を参照してください。

ステップ 3: クライアントから executable を呼び出す

Client code
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
const audioFile = fileInput.files![0];

const transcript = await squid.executeFunction('transcribeAudio', audioFile);
console.log(transcript);

認証と設定

音声メソッドには、admin アクセスを持つ認証済みの Squid client が必要です。これは transcribe()createSpeech() の両方に当てはまります。推奨パターンは 2 つあります。

  1. 呼び出しを executables にラップする。 これが標準パターンです。executable は admin context でバックエンド上で実行され、クライアントが基盤となる API key を見ることはありません。executables を参照してください。
  2. 特権を持つバックエンドサービスから呼び出す。 triggers、schedulers、webhooks などのバックエンド専用エントリポイントは、すでに backend privileges で実行されるため、そこから音声メソッドを直接呼び出せます。

未認証のブラウザクライアントからの呼び出しは UNAUTHORIZED エラーで拒否されます。

OpenAI は Squid app の external service として有効化されている必要があります。API key は Squid Console に保存され、audio client はリクエスト時にそれを参照します。

コアコンセプト

文字起こしモデル

Squid は 3 つの OpenAI 文字起こしモデルをサポートします。

モデル注記
whisper-1デフォルト。最も広いレスポンス形式をサポートし、コストが低いです。
gpt-4o-transcribe高精度。JSON のみを返します。
gpt-4o-mini-transcribegpt-4o-transcribe より小さく安価。JSON のみを返します。

文字起こしオプション

AiAudioTranscribeOptionsmodelName による discriminated union です。すべてのバリアントは、次の共通のベースフィールドを共有します。

フィールド必須説明
modelNamestringYesサポートされている文字起こしモデルのいずれか
temperaturenumberNoサンプリング温度
promptstringNo文字起こしを誘導するための任意テキスト(例: 固有名詞)

whisper-1 は追加で以下をサポートします。

フィールド説明
responseFormatstring'json', 'text', 'srt', 'verbose_json', 'vtt' のいずれか。既定は 'json'

gpt-4o-transcribegpt-4o-mini-transcribe'json' のみを返します。

このメソッドは、モデルの内部的なレスポンス形式に関わらず、常にプレーンな文字列を返します。

音声生成モデル

モデル注記
tts-1高速、低レイテンシー、忠実度はやや低め
tts-1-hd高忠実度、低速
gpt-4o-mini-tts新しい GPT-4o ファミリーの TTS モデル

音声生成オプション

AiAudioCreateSpeechOptions フィールド:

フィールド必須説明
modelNamestringYesサポートされている TTS モデルのいずれか
voicestringNo'alloy', 'ash', 'ballad', 'coral', 'echo', 'fable', 'onyx', 'nova', 'sage', 'shimmer', 'verse' のいずれか。既定は 'alloy'
responseFormatstringNo音声コンテナ形式。'mp3', 'opus', 'aac', 'flac', 'wav', 'pcm' のいずれか。既定は 'mp3'
instructionsstringNo話し方スタイルの自由形式ガイダンス(例: "speak slowly and clearly")
speednumberNo再生速度の倍率。既定は 1.0

戻り値の形

メソッドTypeScript の戻り値Python の戻り値
transcribe()Promise<string>str
createSpeech()Promise<File>bytes

TypeScript では、ファイルの MIME type と拡張子は responseFormat から推論されます。たとえば responseFormat: 'mp3' のリクエストでは、MIME type が audio/mpegaudio.mp3 という名前のファイルが返ります。

コード例

クライアントがアップロードした音声を文字起こしする

Backend code
import { executable, SquidFile, SquidService } from '@squidcloud/backend';

export class AudioService extends SquidService {
@executable()
async transcribeRecording(audio: SquidFile, languageHint?: string): Promise<string> {
this.assertIsAuthenticated();

const file = new File([audio.data], audio.originalName, { type: audio.mimetype });

return this.squid.ai().audio().transcribe(file, {
modelName: 'whisper-1',
// prompt を使って、正しい綴りや用語へモデルをバイアスします。
prompt: languageHint,
});
}
}

読み上げ音声を生成してクライアントに返す

この例では、テキストから MP3 ファイルを作成し、クライアントが再生できるよう base64 として返します。

Backend code
import { executable, SquidService } from '@squidcloud/backend';

export class SpeechService extends SquidService {
@executable()
async narrate(text: string): Promise<{ base64: string; mimeType: string }> {
this.assertIsAuthenticated();

const audioFile = await this.squid.ai().audio().createSpeech(text, {
modelName: 'tts-1-hd',
voice: 'nova',
responseFormat: 'mp3',
speed: 1.0,
});

// File を base64 に変換して、JSON 経由でクライアントに返せるようにします。
const buffer = Buffer.from(await audioFile.arrayBuffer());
return {
base64: buffer.toString('base64'),
mimeType: audioFile.type,
};
}
}

生成した音声を長期保存したい場合は、インラインで返すのではなく、結果を storage connector にアップロードしてください。

往復: 音声を生成してから、それを文字起こしで戻す

統合テストやサニティチェックに便利なパターンです。

Backend code
const speechFile = await this.squid.ai().audio().createSpeech('The quick brown fox jumps over the lazy dog.', {
modelName: 'tts-1',
});

const transcript = await this.squid.ai().audio().transcribe(speechFile, {
modelName: 'whisper-1',
});

console.log(transcript); // "The quick brown fox jumps over the lazy dog."

エラーハンドリング

よくあるエラー

エラー原因解決策
UNAUTHORIZED音声呼び出しが非 admin context(例: バックエンドなしのブラウザ)から発生した呼び出しを executable にラップするか、バックエンドコードから呼び出す
Unsupported audio modelmodelName がサポート一覧にない一覧にある文字起こしまたは TTS モデルのいずれかを使用する
OpenAI external services are disabledアプリケーションで OpenAI が有効化されていないSquid Console で OpenAI を有効化し、API key を設定する
File too largeアップロードした音声が上流プロバイダーの制限を超えているWhisper は 25 MB のアップロード制限があります。このサイズを超える音声は分割または圧縮してください。

呼び出し前に入力を検証する

OpenAI Whisper API は 25 MB を超えるファイルを拒否します。上流のエラーを待つのではなく、executable 内で大きすぎるアップロードを拒否してください。

Backend code
@executable()
async transcribeAudio(audio: SquidFile): Promise<string> {
this.assertIsAuthenticated();

const MAX_BYTES = 25 * 1024 * 1024;
if (audio.size > MAX_BYTES) {
throw new Error('Audio file exceeds 25 MB. Split or compress before transcribing.');
}

if (!audio.mimetype.startsWith('audio/')) {
throw new Error('Only audio files are accepted');
}

const file = new File([audio.data], audio.originalName, { type: audio.mimetype });
return this.squid.ai().audio().transcribe(file, { modelName: 'whisper-1' });
}

ベストプラクティス

  1. 音声呼び出しは常に executables にラップしてください。 音声メソッドは admin アクセスを必要とします。ブラウザから直接公開すると API key の漏えいにつながり、認証もバイパスされます。
  2. transcribe() を呼ぶ前に、ファイルサイズと MIME type を検証してください。上流プロバイダーにも制限があり、不正な入力を早期に弾くことでユーザーにより良いエラーメッセージを返せます。
  3. 文字起こしでは prompt フィールドを使って、ドメイン用語、固有名詞、想定言語などを入力してください。精度改善のための最も安価な方法です。
  4. ストリーミングや低レイテンシー UX には tts-1、レイテンシーより品質が重要な オフライン資産には tts-1-hd を選んでください。
  5. 音声 executables に rate limiting を適用してください。音声生成と文字起こしはいずれも有償 API クォータを消費します。
  6. 生成した音声をキャッシュしてください。同じ入力テキストに対する text-to-speech は、同じ voice であれば常に同じ出力になるため、キャッシュによりクォータを節約できます。

参照

  • Executables - 音声呼び出しをラップしてクライアントから呼べるようにする
  • AI agent - 音声入力と音声出力を備えた AI agent を構築する
  • AI chat widget - chat widget は enable-transcription で音声入力を公開します
  • Rate and quota limiting - 音声 executables を悪用から保護する