yikegaya’s blog

yikegayaのブログ

Reactで動画をキャプチャしてDBに保存する

Reactでビデオ要素をキャプチャしてDBに保存する実装のメモ。

サーバサイドは/api/internal/register_imageのエンドポイントを作ってbinary型のカラムに保存できるようにしておく

フロント側の実装

video要素をcanvasに描画してそのままrequestで送れる。

const sample = () => {
  const videoCapture = () => {
    const canvas = document.getElementById('video-canvas');
    const videoHeight = video.videoHeight;
    const videoWidth = video.videoWidth;

    canvas.height = videoHeight;
    canvas.width = videoWidth;
    canvas.getContext('2d').drawImage(video, 0, 0);
    const canvas_image = canvas.toDataURL('image/png');
    axios.post(
      '/api/internal/register_image',{
        headers: {
          'content-type': 'multipart/form-data',
        },
        image: image,
      }
    );
  }
  
  return (
    <video></video>
    <canvas id='video-canvas' hidden><canvus>
    <button onClick={videoCapture}>キャプチャする</button>
  )
}

こんな形式の値がpostされる。

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4Xuy9iZOt2VXdue98c8431CghkISMaSOMsY3H6Gg3NgaDcdvR0dER/RfbbcAYDBJSSfVevfll5svxzkPHb6297/0y65WqJAGtwmRFxsvKvPe733DOPuusvfbarfVqvY4vy1frzom+7cz5XTsi+JfXL6/i5vpVrJfnsV5No9XqRKvVisVyEa31Mq7O38T5yat49eyTePH0SQx7/Viv1/o7t6a1jlivV7FuraPX68VyuY7Vahk345sYjUbx7W//evzSL/+92Dk4jGjxgatoxSrWsdTP88U8FouF3sNXuxXR7XRivV7qPFarVbQ7bb231WpHSycdsVwto91uR7fbjU6np4vi7+v1IpbLeazWK72OY7U7Hf3Mefa6Pf3/StdfN4x/W9FucWP8tVrx+rWucbla6WfOh+9O18fk53Z+87Pf6JvO6/Uv3/xtnX9vrfWeTqcfwed1u9Fqc34+B73B7/Lx9E/+nmPynnY7gnuiB9mN1bqle1H/vx0F9T7+lsfP+6fjbL5aES3OIY+xrmO1dWzOvd1uNc9K1/5X/eVPqHuSn8aAa37Vff2rPpmf9vh12s0hd+s6bj+OT39cjQn+Ze7No617sY5VLGOxmsR8NY3ZfByL1SouLm/i//2vfxh/9Ad/HOPRNF6/fh3X1zcxmy2i3xtqXjFX+4Od2N8/1Lwfj2exWC41hJlL3U4vOp1uaNi1WrFcLmI+X8R0Oo35jHm7jm6rp/fyNZlMNHF2d3b1+n6fWBGxXK70nn5/EMvFMqbTmeZ9p9PRXGIuL+dzz3WN44jVgniw1rjr9brRbncUI3gNX/y+xXfOSeZoxZLlchmz2Uyftbe/p/csFkvNOz6Lr8FgoDlMHOt2iR+cJ8ePmM6mGnbElna7q3lR94HX9bpdvZ/jdns9xRXu12q50n2ZjCdxfn6+iRnEnOFgGMP+IHaGg+j2OjFfTmK1WsRitojDw8P4lV/9+/Huu+/G48eP4+TkJK6urmI0HuserloR07mfjeJUuxPtbkd/6/X7Opf9g8PY29+Pfq+va1EsXiz0LPg7r+VrOh7HarXWuXLPBsMd/b2nmLuKyWQco9GNrmExn8V0NtbvHPPnEe0lISu67XX0OxE7g07s9tv
  • 表示側 サーバ側から上記の形式でデータを受け取ってそのままimgタグのsrcに指定して表示できる
  const [images, setImages] = useState([]);

  useEffect(() => {
    async function fetchImages() {
      const images = await axios.get
        '/api/internal/images'
      );
      setImages(images.data);
    }
    fetchImages();
  }, []);

  return (
    images.map((image, i) => (
      <img src={image.image} key={i}</img>
    )
  )

追記

DBに入れるとストレージ食うのでS3とかに入れた方がよかった。