as

Settings
Sign out
Notifications
Alexa
Amazonアプリストア
AWS
ドキュメント
Support
Contact Us
My Cases
開発
設計と開発
公開
リファレンス
サポート

Dash.jsプレーヤーを使用したアダプティブコンテンツの再生

Dash.jsプレーヤーを使用したアダプティブコンテンツの再生

次の手順では、Dash.jsプレーヤーをMSEモードで使用して、アダプティブストリーミングコンテンツを再生する方法を示しています。

Amazonから提供されるDash.jsプレーヤーパッチは特定のバージョンのプレーヤーを対象としていますが、任意のバージョンのDash.jsプレーヤーに移植することができます。Amazonでは、特定のバージョンのDash.jsプレーヤーを使用するように要求する規定は設けていません。開発者は、独自の要件に合わせて最適なDash.jsプレーヤーのバージョンを決定できます。Dash.jsプレーヤーによるコンテンツの処理に関する問題については、オープンソースコミュニティに問い合わせてください。

Dash.jsプレーヤーとサポートされるさまざまな構成の詳細については、Dash.jsプレーヤーに関するページ(英語のみ)を参照してください。

前提条件

Dash.jsプレーヤーでアダプティブコンテンツを再生できるようにコードを変更する前に、次の前提条件を満たしていることを確認し、アプリとプレーヤーを設定します。

