ナレーション
各ページを読み上げ、読み上げ中の文をハイライトする「このページを聞く」プレーヤーです。読者のブラウザの音声、またはビルド時に生成されるニューラル音声を使用します。
ナレーション機能を有効にすると、各ページの説明文の下に このページを聞く プレーヤーが表示されます。読者が再生ボタンを押すと、ページがタイトルから順に読み上げられます。読み上げ中の文はハイライトされ、常に画面内に表示されます。この機能はオプトインです:
export default defineConfig({
narration: true,
});
true を指定すると、読者自身のブラウザの音声でページが読み上げられます。キーもビルドステップも必要ありません。静的ホスティングかどうかにかかわらず、どのホストでも動作します。代わりに生成音声を使う場合は、provider を追加してください。
読み上げる内容
ナレーションは、ページのタイトル、説明文、見出し、段落、リスト項目、カードのテキストを順番に読み上げます。一部のコンポーネントでは、先に短い音声の合図が入ります。これにより、聞き手は次にどのような種類のコンテンツが来るのかを把握できます:
| コンポーネント | 合図 |
|---|---|
| コールアウト | 「注記。」「ヒント。」「警告。」など |
| ステップ | 「ステップ 1。」「ステップ 2。」 |
| タブ | 「macOS タブ。」開いているタブだけでなく、すべてのタブが読み上げられます |
| アコーディオンと Expandable | 「展開可能なセクション。」 |
閉じたセクションや非表示のタブに到達すると、ナレーションはそれを自動で開きます。そのため、ハイライトされるテキストは常に読者の目に見える状態になります。
コードブロック、表、画像、動画、図、数式、型テーブル、ファイルツリー、ライブコンポーネントプレビューはスキップされます。これらは読み上げても意味をなさないためです。
プレーヤーが表示されるのは、聞く価値のある量の文章(おおよそ 50 語)があるページだけです。非常に短いページや、大部分がコードや API フィールドで占められているページには表示されません。
再生
ページの再生中、プレーヤーはヘッダーの下に固定されます。プレーヤーには、再生・一時停止、前の文・次の文への移動、進行状況スライダー、ページ全体の長さに対する経過時間、0.8× から 2× までの速度調整があります。設定した速度は次のページにも引き継がれます。
ページは、読み上げ中の文が画面内に表示されるように自動でスクロールします。読者が別の場所へスクロールすると追従は止まりますが、音声の再生は続きます。読み上げ中の文までスクロールして戻るか、読み上げ箇所を追う を押すと、追従が再開されます。別のページを開くと、ナレーションは停止します。
ブラウザの音声
narration: true の場合、Web Speech API と読者のデバイスにある音声を使ってページを読み上げます。音声はページの言語に合わせて選ばれます。その言語の音声がないブラウザでは、誤ったアクセントで読み上げることを避けるため、プレーヤーは非表示のままになります。
この方法では、準備も費用も必要ありません。ただし、音声の品質はデバイスによって異なります。macOS、iOS、Windows のシステム音声は高品質ですが、一部の Linux ブラウザには音声がほとんど、またはまったく入っていません。
生成音声
provider を渡すと、ビルド時にニューラル音声モデルで音声を生成します。プロバイダーには、アシスタントと同じ gateway() アダプターを使い、音声モデルを指定します:
import { defineConfig } from "blume";
import { gateway } from "blume/ai";
export default defineConfig({
narration: {
provider: gateway({
model: "openai/tts-1-hd",
voice: "alloy",
}),
},
});
blume build は、ビルドされた各ページをプレーヤーとまったく同じ方法で読み取り、文ごとに分割します。そして、Vercel AI Gateway を通じて文ごとに 1 つのクリップを生成します。クリップとページごとの小さなマニフェストは、静的ファイルとして /blume-narration/ 以下に出力されます。そのため、繰り返し再生しても費用はかからず、サーバー上で処理が実行されることもありません。
ビルドは生成を始める前に、必要な新しいクリップの数とその合計文字数をログに出力します。そのため、コストを事前に確認できます:
Generating narration: 214 new clip(s), 15,880 characters, with openai/tts-1-hd
| オプション | デフォルト | 説明 |
|---|---|---|
model |
openai/tts-1-hd |
ゲートウェイの音声モデルです。openai/tts-1、openai/tts-1-hd、fish-audio/s2.1-pro、spacexai/grok-tts のほか、ゲートウェイに掲載されている他のモデルも指定できます。 |
voice |
alloy |
モデルの音声です。 |
instructions |
指示に対応したモデルで、音声の話し方を指定します(例:「教師のように落ち着いて読んでください」)。 | |
apiKeyEnv |
AI_GATEWAY_API_KEY |
ゲートウェイのキーを格納する環境変数です。Vercel では、ビルドの OIDC トークンも使用できます。 |
headers |
すべてのリクエストに付加される静的ヘッダーです。 | |
providerOptions |
AI SDK の generateSpeech にそのまま渡されます。Blume にオプションが用意されていないモデル設定に使います。 |
キャッシュ
クリップは node_modules/.cache/blume/narration にキャッシュされます。キャッシュのキーは、音声の内容を決める要素(文、言語、モデル、音声、指示)です。再ビルド時に費用が発生するのは変更された文だけです。また、複数のページに共通する文は 1 回だけ生成されます。Vercel と Netlify はビルドキャッシュから node_modules を復元するため、デプロイ時には変更された部分だけが再生成されます。その他の CI では、実行間でこのディレクトリをキャッシュしてください。
フォールバック
生成音声は、クリップが存在しない場合にブラウザの音声にフォールバックします:
blume devの場合。blume devは音声を生成しません。生成音声をローカルで確認するには、blume buildとblume previewを実行してください。- ビルド時にキーが設定されていない場合。ビルドは警告を出し、生成をスキップします。
- 生成に失敗した場合。AI SDK がすでにリトライしているため、ビルドは最初に失敗したクリップで停止します。それまでにキャッシュされたクリップはすべて保持されます。
言語
ナレーションは、各ページをそのコンテンツの言語で読み上げます。そのため、国際化されたサイトでは、ロケールごとにその言語の音声で読み上げられます。音声の合図とプレーヤーのラベルは、すべての組み込み UI 言語に翻訳されています。ロケールごとに上書きする場合は、i18n.ui の narration で指定してください。
ページごとに無効にする
ページのフロントマターで narration: false を設定すると、そのページにはプレーヤーが表示されなくなります:
---
title: Changelog
narration: false
---
コンテンツを除外する
要素に data-blume-narration="skip" を追加すると、その要素と内部のすべてのコンテンツがナレーションの対象外になります。Blume が自身の型テーブルやプレビューをスキップしているのもこの仕組みです。独自のコンポーネントやアイランドでも同じように機能します:
<div data-blume-narration="skip">
<PricingCalculator />
</div>
アナリティクス
読者が再生を始めると、プレーヤーは narration_play イベントを送信します。このイベントには engine(audio または browser)とページの path が含まれます。ページが最後まで再生されると、narration_complete イベントを送信します。どちらのイベントも、他のカスタムイベントと同じくアナリティクスアダプターを通じて送信されます。