Rx-player + MPEG-Dash Widevine DRM + MS Smooth Streaming  + ReactJSの使用法 

##はじめに

こんにちは streampack チームのメディです。
https://cloudpack.jp/service/option/streampack.html

In my opinion ***Rx-Player*** is a really interesting player  and  I would like to show you common use cases. 
***Rx-Player*** は興味深いプレイヤーなので、一般的な使用法を説明します。

##Copyrights of videos
**Big Buck Bunny**
© copyright 2008, Blender Foundation | www.bigbuckbunny.org
**Tears of Steel**
© copyright Blender Foundation | https://mango.blender.org/

#What is Rx-player 
From the official webpage:
>The Rx-player is a library implementing a ***DASH*** and ***Microsoft Smooth Streaming*** video player ***directly on the browser***, without plugins. It relies on HTML5 Media Source Extensions and Encrypted Media extensions and is written in TypeScript, a superset of JavaScript.

公式ウェブページから：
>Rxプレーヤーは、DASHおよびMicrosoft Smooth Streamingビデオプレーヤーをプラグインなしでブラウザに直接実装するライブラリです。 HTML5 Media Source ExtensionsとEncrypted Media拡張機能に依存しています。 RxプレーヤーはTypeScriptで書かれています。


#Create the React App ・ React Appを作成してください

```bash
yarn create react-app my-app
```

```bash
cd my-app/
```

```bash
yarn add rx-player
```

```bash 
yarn start
```

Please go to :
次のURLにアクセスしてください:
http://localhost:3000/

You should see something similar to this:
これに似たものが表示されます。
<img width="484" alt="Screen Shot 2018-07-27 at 18.12.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/229807/d6d0d2ad-7bcc-bf46-632c-1752201fa798.png">

To try the following examples, simply replace the code defined in 
*my-app/src/App.js* 
次の例を試すには、*my-app/src/App.js*


#MPEG-DASH example

<img width="665" alt="Screen Shot 2018-07-27 at 18.10.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/229807/e8daef94-26e6-370f-35ec-6d58a0729a11.png">


```react:App.js
import React, {Component} from 'react';
import RxPlayer from "rx-player";
RxPlayer.LogLevel = "DEBUG";

class App extends Component {

  constructor(props) {
    super(props)
    this.state = {}
  }

  componentDidMount() {
    this.initPlayer();
  }

  initPlayer() {
    const player = new RxPlayer({videoElement: document.getElementById("video")});
    player.loadVideo({
      url: "http://vm2.dashif.org/livesim-dev/segtimeline_1/testpic_6s/Manifest.mpd",
      transport: "dash",
      autoPlay: false});
  }

  render() {
    return (
      <div className="App">
        <video id="video" controls></video>
      </div>
    );
  }
}

export default App;
```




#  MPEG-DASH + Widevine DRM

<img width="778" alt="Screen Shot 2018-09-07 at 10.09.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/229807/10a3c226-3a34-fc9e-88fc-ed914d83dd23.png">


Widevine DRM system is compatible with Chrome, Firefox and Android.
Widevine DRMシステムは、Chrome、Firefox、Androidと互換性があります。

Data are passed to the license server through a custom header.
In this example the custom header name is `X-AxDRM-Message`.
The custom header name depends on your DRM provider.

データは、カスタムヘッダーを介してライセンスサーバーに渡されます。
この例では、カスタムヘッダー名は`X-AxDRM-Message`です。
カスタムヘッダ名はDRMプロバイダによって異なります。


####About Rx-player DRM behaviour ・ Rx-playerのDRM動作について
The encryption information can usually be at two places:

- in the Manifest/MPD
- in the initialization segments of the encrypted content

Rx-player trusts more what the segment contains than the manifest. 

暗号化情報は通常2つの場所にあります。

- MPDマニフェスト
- 暗号化されたコンテンツの初期化セグメント

