Vegaでクローズドキャプションと字幕を実装する方法
この記事では、W3C準拠のテキストトラックAPIを使用して、Vegaアプリにクローズドキャプションと字幕を実装します。クローズドキャプションは音声の書き起こしを提供し、障がいを持つ視聴者や周囲に騒音がある場合に役立ちます。字幕は、会話をさまざまな言語に翻訳します。テキストトラックは、大きく次の2つのカテゴリーに分けられます。
- 帯域内: メディアセグメント内で配信されるテキストトラック。たとえば、CEAキャプションやMP4テキストトラック(個別のトラックとしてのWebVTT/TTML)があります。
- 帯域外(OOB): メディアストリームとは別のファイルとして配信されるテキストトラック。ABRストリーミングでは、これらのファイルはプレイリストまたはマニフェストファイルで参照されます。場合によっては、キャプションファイルがデータベースを通じてメディアコンテンツに関連付けられ、マニフェストファイルには記述されないこともあります。
前提条件
- Vega開発環境がセットアップされていること
- React NativeとTypeScriptに関する基本的な知識
@amazon-devices/react-native-w3cmediaパッケージバージョン2.1.14以降- Vega SDK v0.10以降
必要な権限の追加
アクセシビリティ権限を追加するために、manifest.tomlに以下を追加します。
[[wants.privilege]]
id = "com.amazon.devconf.privilege.accessibility"
VTTCueポリフィルのインストール
@amazon-devices/react-native-w3cmediaパッケージには、VTTCueのポリフィルが用意されています。これはTextTrackCueインターフェイスの実装です。
アプリの初期化中にポリフィルをインストールします。
import { VTTCue } from '@amazon-devices/react-native-w3cmedia';
// ポリフィルクラス内:
static install() {
console.log('W3CMediaポリフィルをインストールします');
global.window.VTTCue = global.VTTCue = VTTCue;
if(!window.VTTCue) {
console.log("VTTCueのポリフィルは適用されませんでした");
}
}
KeplerCaptionsViewコンポーネントの追加
KeplerCaptionsViewコンポーネントは、クローズドキャプションと字幕を画面上にレンダリングします。このコンポーネントは、VideoPlayerコンポーネントやAudioPlayerコンポーネントを使用してプレバッファリングモードで動作している場合に使用します。
コンポーネントをレンダーツリーに追加します。
import { KeplerCaptionsView } from '@amazon-devices/react-native-w3cmedia';
const onCaptionViewCreated = (captionsHandle: string): void => {
videoPlayer.setCaptionViewHandle(captionsHandle);
}
// コンポーネントのreturnステートメント内:
<View style=>
<KeplerCaptionsView
onCaptionViewCreated={onCaptionViewCreated}
show={true}
style=
/>
</View>
キャプションをレンダリングするには、showプロパティをtrueに設定する必要があります。
アプリで解析したキャプションのテキストトラックの追加
キャプションデータの取得と解析をアプリで直接処理する場合は、アプリのHTMLMediaElementの実装にテキストトラックを追加し、そのトラックにVTTCueオブジェクトを設定します。このアプローチは、ソースが帯域内か帯域外かにかかわらず、アプリで解析するすべてのテキストトラックに適用できます。Shaka PlayerなどのJavaScriptプレーヤーを使用する場合は、プレーヤーが内部でトラックの作成を管理するため、この手順に従う必要はありません。
const textTrack = videoPlayer.addTextTrack('subtitles', 'SampleTextTrack', 'en');
テキストトラックへのキューの追加
キャプションデータを解析したら、VTTCueを使用してキューをテキストトラックに追加します。
const vttCue = new VTTCue(startTime, endTime, payload);
vttCue.lineAlign = lineAlign;
vttCue.positionAlign = positionAlign;
if (size) {
vttCue.size = size;
}
textTrack.addCue(vttCue);
ネイティブに解析されたテキストトラックのリッスン
プラットフォームは、CEA 608や708などの帯域内字幕を自動的に検出します。SourceBufferにメディアセグメントが追加されている場合、プラットフォームはこれらの字幕をネイティブレイヤーで解析します。これはJavaScriptベースの解析よりも効率的です。テキストトラックの検出時に通知を受け取るために、addtrackイベントに登録します。
videoPlayer.textTracks.addEventListener("addtrack", onTextTrackAdded);
const onTextTrackAdded = (event: Event): void => {
const textTrackList: TextTrackList | undefined | null = media.current?.textTracks;
if(textTrackList === undefined || textTrackList === null) {
return;
}
for (let i = 0; i < textTrackList.length; i++) {
const textTrack = textTrackList[i];
console.log(`text track id = ${textTrack.id} \
kind = ${textTrack.kind} \
language = ${textTrack.language} \
label = ${textTrack.label} \
mode = ${textTrack.mode}`);
}
}
キャプションファイルのURLを含むテキストトラックの追加
アプリに解析機能がなく、キャプションファイルのURLだけがある場合は、プラットフォームで既知の字幕形式の取得、解析、レンダリングを行うことができます。テキストトラックを追加するときに、キャプションファイルのURLとそのMIMEタイプを渡します。
このアプローチはW3Cに準拠せず、推奨される方法でもなく、廃止される予定となっています。可能な場合は、代わりにアプリ側で解析するか、JavaScriptプレーヤーベースの解析を使用してください。
const textTrack = videoPlayer.addTextTrack("subtitles", 'SampleTextTrack', 'en',
contentUri, contentMimeType);
contentUriとcontentMimeTypeの各パラメーターは、W3Cの標準パラメーターではありません。
次のMIMEタイプがサポートされます。
application/ttml+xmltext/vttapplication/x-subtitleapplication/x-subtitle-samiapplication/x-subtitle-tmplayerapplication/x-subtitle-mpl2application/x-subtitle-dksapplication/x-subtitle-qttextapplication/x-subtitle-lrcapplication/x-subtitle-vtt
テキストトラックの選択と表示
テキストトラックを画面上にレンダリングするには、そのモードをshowingに設定します。
textTrack.mode = 'showing';
デフォルトでは、テキストトラックはモードがhiddenに設定された状態で追加されます。
ShakaPlayerを使用したキャプションの自動解析
ShakaPlayerは、マニフェストファイルとメディアセグメントからキャプションを自動的に解析してレンダリングできます。ShakaPlayerを使用する場合は、プレーヤーが内部でテキストトラックの作成とキューの管理を処理するため、開発者が手動でaddTextTrack()やaddCue()を呼び出す必要はありません。
ShakaPlayerを構成して、テキストトラックのレンダリングを有効にします。
shakaPlayer.configure({
autoShowText: shaka.config.AutoShowText.ALWAYS,
});
コンテンツを読み込んだ後、テキストトラックの表示状態をtrueに設定してキャプションを表示します。
async load(content: any) {
await shakaPlayer.load(content.uri);
shakaPlayer.setTextTrackVisibility(true);
}
Vega SDK v0.21以降と、shaka-rel-v4.6.18-r2.5.tar.gz以降のShakaPlayerパッチを使用していることを確認してください。
実装のテスト
アプリをビルドし、Fire TVデバイスまたはエミュレーターで実行します。
- ビデオ再生の画面に移動します。
- キャプションを含むメディアの再生を開始します。
- 画面にキャプションが表示されることを確認します。
- 複数のキャプショントラックがある場合は、異なるトラック間の切り替えをテストします。
既知の制限事項
- 縦向きの字幕のレンダリングはサポートされません。
const cue = new VTTCue(startTime, endTime, text); cue.vertical = ""; // "rl"や"lr"はサポートされません。 - カスタムサイズのキューウィンドウはサポートされません。キャプションウィンドウのサイズは自動だけです。
const cue = new VTTCue(startTime, endTime, text); cue.size = 20; // カスタムのキューサイズはサポートされません。 - VTTCueに位置が指定されていない場合、字幕とキャプションは画面の下部に重ならないように配置されます。
- 同じプロセス内で複数の
KeplerCaptionsViewインスタンスを使用することはサポートされません。 - CEA 708ネイティブトラックは最大で1つしかサポートされません。
- ネイティブキャプションのロールアップモードはサポートされません。詳細については、Rollup Captions(英語のみ)を参照してください。
- ネイティブのキャプショントラックには言語メタデータは含まれていません。言語パラメーターには、CC1、CC2、CC3、CC4のようなチャネル識別子が含まれています。
- VTTRegionはサポートされません。
- 字幕とキャプションのCSSスタイルはサポートされません。
よくある質問(FAQ)
- Q: プラットフォームがCEA 608/708のネイティブ解析をサポートしている場合、アプリで帯域内キャプションを解析する必要はありますか?
- 理想的には、CEA 608/708のネイティブ解析を有効にし、JavaScriptベースの解析は避けることをお勧めします。アプリでキャプションを解析する必要があるのは、ネイティブ解析が機能しない場合か、アプリでキャプションテキストにアクセスする必要がある場合だけです。
- Q: ShakaPlayer APIで、ネイティブに解析されたキャプショントラックが報告されません。これらをアプリで検出するにはどうすればよいですか?
- 次のように、トラックの管理戦略を組み合わせて使用します。
subtitleトラックにはJavaScriptプレーヤーAPI(ShakaPlayerなど)使用します。captionトラックにはW3C Media APIのVideoPlayer(MediaElement)を使用します。
次の例では、このアプローチを使用して、使用可能なすべてのテキストトラックを照会します。
getTextTracks(): TextTrackInfo[] { let textTrackInfoList: TextTrackInfo[] = []; if (this.player) { let shakaTextTrackList = this.player.getTextTracks(); for (let track of shakaTextTrackList) { textTrackInfoList.push({ id: 'shaka:' + track.id.toString(), kind: track.kind, language: track.language, label: track.label, mode: (track.active === true ? 'showing' : 'hidden'), playerTrackData: ({ type: 'shaka', track: track }), }); } } if (this.mediaElement) { let nativeTextTrackList = this.mediaElement.textTracks; for (let track of nativeTextTrackList) { if (track.label == 'Shaka Player TextTrack') { continue; } textTrackInfoList.push({ id: 'native:' + track.id.toString(), kind: track.kind, language: track.language, label: track.label, mode: track.mode, playerTrackData: ({ type: 'native', track: track }), }); } } return textTrackInfoList; } - Q: テキストトラックを有効または無効にするにはどうすればよいですか?
- 上記と同じように、トラックの管理戦略を組み合わせて使用します。次の例は、テキストトラックを選択する方法を示しています。
setTextTrack(newTrack: TextTrackInfo | null, currTrack: TextTrackInfo | null): void { if (currTrack) { if (currTrack.playerTrackData.type == 'native') { currTrack.playerTrackData.track.mode = 'hidden'; } else if (currTrack.playerTrackData.type == 'shaka') { this.player?.setTextTrackVisibility(false); } } if (newTrack) { if (newTrack.playerTrackData.type == 'native') { newTrack.playerTrackData.track.mode = 'showing'; } else if (newTrack.playerTrackData.type == 'shaka') { this.player?.selectTextTrack(newTrack.playerTrackData.track); this.player?.setTextTrackVisibility(true); } } } - Q: JavaScriptプレーヤーによるキャプション解析を有効にすると、重複するテキストトラックが報告されます。どうすればこれを回避できますか?
- ネイティブのキャプション解析を使用する場合は、テキストトラックの重複を防ぐために、JavaScriptプレーヤーの帯域内キャプションパーサーを無効にしてください。
ShakaPlayerによる帯域内キャプションの解析を無効にするには、メディアセグメントのキャプションパーサーの登録を解除します。
shaka.media.ClosedCaptionParser.unregisterParser('video/mp4'); shaka.media.ClosedCaptionParser.unregisterParser('video/mp2t');代わりにJavaScriptで帯域内解析を行う場合は、JavaScriptプレーヤーAPIを使用してテキストトラックを管理します。
- 利用可能なテキストトラックを取得するには、
getTextTracks()を使用します。 - テキストトラックを有効または無効にするには、
setTextTrackVisibility(isVisible)を使用します。
- 利用可能なテキストトラックを取得するには、
- Q: 字幕とキャプションのスタイル設定はサポートされていますか?
- はい。次のスタイルタグがサポートされます。
- クラススパン:テキストの色とテキストの背景色
- 斜体スパン
- 太字スパン
- 下線スパン
詳細については、WebVTT仕様(英語のみ)を参照してください。
- Q: VTTRegionはサポートされていますか?
- VTTRegionはサポートされません。
- Q: 字幕とキャプションのCSSスタイルはサポートされていますか?
- 字幕とキャプションのCSSスタイルはサポートされません。
関連コンテンツ
- W3Cメディアプレーヤーのドキュメント
- W3C TextTrack仕様(英語のみ)
- WebVTT仕様(英語のみ)
Last updated: 2026年6月2日

