19. Webcam Fun


プロジェクトの概要
  • Webカメラで受信ビデオデータをWebページのキャンバスにレンダリングしながら、さまざまな効果を実現するための練習を行います.
  • は、取得する画像をデバイスに保存する機能
  • を含む.
    学んだこと
    Media(video,audio)イベント
    -値の順序:loademetadata->loadeddata->canplay->canplayrough**
    loadedmetadata
    :メディアのメタデータがロードされていることを示します.
    :メタデータは、私たちが使用できるビデオの再生時間を意味します.メディアをロードする前に、メタデータを抽出して利用できます.
    loadeddata
    :メディア上のフレームがロードされていることを示します.
    :フレームは、メディアフレーム全体ではなく、最初のフレームであってもよいし、現在のフレームであってもよい.つまり、少しダウンロードしたときでも、その意味が再生できることに気づくことができます.
    :ただし、ロードされたデータは再生に十分ではないことに注意してください.すなわち、loaddataイベントが発生したときにplay()メソッドを呼び出すと、再生に失敗する可能性がある.
    :まずメタデータをインポートし、loademetadataイベントが発生した後、loadeddataイベントが発生したと考えられます.すなわちloadddataでもメタデータを使用することができる.
    canplay
    :再生のために十分なデータがロードされると、メディアはイベントを再生して呼び出すことができると考えられます.すなわち、canplayイベントは、メディアを再生できることを示す.
    :ただし、再生は保証されますが、バッファによって中断される可能性があります.すなわち、全ての再生ではなく現在の時点で再生できるか否かを保証する.
    canplaythrough
    :canplayイベントと同じですが、メディア全体が連続的に再生できる場合に呼び出されます.canplayイベントが完全な再生を保証できない場合は、canplaythroughの目的は完全な再生を確保することです.現在のロード速度を維持し、中断しないと判断した場合に呼び出されます.しかし、これも仮説であるため、canplay活動よりも再生全体を保証しますが、肯定的ではありません.また、一方、canplaythroughイベントは、canplayイベントが発生した後に呼び出される.
    出典:https://mygumi.tistory.com/356[私の欧米世界]
    navigator (Web-API)
    スクリプトで情報を照会し、アクティビティを登録するときにアプリケーションを使用するためのユーザーエージェントのステータスとアイデンティティ情報を表します.
    .geolocation:デバイスの場所情報にアクセスできるgeolocationオブジェクトを返します.
    .mediaDevices:利用可能なメディアデバイス情報を取得できるメディアデバイスリファレンスを返し、ユーザーデバイスのメディアに対するサポート制限を返し、メディアへのアクセスを要求する
    .getUserMedia() method
    Promiseオブジェクトフォーマット、MainStreamオブジェクト(ビデオ再生のアドレスを含む)を返します.
    https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
    .drawImage (canvas method)
    void ctx.drawImage(image, dx, dy);
    void ctx.drawImage(image, dx, dy, dWidth, dHeight);
    void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
    .getImageData (canvas method)
    imagedataオブジェクト形式でcanvasにインポートされたピクセル値=>ピクセル単位の変換を作成する場合は、
    https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData
    .putImageData (canvas method)
    ピクセルデータをcanvas領域に分散する方法
    https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData
    .toDataURL (canvas method)
    cavas画面上の画像を指定タイプ(default:jpeg)に指定したデータURL値を=>img src値に戻す
    https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
    aラベルの「ダウンロード」属性
    ダウンロード属性を含むタグをクリックしてデータ(画像など)をダウンロードします.
    ダウンロードファイル名を「download:」「x」=>xと指定できます.
    https://www.w3schools.com/tags/att_a_download.asp
    最終コード
    const video = document.querySelector('.player');
    const canvas = document.querySelector('.photo');
    const ctx = canvas.getContext('2d');
    const strip = document.querySelector('.strip');
    const snap = document.querySelector('.snap');
    
    function getVideo() {
      navigator.mediaDevices
        .getUserMedia({ video: true, audio: false })
        .then((localMediaStream) => {
          console.log(localMediaStream);
    
          //  DEPRECIATION :
          //       The following has been depreceated by major browsers as of Chrome and Firefox.
          //       video.src = window.URL.createObjectURL(localMediaStream);
          //       Please refer to these:
          //       Deprecated  - https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
          //       Newer Syntax - https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject
    
          video.srcObject = localMediaStream;
          video.play();
        })
        .catch((err) => {
          console.error(`OH NO!!!`, err);
        });
    }
    
    function paintToCanvas() {
      const width = video.videoWidth;
      const height = video.videoHeight;
      canvas.width = width;
      canvas.height = height;
    
      return setInterval(() => {
        ctx.drawImage(video, 0, 0, width, height);
        // take the pixels out
        let pixels = ctx.getImageData(0, 0, width, height);
        // mess with them
    
        pixels = rgbSplit(pixels);
        // ctx.globalAlpha = 0.8;
    
        // put them back
        ctx.putImageData(pixels, 0, 0);
      }, 16);
    }
    
    function takePhoto() {
      // played the sound
      snap.currentTime = 0;
      snap.play();
    
      // take the data out of the canvas
      const data = canvas.toDataURL('image/jpeg');
      const link = document.createElement('a');
      link.href = data;
      link.setAttribute('download', 'handsome');
      link.innerHTML = `<img src="${data}" alt="Handsome Man" />`;
      strip.insertBefore(link, strip.firstChild);
    }
    
    
    function rgbSplit(pixels) {
      for (let i = 0; i < pixels.data.length; i += 4) {
        pixels.data[i - 150] = pixels.data[i + 0]; // RED
        pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
        pixels.data[i - 550] = pixels.data[i + 2]; // Blue
      }
      return pixels;
    }
    
    
    getVideo();
    
    video.addEventListener('canplay', paintToCanvas);
    
    感じる/記憶
  • 既存のメディアストリーム(最終コードの内容を参照)
  • を最新の方法で受信する.
  • ピクセルの変形などの詳細はまだ完全に理解されていません