getUserMediaを使ってローカルでwebカメラの映像をブラウザに表示させる

##はじめに
getUserMediaを使ってwebカメラの映像をブラウザに表示させる機会があったので今回、復習として記事を書いていこうと思います

##環境

* react v17.0.1
* next  v10.0.3

##getUserMdeia

getUserMedia()は、ユーザーのWebカメラやマイクの「メディアストリーム」を取得するメソッドです。

引数では、「audio」(音声)と「video」(動画)の有効・無効を指定できます。

```react

const mediaStream = await navigator.mediaDevices
  .getUserMedia({
    audio: true,
    video: true
  })
```

true・falseの代わりに「制約」を指定することもできます。
以下は、カメラの解像度を取得する例になります。

```react

const mediaStream = await navigator.mediaDevices
  .getUserMedia({
    audio: false,
    video: {
      width:600,
      height:400 
    }
  })
```

##実際に使ってみる

```react


import React, { useEffect, useRef, useState } from "react";
import { CameraOnOfButton } from "~/components/Button/Camera";
import { MicOnOfButton } from "~/components/Button/Mic";

//audioのbooleanとvideoの大きさをpropsで渡す
type MediaProps = {
  audio: boolean;
  video: {
    width: number;
    height: number;
  };
};


const WebCameraTest: React.FC<MediaProps> = ({ audio, video }) => {
  const constraints = {
    audio: false,
    video: {
      width: video.width,
      height: video.height,
    },
  };

  const videoRef = useRef<HTMLVideoElement>(null);
//カメラとマイクのon/offボタンのstateを管理
  const [mutedState, setMutedState] = useState(false);
  const micSetter = (isChecked: boolean) => setMutedState(isChecked);
  const [cameraState, setCameraState] = useState(false);
  const cameraSetter = (isChecked: boolean) => setCameraState(isChecked);

//画面がロードされたタイミングでwebカメラに接続
  useEffect(() => {
    navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
      videoRef.current!.srcObject = stream;
    });
  }, []);


//カメラのon/offボタンの実装
  useEffect(() => {
    navigator.mediaDevices
      .getUserMedia({ audio: true, video: true })
      .then((stream) => {
        videoRef.current!.srcObject = cameraState ? null : stream;
      });
  }, [cameraState]);

//マイクのon/offボタンの実装
  useEffect(() => {
    navigator.mediaDevices
      .getUserMedia({ audio: mutedState ? false : true, video: true })
      .then(() => {});
    console.log(audio);
  }, [mutedState]);

  return (
    <>
      <video
        ref={videoRef}
        id="local-video"
        autoPlay
        playsInline
        muted
        width={video.width}
        height={video.height}
      />
      <br />
      <CameraOnOfButton muted={cameraState} setter={cameraSetter} />
      <MicOnOfButton muted={mutedState} setter={micSetter} />
    </>
  );
};

export default WebCameraTest;

```

カメラとマイクボタンのコンポーネント↓

```react

import React from "react";
import styled from "styled-components";

type Props = {
  muted: boolean;
  setter: any;
};

//styled-componentを使いbuttonのoutlineを0に
const Button = styled.button`
  &:focus {
    outline: 0;
  }
`;

export const MicOnOfButton: React.FC<Props> = ({ muted, setter }) => {
  let icon;
  if (muted) {
    icon = (
     //使いたいアイコン(offの時)
    );
  } else {
    icon = (
     //使いたいアイコン(onの時)
  }
  const handleOnClick = () => {
    setter(!muted);
  };
  return <Button onClick={handleOnClick}>{icon}</Button>;
};

```
video要素はautoplayを有効にしておくか、もしくはplay()メソッドで再生させることができます。

そしてカメラのデータ(stream)をvideo要素のsrcObjectに代入することで表示することができます。

とりあえずこれでvideo要素にWebカメラの映像を表示することができました。

videoタグの属性には他にも色々あるのでお好みで設定してみてください↓
 [video: 動画埋め込み要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/video "video")

##最後に

他にもMediaStreamは様々なプロパティやメソッドを持っており、カメラの解像度やノイズ抑制、明るさ、ズームといった様々な機能を実装することができると思うのでこれから勉強していきたいと思います