브라우저가 숨겨지면 마이크 입력 해제

곤란한 일



webAudioAPI를 사용하여 마이크 입력 데이터를 사용하는 중
  • 다른 탭으로 전환하면 탭 녹음 중 표시가 사라지지 않습니다 (PC)
  • 홈 버튼을 누를 때 화면에 빨간색 띠가 남습니다 (iOS)

  • 탭은 이런 둥근 녀석↓


    붉은 띠는 이런 녀석↓


    환경



    PC


  • MacBook Pro 2016
  • macOS Mojave 10.14.6
  • Chrome 79.0.3945.88(Official Build)(64비트)

  • 스마트폰


  • iPhone 6s
  • iOS13.3
  • safari

  • 절차


  • 탭이 더 이상 활성화되지 않았음을 감지하고
  • 마이크 입력 트랙 해제

  • 탭이 더 이상 활성화되지 않음을 감지합니다.



    코드


    function setEventListener() {
      let hidden, visibilityChange;
      if (typeof document.hidden !== "undefined") { // Opera 12.10 や Firefox 18 以降でサポート
        hidden = "hidden";
        visibilityChange = "visibilitychange";
      } else if (typeof document.msHidden !== "undefined") {
        hidden = "msHidden";
        visibilityChange = "msvisibilitychange";
      } else if (typeof document.webkitHidden !== "undefined") {
        hidden = "webkitHidden";
        visibilityChange = "webkitvisibilitychange";
      }
      document.hiddenStatus = hidden;
    
      if (hidden === undefined) {
        console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
      } else {
        document.addEventListener(visibilityChange, browserBlorFunction, {once: true});
      }
    }
    
    async function browserBlurFunction() {
      if (document.hidden) {
        // 非表示状態になった時の動作
        await stopRecording();
      }
    }
    

    해설



    이 기사에 모두 쓰여져 있습니다!
    [iOS/Android] 브라우저에서 페이지가 숨겨진 것을 감지하는 방법

    이번은 탭이 액티브하지 않을 때의 체험을 해치지 않는 것을 목적으로 하고 있었으므로,
    Page Visibility API 만 이용하고 있습니다.

    간단히 말하면, 「페이지가 표시되고 있는지 어떤지」를 판정해 주는 API입니다.
    EventListener에 등록하여 사용할 수 있습니다!

    이 기능에 의해 추가된 프로퍼티인 document.hidden 로 현재의 브라우저의 표시 상태를 취득할 수 있으므로,document.hidden === true 때 마이크 입력 해제 함수를 실행합니다.

    그건 그렇고



    같은 동작을 시키고 싶을 때의 글로벌 이벤트 핸들러로서 window.onblur 가 있습니다.
    이것은 창 전환을 의미하며 페이지 표시를 감지하지 않습니다.
    따라서 window.onblur 에 마이크 입력 해제 코드를 설정해도
    iPhone에서 홈 버튼을 누른 후 처음부터 소개한 붉은 띠가 나오고,
    탭을 전환해도 브라우저의 둥근 표시는 그대로 유지됩니다.

    마이크 입력 해제



    코드


    //streamsには、mediaStreamそのものが入っています。
    function stopRecording() {
      let tracks = streams.getTracks();
      tracks.forEach(function (track) {
        track.stop();
      });
    }
    
    //streamsへの格納
    navigator.mediaDevices.getUserMedia({audio: true})
        .then(mediaStream => {
          gotStream(mediaStream);
        }).catch(e => {
        alert('Error getting audio');
      });
    }
    
    let streams = null;
    function gotStream(stream){
      streams = stream;
      //以下音声の処理...
    }
    

    해설



    마이크 입력은 mediaDevices.getUserMedia 로부터 취득하고 있어 그 때에 취득한 mediaStreamTrack 를 정지시키는 것에 의해, 입력을 해방합니다.

    track 정지



    mediaStreamTrack.readyState 이라고 하는 프로퍼티의 값이 "ended" 가 되면 입력 디바이스로부터의 데이터를 받지 않게 됩니다.

    "ended"는 입력 장치가 더 이상 데이터를 제공하지 않고 새로운 데이터도 제공되지 않음을 나타냅니다.
    인용 소스 : mediaStreamTrack.readyState

    이를 위한 함수로서

    MediaStreamTrack.stop()
    트랙과 관련된 소스의 재생을 중지하고 소스와 트랙의 연결을 해제합니다. 트랙 상태는 ended로 설정됩니다.

    여기가 준비되어 있으므로 사용합시다!
    mediaStream.getTracks
    function stopRecording() {
      let tracks = streams.getTracks();
      tracks.forEach(function (track) {
        track.stop();
      });
    }
    

    이제 mediaStreamTrack.readyState가 끝나기 때문에 기사 시작 부분에서 소개한 동작은 더 이상 발생하지 않습니다.

    마지막으로



    인생 첫 Qiita 기사 써 보았습니다!
    덧붙여서 safari의 앱을 완전히 떨어뜨리면 같은 일을 달성 할 수 있습니다 ()

    올해는 최선을 다하고 출력합니다.

    좋은 웹페이지 즐겨찾기