このページでは、スマホのカメラやPCのWebカメラの映像をWebページ内に表示する方法について解説します。
HTMLにvideo要素を配置し、JavaScriptで「カメラ権限の取得」と、「video要素とデバイスカメラの関連付け」を行うという処理が必要になっています。
カメラの映像をWebページに表示する方法の解説
実際の動作はこんな感じになります。
まず、HTMLからです。
videoタグの要素と、ボタン要素が1つずつ設置されているだけのシンプルな画面です。
<html>
<head>
<script src="index.js"></script>
</head>
<body>
<div>
<input type="button" value="カメラ起動" onclick="cameraInitSmartphoneSupport()">
</div>
<div>
<video id="camera" autoplay muted playsinline></video>
</div>
</body>
</html>
次に、JavaScriptです。
カメラの縦横幅を設定した定数と、
ボタンを押したときに実行されるカメラ初期化処理が定義されています。
const cameraWidth = 300;
const cameraHeight = 400;
const cameraInit = () => {
const video = document.getElementById("camera");
const cameraSetting = {
audio: false,
video: {
width: cameraWidth,
height: cameraHeight,
facingMode: "environment",
}
}
navigator.mediaDevices.getUserMedia(cameraSetting)
.then((mediaStream) => {
video.srcObject = mediaStream;
})
.catch((err) => {
console.log(err.toString());
});
}
index.htmlを開き、「カメラ起動」ボタンを押下すると
Webページ内にカメラ映像が映し出されると思います。
デバイスのメディア(マイクやカメラ)の使用権限を取得する場合は、
navigator.mediaDevices.getUserMedia()メソッドを使います。
引数には使用するメディアの設定を渡します。
今回はカメラ映像だけなのでaudioはfalseとし、
videoパラメータに設定を行っています。
facingModeを”user”にすればインカメラが使用できるようになります。
当項目の設定についてはこちらが参考になります。
navigator.mediaDevices.getUserMedia()は非同期メソッドであり、
権限付与の確認ダイアログが閉じられるまで待機します。
権限付与が無事に完了したら、video要素のsrcをカメラ映像に設定しています。
ここからは、注意点です。
注意点1:スマートフォンでカメラの縦横幅が逆になる
スマートフォンで同様のページを表示すると、
縦横幅が逆の状態で表示されてしまいます。
どうやら、スマートフォンだとカメラの向きが90°右に回転した状態で固定されてしまうみたいです。
これを防ぐために、スマートフォンの閲覧時には、縦横幅を逆にする必要があります。
このあとお見せする応用アプリでは、スマホ、PCのどちらで表示されているかの判定では、userAgent情報に端末名が含まれているかでやっています。
ユーザエージェントについては、こちらのページが参考になります。
注意点2:HTTPS通信でないと機能しない
このような機能を搭載したWebページをインターネットで公開するとき、
サーバがSSL通信に対応していないとカメラの権限がブラウザに付与できません。
セキュリティ上の観点から、navigator.mediaDevices.getUserMediaメソッドがブラウザでブロックされることが原因のようで、
SSL通信に対応するという方法しか解決策がなさそうです。
ただし、ローカルPC内で完結するようであれば、IPアドレスを”localhost”として接続することでカメラ権限を取得することは可能です。あくまで、外部公開するときだけ、です。
応用編 カメラ撮影機能をWebサイト上で作ってみよう
シャッターボタンを押して、カメラ映像を静止画としてブラウザ上に表示するアプリを作ってみました。
HTMLには描画用のcanvas要素とシャッターボタンを追加しています。
<html>
<head>
<script src="index.js"></script>
</head>
<body>
<div>
<input type="button" value="カメラ起動" onclick="cameraInitSmartphoneSupport()">
<input type="button" value="撮影" onclick="shoot()">
</div>
<div>
<video id="camera" autoplay muted playsinline></video>
<canvas id="canvas" wcrossorigin="anonymous"></canvas>
</div>
</body>
</html>
JavaScript側では描画用の処理を追加します。
基本的にはボタン押下時の映像をcanvasにそのままコピーしているだけです。
const cameraWidth = 300;
const cameraHeight = 400;
const cameraInitSmartphoneSupport = () => {
const video = document.getElementById("camera");
//スマホからの閲覧か
const isMobile = navigator.userAgent.match(/iPhone|Android/);
const cameraSetting = {
audio: false,
video: {
//スマホの場合は縦横を逆に設定する
width: isMobile ? cameraHeight : cameraWidth,
height: isMobile ? cameraWidth : cameraHeight,
facingMode: "environment",
}
}
navigator.mediaDevices.getUserMedia(cameraSetting)
.then((mediaStream) => {
video.srcObject = mediaStream;
})
.catch((err) => {
console.log(err.toString());
});
}
const shoot = () => {
//video要素
const video = document.getElementById("camera");
//canvas要素
const canvas = document.getElementById("canvas");
//canvas要素の大きさを変更
canvas.width = cameraWidth;
canvas.height = cameraHeight;
//描画用オブジェクトを取得
const ctx = canvas.getContext("2d");
//描画する
ctx.drawImage(
video, // データソース
0, // 描画開始x座標
0, // 描画開始y座標
cameraWidth, // 描画横サイズ
cameraHeight // 描画縦サイズ
);
}
先程の「注意点」で説明した通り、スマホでの閲覧の場合、カメラの縦横を逆にする処理を追加しています。
このような応用方法で、色々なアプリが作れそうですね。
コメント