Vega用Dash.jsプレーヤーの構成

  1. Vega向けDash.jsプレーヤーを既知の場所にダウンロードします。

    Dash.jsプレーヤーパッケージ

  2. Dash.jsプレーヤーパッケージを展開します。

    クリップボードにコピーしました。

    tar -xzf dash-rel-v<x.y.z>-r<a.b>.tar.gz`
    

    次に例を示します。

    クリップボードにコピーしました。

    tar -xzf dash-rel-v5.0.0-r1.3.tar.gz
    
  3. /dash-rel/scriptsディレクトリに移動します。
  4. setup.shヘルパースクリプトを実行します。

./setup.sh

setup.shスクリプトによってビルドが実行され、dash.jsというディレクトリが生成されます。

  • 生成されたdash.jsディレクトリから、dash-rel/src/*ディレクトリの内容を<アプリのルート>/src/*にコピーします。
  • 生成されたdash.jsディレクトリから、distディレクトリを<アプリのルート>/src/dashjsplayer/distにコピーします。

アダプティブコンテンツの再生

ビデオコンポーネントがマウントされたら、次の手順を実行してDash.jsプレーヤーを読み込みます。

Dash.jsプレーヤーでアダプティブコンテンツを再生する方法

  • src/App.tsxを開き、コンテンツを以下のコードに置き換えます。

    クリップボードにコピーしました。

    /*
    * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All rights reserved.
    *
    * 専有/機密情報。 使用にあたってはライセンス条項が適用されます。
    */
    
    import * as React from 'react';
    import {useRef, useState, useEffect} from 'react';
    import {
      Platform,
      useWindowDimensions,
      View,
      StyleSheet,
      TouchableOpacity,
      Text,
    } from 'react-native';
    
    import {
      VideoPlayer,
      VegaVideoSurfaceView,
      VegaCaptionsView,
    } from '@amazon-devices/react-native-w3cmedia';
    import { DashJsPlayer } from './dashjsplayer/DashJsPlayer';
    
    // ポリフィルをインポートします
    import Document from './polyfills/DocumentPolyfill';
    import Element from './polyfills/ElementPolyfill';
    import TextDecoderPolyfill from './polyfills/TextDecoderPolyfill';
    import W3CMediaPolyfill from './polyfills/W3CMediaPolyfill';
    import MiscPolyfill from './polyfills/MiscPolyfill';
    
    // ポリフィルをインストールします
    Document.install();
    Element.install();
    TextDecoderPolyfill.install();
    W3CMediaPolyfill.install();
    MiscPolyfill.install();
    
    // アプリからビデオの再生APIを手動で呼び出す場合は、falseに設定します。
    const AUTOPLAY = true;
    
    const DEFAULT_ABR_WIDTH: number = Platform.isTV ? 3840 : 1919;
    const DEFAULT_ABR_HEIGHT: number = Platform.isTV ? 2160 : 1079;
    
    const content = [
      {
        secure: 'false', // true: セキュアなビデオバッファーを使用します。false: 非セキュアなビデオバッファーを使用します。
        uri: 'https://storage.googleapis.com/shaka-demo-assets/angel-one/dash.mpd',
        drm_scheme: '', // com.microsoft.playready, com.widevine.alpha
        drm_license_uri: '', // DRMライセンス取得サーバーのURL(コンテンツがDRMで保護されている場合にのみ必要)
      },
    ];
    
    export const App = () => {
      const player = useRef<any>(null);
      const videoPlayer = useRef<VideoPlayer | null>(null);
      const timeoutHandler = useRef<ReturnType<typeof setTimeout> | null>(null);
      const [buttonPress, setButtonPress] = useState(false);
      const [nextContent, setNextContent] = useState({index: 0}); // { index: number }
      // 再レンダリングのためにnextContentの状態を追跡します。
      const nextContentRef = useRef<number>(0);
      // 全画面解像度でレンダリングします。
      const {width: deviceWidth, height: deviceHeight} = useWindowDimensions();
    
      useEffect(() => {
        if (nextContent.index !== nextContentRef.current) {
          nextContentRef.current = nextContent.index;
          // <Video>コンポーネントを強制的に再レンダリングします。
          initializeVideoPlayer();
          setNextContent((prev) => {
            return {...prev};
          });
        }
      }, [nextContent]);
    
      useEffect(() => {
        console.log('app:AppPreBuffering v13.0を開始します');
        initializeVideoPlayer();
      }, []);
    
      const onEnded = async () => {
        console.log('app:onEndedを受け取りました');
        player.current.unload();
        player.current = null;
        await videoPlayer.current?.deinitialize();
        removeEventListeners();
        onVideoUnMounted();
        setNextContent({index: (nextContent.index + 1) % content.length});
      };
    
      const onError = () => {
        console.log(`app: AppPreBuffering:エラーイベントリスナーが呼び出されました`);
      };
    
      const setUpEventListeners = (): void => {
        console.log('app:イベントリスナーをセットアップします');
        videoPlayer.current?.addEventListener('ended', onEnded);
        videoPlayer.current?.addEventListener('error', onError);
      };
    
      const removeEventListeners = (): void => {
        console.log('app:イベントリスナーを削除します');
        videoPlayer.current?.removeEventListener('ended', onEnded);
        videoPlayer.current?.removeEventListener('error', onError);
      };
    
      const initializeVideoPlayer = async () => {
        console.log('app:initializeVideoPlayerが呼び出されました');
        videoPlayer.current = new VideoPlayer();
        // @ts-ignore
        global.gmedia = videoPlayer.current;
        await videoPlayer.current.initialize();
        setUpEventListeners();
        videoPlayer.current!.autoplay = false;
        initializeDash();
      };
    
      const onSurfaceViewCreated = (surfaceHandle: string): void => {
        console.log('app:サーフェスが作成されました');
        videoPlayer.current?.setSurfaceHandle(surfaceHandle);
        videoPlayer.current?.play();
      };
    
      const onSurfaceViewDestroyed = (surfaceHandle: string): void => {
        videoPlayer.current?.clearSurfaceHandle(surfaceHandle);
      };
    
      const onCaptionViewCreated = (captionsHandle: string): void => {
        console.log('app:キャプションビューが作成されました');
        videoPlayer.current?.setCaptionViewHandle(captionsHandle);
      };
    
      const initializeDash = () => {
        console.log('app: in initializePlayer() index = ', nextContent.index);
        if (videoPlayer.current !== null) {
          player.current = new DashJsPlayer(videoPlayer.current);
        }
        if (player.current !== null) {
          player.current.load(content[nextContent.index], AUTOPLAY);
        }
      };
    
      const onVideoUnMounted = (): void => {
        console.log('app: in onVideoUnMounted');
        // @ts-ignore
        global.gmedia = null;
        videoPlayer.current = null;
      };
    
      if (!buttonPress) {
        return (
          <View style={styles.container}>
            <TouchableOpacity
              style={styles.button}
              onPress={() => {
                setButtonPress(true);
              }}
              hasTVPreferredFocus={true}
              activeOpacity={1}>
              <Text style={styles.buttonLabel}> Press to Play Video </Text>
            </TouchableOpacity>
          </View>
        );
      } else {
        return nextContent.index === nextContentRef.current ? (
          <View style={styles.videoContainer}>
            <VegaVideoSurfaceView
              style={styles.surfaceView}
              onSurfaceViewCreated={onSurfaceViewCreated}
              onSurfaceViewDestroyed={onSurfaceViewDestroyed}
            />
            <VegaCaptionsView
              onCaptionViewCreated={onCaptionViewCreated}
              style={styles.captionView}
            />
          </View>
        ) : (
          <View style={styles.videoContainer}></View>
        );
      }
    };
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        flexDirection: 'column',
        backgroundColor: '#283593',
        justifyContent: 'center',
        alignItems: 'center',
      },
      button: {
        alignItems: 'center',
        backgroundColor: '#303030',
        borderColor: 'navy',
        borderRadius: 10,
        borderWidth: 1,
        paddingVertical: 12,
        paddingHorizontal: 32,
      },
      buttonLabel: {
        color: 'white',
        fontSize: 22,
        fontFamily: 'Amazon Ember',
      },
      videoContainer: {
        backgroundColor: 'white',
        alignItems: 'stretch',
      },
      surfaceView: {
        zIndex: 0,
      },
      captionView: {
        width: '100%',
        height: '100%',
        top: 0,
        left: 0,
        position: 'absolute',
        backgroundColor: 'transparent',
        flexDirection: 'column',
        alignItems: 'center',
        zIndex: 2,
      }
    });
    
  • Vega SDKを使用してアプリをビルドし、デバイスまたはシミュレーターで実行してログを収集します。アプリを作成してシミュレーターまたはデバイスで実行する方法の詳細については、Vegaアプリの作成Vega仮想デバイスFire TV Stickでのアプリの実行を参照してください。

    Dash.jsプレーヤーを手動で統合する方法

  1. https://github.com/Dash-Industry-Forum/dash.jsからDash.jsパッケージのクローンを作成します。

    クリップボードにコピーしました。

    cd <ルートディレクトリ>
    git clone https://github.com/Dash-Industry-Forum/dash.js.git
    
  2. 特定のコミットにハードリセットします。

    クリップボードにコピーしました。

    cd dash.js
    git reset --hard ca4c7aa0227d001bb31801faa61a2d57c4e14da4
    
  3. v5.0.0ベースのgitブランチを、v5.0.0-keplerという名前のローカルブランチにチェックアウトします。

    クリップボードにコピーしました。

    git checkout -b amz_5.0.0 
    
  4. Vega Dash.jsプレーヤーパッケージを、ファイルの展開先となる既知の場所にダウンロードします。
  5. ファイルを展開します。

    クリップボードにコピーしました。

    tar -xzf dash-rel-v[x.y.z]-r[x.y].tar.gz
    
  6. Dash.jsパッチを適用します。

    クリップボードにコピーしました。

    git apply dash-rel/dash-patch/*.patch -3
    
  7. npm installを実行してDash.jsの依存関係をインストールします。

    クリップボードにコピーしました。

    npm install
    
  8. npm run buildを実行してDash.jsプレーヤーをビルドします。

    クリップボードにコピーしました。

    npm run build  
    

注: ビルドでbase-64およびxmldomノードモジュールを解決できないというエラーが発生した場合は、次のコマンドを実行してこれらのモジュールをインストールします。

クリップボードにコピーしました。

npm install --save base-64   
npm install --save xmldom

Last updated: 2025年9月30日