すべてのプロダクト
Search
ドキュメントセンター

ApsaraVideo VOD:外部字幕の追加方法

最終更新日:Nov 09, 2025

ApsaraVideo Player SDK を使用すると、WebVTT、SRT、および ASS 形式の外部字幕ストリームを追加、解析、レンダリングできます。このソフトウェア開発キット (SDK) は、M3U8 ファイルに埋め込まれた字幕ストリームの解析とレンダリングもサポートしています。このトピックでは、Android および iOS プラットフォームでこの機能を実装する方法について説明します。

重要

このトピックのすべてのコードと実装の詳細については、API-Example プロジェクトを参照し、ベストプラクティスに基づいて適応させてください

具体的な実装については、このトピックのソリューションを使用し、対応する API-Example-Android および API-Example-iOS プロジェクトの ExternalSubtitle モジュールのソースコードを参照してください。

制限事項

  • WebVTT、SRT、および ASS 形式の外部字幕ファイルのみがサポートされています。

レンダリング例

レンダリングのために字幕ストリームをパッケージングするには、「複数字幕のトランスコーディングとパッケージングのベストプラクティス」をご参照ください。

Android での主要な実装

外部字幕のレンダリング

  1. 依存ライブラリをインポートします。

    import com.aliyun.subtitle.SubTitleBase;
    import com.cicada.player.utils.webVtt.VttSubtitleView;
    import com.aliyun.player.IPlayer;
  2. 表示ビューを設定します。

    vttSubtitleView = new VttSubtitleView(getContext());
    vttSubtitleView.setId(R.id.cicada_player_vtt_subtitle);
    
    
    // 字幕の表示位置を設定します。レイアウトの中央に追加します。
    FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.WRAP_CONTENT,
            FrameLayout.LayoutParams.WRAP_CONTENT
    );
    params.gravity = Gravity.CENTER; // レイアウトの中央に追加します。
    
    // VTT 字幕ビューをルートレイアウトビューに追加します。
    mRootFrameLayout.addView(mVttSubtitleView, params);
  3. コールバックを設定します。

    // 次の例では、mVideoListPlayer は listPlayer です。aliPlayer を使用する場合もプロセスは同じです。
    // 1. OnSubtitleDisplayListener を設定します。
    mVideoListPlayer.setOnSubtitleDisplayListener(new IPlayer.OnSubtitleDisplayListener() {
        @Override
        public void onSubtitleExtAdded(int trackIndex, String url) {
          // 単一の VTT ファイルの追加のみをテストしているため、VTT ファイルが追加された直後に字幕トラックを選択します。
            mVideoListPlayer.selectExtSubtitle(trackIndex, true);
        }
    
        @Override
        public void onSubtitleShow(int trackIndex, long id, String data) {
            if (vttSubtitleView != null) {
                vttSubtitleView.show(id, data);
            }
        }
    
        @Override
        public void onSubtitleHide(int trackIndex, long id) {
            if (vttSubtitleView != null) {
                vttSubtitleView.dismiss(id);
            }
        }
    
        @Override
        public void onSubtitleHeader(int trackIndex, String header) {
            if (vttSubtitleView != null) {
                vttSubtitleView.setVttHeader(header);
            }
        }
    });
    
    // 2. VideoSizeChangedListener を設定します。これは必須のステップです。データは vttSubtitleView に渡す必要があります。
    mVideoListPlayer.setOnVideoSizeChangedListener(new IPlayer.OnVideoSizeChangedListener() {
        @Override
        public void onVideoSizeChanged(int width, int height) {
            int viewWidth = getWidth();
            int viewHeight = getHeight();
            IPlayer.ScaleMode mode = mVideoListPlayer.getScaleMode();
            SubTitleBase.VideoDimensions videoDimensions = SubTitleBase.getVideoDimensionsWhenRenderChanged(width, height, viewWidth, viewHeight, mode);
            vttSubtitleView.setVideoRenderSize(videoDimensions.videoDisplayWidth, videoDimensions.videoDisplayHeight);
        }
    });
  4. プレーヤーが prepare/moveTo/moveToNext/moveToPrev 操作を実行した後、表示ビューをクリアします。

    source = getSource(someParams); // 擬似コード
    
    mVideoListPlayer.moveTo(mCurrentUUID + "");
    if (vttSubtitleView != null) {
        vttSubtitleView.clearAll();
    }
    
    if (!source.getExtSubtitleUrl().isEmpty()) {
        mCurrentExtSubtitle = source.getExtSubtitleUrl(); // 外部字幕の URL を取得します。
    }
  5. プレーヤーの onPrepared コールバックが呼び出された後、字幕ファイルを追加します。

    // 現在、addExtSubtitle はプレーヤーの onPrepared コールバックが呼び出された後にのみ呼び出すことができます。
    mVideoListPlayer.addExtSubtitle(mCurrentExtSubtitle);

