audiovisualcoding

これをやるのに必要なのはこれだけ、が欲しかったプログラミング初心者による覚え書き

【JavaScript】Webページ上でWebカメラの映像を使いたいとき

【実践したいこと】
何を:ユーザのWebカメラやマイクから、映像・音声(今回は映像のみ)を取得して再生するまで
どこで:Webページ上

【前提知識】

  • HTML属性とDOMプロパティ

  • Promise

【ソース】

▾index.html

<!DOCTYPE html>
<html>
    <body>
        <div id="videoWrap"></div>
        <script src="main.js"></script>
    </body>
</html>

▾main.js

// 1-i HTMLVideoElementオブジェクトを作成する
const video = document.createElement('video');
video.autoplay = true;
video.width = 360;
video.height = 240;
// 1-ii video要素をHTMLに追加する
document.getElementById('videoWrap').appendChild(video);

// 2-i MediaDevicesオブジェクトを用意する
const media = navigator.mediaDevices;
// 2-ii Webカメラを使っていいかユーザに聞く
const constraints = { audio: false, video: true };
media.getUserMedia(constraints)
// 2-iii 取得できた映像・音声データを処理する
.then(function (stream) {
    video.srcObject = stream;
});

取得する映像・音声の行き先を準備する

1-i Videoオブジェクトを作成する

const video = document.createElement('video');

メソッド document.createElement()

HTML要素を新しく作る役割をもつ。

Videoオブジェクトとは、映像データを再生するためのオブジェクトである。
Webカメラの映像をリアルタイムに再生し続けるために必要であり、これを直接ブラウザに表示させたり、canvasに書き出してからの解析・加工できるようになる。
HTMLでは<video>要素にあたる。

ここではdocument.createElement()メソッドを使って、Videoオブジェクトを作成する。

Videoオブジェクトが持つプロパティ

Videoオブジェクトは、HTMLVideoElementインターフェースを実装し、次のようなプロパティを持っている。

srcObject *1

video.srcObject = stream;

映像や音声といったメディアストリーム(一連のデータ)を受け取る。
ここに、表示させたり再生させたりしたいメディアストリームを入れる。

autoplay (HTML属性)

video.autoplay = true;

Webサイトを開いたら自動的に映像を再生させたいときには、これを追加する。

width, height (HTML属性)

video.width = 360;
video.height = 240;

映像を表示させる大きさを決めたいときに指定する。単位は px (ピクセル)。

1-ii video要素をHTMLに追加する

document.getElementById('videoWrap').appendChild(video);

※ 取得した映像や音声をブラウザ上に表示させる必要がなければ、このステップは省いてよい。

今回は、作成した<video>要素を追加するために、HTMLのほうにID付きの<div>要素を準備しておいた。

<div id="videoWrap"></div>

メソッド document.getElementById()

対応するIDを持つHTML要素を探し出す。

メソッド appendChild()

対象の要素のすぐ下の階層に、引数に入れた要素を追加する。

Webカメラやマイクを通した映像・音声を取得する

2-i MediaDevicesオブジェクトを用意する

const media = navigator.mediaDevices;

MediaDevicesオブジェクトとは、映像や音声を取得するためのデバイス(Webカメラやマイク)にアクセスできるようにするオブジェクトである。

読み取り専用プロパティ navigator.mediaDevices

ユーザが使っているパソコンかスマホにどんなマイクやカメラがあるか、それらを使うことができるかなどの情報を返す。

2-ii Webカメラを使っていいかユーザに聞く

const constraints = { audio: false, video: true };
media.getUserMedia(constraints)...

メソッド MediaDevices.getUserMedia()

指定した種類のメディア入力デバイスを使っていいかどうかをユーザに聞くと同時に、Promiseオブジェクトを返す。

無事にユーザから許可をもらったあと、映像と音声(あるいはどちらか)をロードし終わると、次の二つの処理を続けて行う:

  • 返したPromiseオブジェクトをfullfilled状態にする。

  • 取得した映像と音声のトラックが入ったMediaStreamオブジェクトを返す。

MediaDevices.getUserMedia()の引数constraintsには、audioとvideoの二つのプロパティを持つオブジェクトを入れる。
音と映像それぞれ、データとして欲しいときは値をtrueに、取得する必要がないときは値をfalseにする。
他にも、映像のサイズや、複数のデバイスがある場合に自動的に選びとるための条件なども、値に含めることができる*2

2-iii 取得できた映像・音声データを処理する

...getUserMedia(constraints).then(function(stream) {
    video.srcObject = stream;
});
console.log(media.getUserMedia(constraints));

MediaStreamオブジェクトをHTMLVideoElement.srcObjectに渡せば、映像や音をそのままブラウザ上で再生したり、加工することができるようになる。

また、getUserMedia()がPromiseオブジェクトを返すということは、then()をつなげて、ロード完了後の処理を指定することができるということである。

そのため、getUserMedia()の後ろにthen()を付け加えて、MediaStreamオブジェクトをHTMLVideoElement.srcObjectに渡す処理を書いた関数を入れている。

参考文献

developer.mozilla.org

gray-code.com

qiita.com

zenn.dev

tec.tecotec.co.jp

houwa-js.co.jp

*1:HTMLVideoElementが継承している、HTMLMediaElementインターフェースが持つプロパティ

*2:「MediaStreamConstraintsオブジェクト」で調べる