Rx-playerは、セグメントに含まれるものがマニフェストよりも信頼しています。

#####About the `getLicence` method ・`getLicence`メソッドについて
The **getLicense** method takes the "challenge" (message to generate the license) and has to perform the request to the license server. It should then return the license as an **arraybuffer** (wrapped in a **promise** for asynchronous functions).

**getLicense** メソッドはパラメータとして「チャレンジ」（ライセンスを生成するメッセージ）を受け取り、ライセンスサーバーへの要求を実行する必要があります。
ライセンスを **arraybuffer**（非同期関数の **promise** で囲んだもの）として返します。




*Thanks to the Rx-player team for giving me those detailed information !*
*詳細な情報を提供してくれたRx-playerチームに感謝します！*


```react:App.js
import React, {Component} from "react";
import RxPlayer from "rx-player";

RxPlayer.LogLevel = "DEBUG";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  componentDidMount() {
    console.log("did  mount");

    this.initPlayer();

  }
  initPlayer() {

    const player = new RxPlayer({videoElement: document.getElementById("video")});

    player.loadVideo({
      url: "//media.axprod.net/TestVectors/v6.1-MultiDRM/Manifest_1080p.mpd",
      transport: "dash",
      autoPlay: false,
      keySystems: [
        {
          type: "widevine",
          getLicense(message, messageType) {
            console.log("Message type: " + messageType);
            return new Promise((resolve, reject) => {
              return fetch("https://drm-widevine-licensing.axtest.net/AcquireLicense", {
                body: message,
                headers: {
                  "X-AxDRM-Message": 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiNmU1YTFkMjYtMjc1Ny00N2Q3LTgwNDYtZWFhNWQxZDM0YjVhIn1dfX0.yF7PflOPv9qHnu3ZWJNZ12jgkqTabmwXbDWk_47tLNE'
                },
                method: "POST"
              }).then((response) => {
                if (response.ok) {
                  response.arrayBuffer().then(function(buffer) {
                    resolve(buffer);
                  });
                } else {
                  reject(new Error('error'))
                }
              }, error => {
                reject(new Error(error.message))
              })
            });
          }
        }
      ]
    });
  }

  render() {
    return (
      <div className="App">
        <video id="video" controls></video>
      </div>
    );
  }
}

export default App;


```

#Microsoft Smooth Streaming 
<img width="651" alt="Screen Shot 2018-07-27 at 18.31.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/229807/8d0a0c6c-bc84-4c5b-e45e-9fde516b11bd.png">



```react:App.js
import React, {Component} from 'react';
import RxPlayer from "rx-player";
RxPlayer.LogLevel = "DEBUG";

class App extends Component {

  constructor(props) {
    super(props)
    this.state = {}
  }

  componentDidMount() {
    this.initPlayer();
  }

  initPlayer() {
    const player = new RxPlayer({videoElement: document.getElementById("video")});
    player.loadVideo({
      url: "http://amssamples.streaming.mediaservices.windows.net/683f7e47-bd83-4427-b0a3-26a6c4547782/BigBuckBunny.ism/manifest",
      transport: "smooth",
      autoPlay: false});
  }

  render() {
    return (
      <div className="App">
        <video id="video" controls></video>
      </div>
    );
  }
}

export default App;

```



##Information sources ・ 情報源

###RxPlayer homepage
https://github.com/canalplus/rx-player

###Rx-player DRM discussion
https://github.com/canalplus/rx-player/issues/281

###RxPlayer style
https://raw.githubusercontent.com/canalplus/rx-player/master/demo/full/styles/style.css

###ReactJS
https://github.com/facebook/create-react-app

###RxPlayer documentation
https://developers.canal-plus.com/rx-player/doc/pages/api/index.html
https://github.com/canalplus/rx-player/tree/master/doc/architecture

###Media files & streams
https://github.com/Axinom/drm-quick-start
http://playready.azurewebsites.net/Home/AmsSamples