M3U8 パッケージ字幕のレンダリング

重要

M3U8 パッケージ字幕と外部字幕を一緒にレンダリングしないでください。

  1. 依存ライブラリをインポートします。

    import com.aliyun.subtitle.SubTitleBase;
    import com.cicada.player.utils.webVtt.VttSubtitleView;
    import com.aliyun.player.IPlayer;
  2. 表示ビューを設定します。

    vttSubtitleView = new VttSubtitleView(getContext());
    vttSubtitleView.setId(R.id.cicada_player_vtt_subtitle);
    
    
    // 字幕の表示位置を設定します。レイアウトの中央に追加します。
    FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.WRAP_CONTENT,
            FrameLayout.LayoutParams.WRAP_CONTENT
    );
    params.gravity = Gravity.CENTER; // レイアウトの中央に追加します。
    
    // VTT 字幕ビューをルートレイアウトビューに追加します。
    mRootFrameLayout.addView(mVttSubtitleView, params);
  3. コールバックを設定します。

    // 次の例では、mVideoListPlayer は listPlayer です。aliPlayer を使用する場合もプロセスは同じです。
    // 1. OnSubtitleDisplayListener を設定します。
    mVideoListPlayer.setOnSubtitleDisplayListener(new IPlayer.OnSubtitleDisplayListener() {
        @Override
        public void onSubtitleExtAdded(int trackIndex, String url) {
          // 単一の VTT ファイルの追加のみをテストしているため、VTT ファイルが追加された直後に字幕トラックを選択します。
            mVideoListPlayer.selectExtSubtitle(trackIndex, true);
        }
    
        @Override
        public void onSubtitleShow(int trackIndex, long id, String data) {
            if (vttSubtitleView != null) {
                vttSubtitleView.show(id, data);
            }
        }
    
        @Override
        public void onSubtitleHide(int trackIndex, long id) {
            if (vttSubtitleView != null) {
                vttSubtitleView.dismiss(id);
            }
        }
    
        @Override
        public void onSubtitleHeader(int trackIndex, String header) {
            if (vttSubtitleView != null) {
                vttSubtitleView.setVttHeader(header);
            }
        }
    });
    
    // 2. VideoSizeChangedListener を設定します。これは必須のステップです。データは vttSubtitleView に渡す必要があります。
    mVideoListPlayer.setOnVideoSizeChangedListener(new IPlayer.OnVideoSizeChangedListener() {
        @Override
        public void onVideoSizeChanged(int width, int height) {
            int viewWidth = getWidth();
            int viewHeight = getHeight();
            IPlayer.ScaleMode mode = mVideoListPlayer.getScaleMode();
            SubTitleBase.VideoDimensions videoDimensions = SubTitleBase.getVideoDimensionsWhenRenderChanged(width, height, viewWidth, viewHeight, mode);
            vttSubtitleView.setVideoRenderSize(videoDimensions.videoDisplayWidth, videoDimensions.videoDisplayHeight);
        }
    });
  4. プレーヤーが prepare/moveTo/moveToNext/moveToPrev 操作を実行した後、表示ビューをクリアします。

    source = getSource(someParams); // 擬似コード
    
    mVideoListPlayer.moveTo(mCurrentUUID + "");
    if (vttSubtitleView != null) {
        vttSubtitleView.clearAll();
    }
    
    if (!source.getExtSubtitleUrl().isEmpty()) {
        mCurrentExtSubtitle = source.getExtSubtitleUrl(); // 外部字幕の URL を取得します。
    }
  5. onTrackReady コールバックを設定して、サブストリーム情報を取得します。

    mAliPlayer.setOnTrackReadyListener(new IPlayer.OnTrackReadyListener() {
        @Override
        public void onTrackReady(MediaInfo mediaInfo) {
            List<TrackInfo>  trackInfos = mediaInfo.getTrackInfos();
            for (TrackInfo trackInfo : trackInfos) {
                if (trackInfo.getType() == TrackInfo.Type.TYPE_SUBTITLE) {
                // TODO 
                }
            }
        }
    });
  6. プレーヤーの onPrepared コールバックが呼び出された後、selectTrack を呼び出して字幕トラックを切り替えます。

    // index はターゲット字幕ストリームの TrackIndex です。
    mAliPlayer.selectTrack(index);

