Auto-Play Blocking(自動再生ブロック)の対応

#概要
ブラウザのAuto-Play Blocking(自動再生ブロック)により、
agora.io Web SDKの映像/音声ストリームがブラウザ上に表示された際、音声がブロックされる場合があります。

この記事ではAuto-Play Blocking(自動再生ブロック)の対応方法について記載します。

参考リファレンス：[Deal with Autoplay Blocking](https://docs.agora.io/en/Video/autoplay_policy_web_ng?platform=Web)

#サンプル
[こちら](https://github.com/fu-jimoto/AgoraIO-AutoPlay-Blocking)をご利用ください。
バージョン3の場合は[こちら](https://github.com/fu-jimoto/AgoraIO-AutoPlay-Blocking/tree/main/Agora_Web_SDK_FULL_v3)
バージョン4の場合は[こちら](https://github.com/fu-jimoto/AgoraIO-AutoPlay-Blocking/tree/main/Agora_Web_SDK_FULL_v4)


#Auto-Play Blocking(自動再生ブロック)とは
・ブラウザ上に表示される「音声付き動画」に対し、音声を自動で再生させないようにするブラウザ側のポリシーのことです。

・音声を再生させるには、ユーザの操作(再生ボタンをクリックする等)が必要です。

・Safariでよく発生しますが、ほとんどのブラウザにこのポリシーがあります。


#よく発生する問題

「リモートの映像と音声をブラウザに表示したところ、リモート側の音声が全く聞こえません。」
というお問い合わせをよくいただきます。

【具体例】
ユーザA、Bで入室した場合の例です。
1.ユーザAが入室
2.ユーザBさんが入室
3.ユーザBにてユーザAの映像/音声を受信
この時、Auto-Play Blockingにより音声の再生に失敗
その結果、ユーザBでユーザAの音声が聞こえない事象が発生します。

#対応方法

##対応ポイント
**音声を再生するUI(ボタンやリンク等)を用意し、音声再生が失敗した場合、ユーザの操作により再生を再開させること**です。

##対応案
案１：音声再生が失敗した時に音声再生用のUI(ボタンやリンク等)を表示する。
案２：(音声再生の失敗に限らず)あらかじめ音声再生用のUI(ボタンやリンク等)を表示する。

->音声再生用のUI(ボタンやリンク等)をユーザがクリックすることで音声が再生させます。

##対応イメージ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505696/6b12a467-3221-84a4-9f29-4673667e8bb1.png" width="80%">
("Click here to play"をクリックすると音声が再生します。)


#実装(WebSDK 3.xの場合)

##対応案１(WebSDK 3.x)
音声再生が失敗した時にUI(ボタンやリンク等)を表示する例です。

```javascript:index_1.html
function handleEvents (rtc) {
  // Occurs when a user subscribes to a remote stream.
  rtc.client.on("stream-subscribed", function (evt) {
    var remoteStream = evt.stream
    var id = remoteStream.getId()
    rtc.remoteStreams.push(remoteStream)
    addView(id)
/*ここから*/
    $("#video_autoplay_"+ id).css({'display':'none'});
    remoteStream.play("remote_video_" + id, function(err){  //★play
      Toast.info('err:'+ err.status);
      if (err.status !== "aborted"){　//★エラーの場合
        $("#video_autoplay_"+ id).css({'display':''});
        $("#video_autoplay_"+ id).on('click', function(){　//★ボタン処理の追加
          remoteStream.resume().then(　//★クリック時resume
          function (result) {
            $("#video_autoplay_"+ id).css({'display':'none'});
          }).catch(
          function (reason) {
            Toast.info('Resume fails: ' + reason);
          });
        });  
      }
/*ここまで*/
    });
    Toast.info("stream-subscribed remote-uid: " + id)
    console.log("stream-subscribed remote-uid: ", id)
  })
}
```


##対応案２(WebSDK 3.x)
(音声再生の失敗に限らず)あらかじめUI(ボタンやリンク等)を表示する例です。

```javascript:index_1.html
function handleEvents (rtc) {
  /*省略*/
  // Occurs when a user subscribes to a remote stream.
  rtc.client.on("stream-subscribed", function (evt) {
    var remoteStream = evt.stream
    var id = remoteStream.getId()
    rtc.remoteStreams.push(remoteStream)
    addView(id)
/*ここから*/
    remoteStream.stop("remote_video_" + id)
    remoteStream.play("remote_video_" + id,{ muted: true }) //★play(mute)
    $("#video_autoplay_"+ id).on('click', function(){　//★ボタンクリック時
        remoteStream.stop("remote_video_" + id)
        remoteStream.play("remote_video_" + id, { muted: false })　//★play(unmute)
    })
/*ここまで*/
    Toast.info("stream-subscribed remote-uid: " + id)
    console.log("stream-subscribed remote-uid: ", id)
  })
}
```

#実装(WebSDK 4.xの場合)
##対応案１(WebSDK 4.x)
音声再生が失敗した時にUI(ボタンやリンク等)を表示する例です。

※[AgoraRTC.onAudioAutoplayFailed](https://docs.agora.io/en/Video/API%20Reference/web_ng/interfaces/iagorartc.html#onaudioautoplayfailed)コールバックAPIを利用します。

```javascript:index_1.js

//onAudioAutoplayFailedコールバック
AgoraRTC.onAudioAutoplayFailed = () => {
  if (isAudioAutoplayFailed) return;
  for (let uid in remoteUsers) {　　//リモートユーザ分
    console.log(uid);
    $("#player-audio-"+ uid).css({'display':''});　//UI表示
  }
  isAudioAutoplayFailed = true;
};


//subscribe
async function subscribe(user, mediaType) {
/*省略*/
  if (mediaType === 'audio') {
//ここから
    const player_audio = $(`
      <div id="player-audio-${uid}" onclick="playAudio(${uid})" class="autoplay-fallback"></div>
      `);
    $("#remote-playerlist").append(player_audio);　//UIを追加
    $("#player-audio-"+ uid).css({'display':'none'});　//UIを非表示
//ここまで
    user.audioTrack.play();
  }
}

//play audio
function playAudio(id){
  const user = remoteUsers[id]
  user.audioTrack.play()   //play
}

```

##対応案２(WebSDK 4.x)
(音声再生の失敗に限らず)あらかじめUI(ボタンやリンク等)を表示する例です。

```javascript:index_2.js
//subscribe
async function subscribe(user, mediaType) {
/*省略*/
  if (mediaType === 'audio') {
//ここから
    const player_audio = $(`
      <div id="player-audio-${uid}" onclick="playAudio(${uid})" class="autoplay-fallback"></div>
      `);
    $("#remote-playerlist").append(player_audio);　　//UIを追加
    $("#player-audio-"+ uid).css({'display':'none'});　//UIを非表示
//ここまで
    user.audioTrack.play(); //play
  }
}

//play audio
function playAudio(id){
  const user = remoteUsers[id]
  user.audioTrack.play() //play
}

```

#注意事項
・Auto-Play Blocking(自動再生ブロック)の今後の動向についてはブラウザのバージョンアップによります。
・Safariでのお問い合わせが多いですが、ほとんどのブラウザで採用されているポリシーですので、ご利用予定の全ブラウザに対して確認することをおすすめします。

#関連リンク
・[Autoplay Blockingについて](https://docs.agora.io/en/Video/autoplay_policy_web_ng?platform=Web)
・[agora.ioの対応ブラウザについて](https://docs.agora.io/en/Video/faq/browser_support)
・[音声が聞こえませんが何が原因ですか？](https://vcube-support.zendesk.com/hc/ja/articles/360037976871)

#最後に
[**agora.ioに関するお問い合わせはこちらから**](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=ec93ed6f0a1fb7f2caf3)
[<img width="912" alt="スクリーンショット 0001-08-15 13.41.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/5d815376-9b89-08fa-9434-6fa7e8e67bcf.png">](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=ec93ed6f0a1fb7f2caf3)