LoginSignup
0
0

More than 3 years have passed since last update.

Firefox で mozCaptureStream() すると音が出なくなる

Posted at

WEB ページ上で Video や Audio を扱うことができる HTMLMediaElement があり、captureStream() メソッドを使用することでメディアをキャプチャできます。

Chrome 等では実際に音をスピーカー等から再生しながらキャプチャできるのですが、Firefox ではキャプチャすると音が出なかった (内部的には再生されていてキャプチャはできる) ため、メモしておきます。

もともと Firefox では captureStream() の実装が仕様に追いついておらず、moz ベンダー接頭辞が付いていますが、MDN にはこの音が出なくなる仕様に関しては書かれていませんでした。

参考「HTMLMediaElement.captureStream() - Web API | MDN

1. 再現コード

Chrome 77 と Firefox 71 で動作確認。

(Chrome ではセキリティの制限で index.html を file スキームで開くと cross-origin data としてブロックされるため、php -S 0.0.0.0:8080 などでローカルサーバーを立てるなどしてください。)

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>mozCaptureStream() バグ</title>
    <script src="main.js"></script>
  </head>
  <body>
    <video id="video" src="video.webm" controls></video>
    <input type="button" value="mozCaptureStream()" onclick="TEST.captureStream();">
  </body>
</html>
main.js
(()=>{

    const TEST = {};

    TEST.captureStream = () => {

        const videoElement = document.getElementById('video');

        return ( 'captureStream' in videoElement ) ? videoElement.captureStream() : videoElement.mozCaptureStream();

    };

    window.TEST = TEST;

})();

これはバグとして Bugzilla に投げられていました。

参考「1178751 - Calling mozCaptureStream on an HTMLMediaElement should not destroy the AudioSink

2. 解決策

理想的なことを言えば Firefox のコードを修正すべきですが、ここでは JavaScript 側で対処します。

main.js (Firefox 対応版)
(()=>{

    const TEST = {};

    TEST.captureStream = () => {

        const videoElement = document.getElementById('video');

        let stream;

        if ( 'captureStream' in videoElement ) {
            stream = videoElement.captureStream();
        } else if ( 'mozCaptureStream' in videoElement ) {
            stream = videoElement.mozCaptureStream();
            // ★
            const audioContext = new AudioContext();
            const mediaStreamSource = audioContext.createMediaStreamSource(stream);
            mediaStreamSource.connect(audioContext.destination);
            // 
        } else {
            console.error('Unsupported: captureStream()');
        }

        return stream;

    };

    window.TEST = TEST;

})();
  1. mozCaptureStream() すると HTMLMediaElement に接続されている AudioContext で音声が再生できなくなる。
  2. 別途新しく AudioContext を作成する。
  3. キャプチャーしたストリームからオーディオソースを作成し、AudioContext.destination 1 に接続する。

キャプチャーしたストリームは、既に音量 HTMLMediaElement.volume を反映しているので、GainNode に接続するような記述は不要です。

ただし、上記の対処法では他のバグ 1443511 の影響を受けます。

参考「1443511 - A small delay occurs when the volume is changed on Soundcloud」(「Soundcloud でボリュームが変更されると、わずかな遅延が発生します」2 )


  1. スピーカーなど、最終的な音声の出力先。 

  2. SoundCloud はサイト名。バグ自体はそのサイトに限らず起きる。 

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0