iOS での主要な実装

外部字幕のレンダリング

  1. コールバックを設定します。

    /**
     @brief 外部字幕が追加されます。
     @param player プレーヤーポインター。
     @param trackIndex 表示する字幕トラックのインデックス。
     @param URL 字幕 URL。
     */
    - (void)onSubtitleExtAdded:(AliPlayer*)player trackIndex:(int)trackIndex URL:(NSString *)URL {
        NSLog(@"onSubtitleExtAdded: %@, trackIndex: %d", URL, trackIndex);
        [self.listPlayer selectExtSubtitle:trackIndex enable:YES];
    }
  2. プレーヤーの onPrepared コールバックが呼び出された後、字幕ファイルを追加します。

    if (self.currentModel.extSubtitleUrl != Nil) {
        [self.listPlayer addExtSubtitle:self.currentModel.extSubtitleUrl];
    }

M3U8 パッケージ字幕のレンダリング

重要

M3U8 パッケージ字幕と外部字幕を一緒にレンダリングしないでください。

  1. コールバックを設定します。

    /**
     @brief 外部字幕が追加されます。
     @param player プレーヤーポインター。
     @param trackIndex 表示する字幕トラックのインデックス。
     @param URL 字幕 URL。
     */
    - (void)onSubtitleExtAdded:(AliPlayer*)player trackIndex:(int)trackIndex URL:(NSString *)URL {
        NSLog(@"onSubtitleExtAdded: %@, trackIndex: %d", URL, trackIndex);
        [self.listPlayer selectExtSubtitle:trackIndex enable:YES];
    }
  2. onTrackReady コールバックを設定して、サブストリーム情報を取得します。

    - (void)onTrackReady:(AliPlayer*)player info:(NSArray<AVPTrackInfo*>*)info {
      //
    }
  3. プレーヤーの prepare done コールバックが呼び出された後、selectTrack を呼び出して字幕トラックを切り替えます。

    // index はターゲット字幕ストリームの TrackIndex です。
    [self.player selectTrack:index];

WebVTT ストリームに基づくカスタムレンダリングの実装

ApsaraVideo Player は、Android と iOS の両方で 標準 WebVTT ストリームの解析とレンダリングをサポートしています。プレーヤーは CSS スタイルを読み取り、両方のプラットフォームで統一された字幕スタイルを作成します。また、1 つのファイルで複数のテキストスタイルをサポートしているため、登場人物の対話を区別したり、重要なコンテンツを強調したり、特殊な視覚効果を作成したりするのに役立ちます。

次のコードは WebVTT ファイルの例を示しています:

  • REGION: 表示エリアを定義します。

  • STYLE: フォントスタイルを定義します。最初の項目はデフォルトのスタイルです。

WEBVTT

REGION
id:bottom
width:70.000000%
lines:3
viewportanchor:15.000000%,95.000000%
regionanchor:0.000000%,100.000000%
scroll:up

STYLE
::cue {
  color: white;
  font-size: 70%;
  font-family: Noto Sans;
  font-weight: bold;
  background-color: rgba(0, 0, 0, 0.2);
}
::cue(.font1) {
  color: rgba(255, 255, 255, 1);
  font-weight: bold;
  font-family: Noto Sans;
  outline-width: 3px;
  outline-color: rgba(0, 0, 0, 1);
}
::cue(.font2) {
  color: rgba(252, 255, 101, 1);
  font-style: bold;
  font-family: Noto Sans;
  outline-width: 3px;
  outline-color: rgba(0, 0, 0, 1);
}
::cue(.font3) {
  color: rgba(255, 191  23, 1);
  font-style: bold;
  font-family: Noto Sans;
  outline-width: 3px;
  outline-color: rgba(183, 28, 28, 1);
}

00:00:00.200 --> 00:00:01.800 region:bottom align:center
被告人 Bo Hanshi

00:00:01.800 --> 00:00:03.200 region:bottom align:center
他に何か言いたいことはありますか

00:00:04.100 --> 00:00:04.800 region:bottom align:center
私

00:00:11.200 --> 00:00:12.200 region:bottom align:center
<v.font1>何も言うことはありません</v.font1>

00:00:14.500 --> 00:00:16.200 region:bottom align:center
被告人 Bo Hanshi

...

テキストセグメントにスタイルを指定するには、次の設定を使用します:

<v.font1>何も言うことはありません</v.font1>