Kullanıcıdan video kaydetme

Mat Scales

Birçok tarayıcı artık kullanıcının video ve ses girişine erişebilir. Ancak tarayıcıya bağlı olarak bu, tam dinamik ve satır içi bir deneyim olabilir veya kullanıcının cihazındaki başka bir uygulamaya devredilebilir.

Basit ve aşamalı olarak başlayın

En kolay yöntem, kullanıcıdan önceden kaydedilmiş bir dosya istemektir. Bunu yapmak için basit bir dosya giriş öğesi oluşturun ve yalnızca video dosyalarını kabul edebileceğimizi belirten bir accept filtresi ve doğrudan kameradan almak istediğimizi belirten bir capture özelliği ekleyin.

<input type="file" accept="video/*" capture />

Bu yöntem tüm platformlarda kullanılabilir. Masaüstünde, kullanıcıdan dosya sisteminden bir dosya yüklemesi istenir (capture özelliği yoksayılır). iOS'te Safari'de kamera uygulamasını açarak video kaydetmenize ve ardından web sayfasına geri göndermenize olanak tanır. Android'de ise kullanıcıya, videoyu web sayfasına geri göndermeden önce hangi uygulamayı kullanarak kaydedeceğini seçme imkanı sunar.

Birçok mobil cihazda birden fazla kamera bulunur. Tercihiniz varsa kullanıcıya bakan kamerayı istiyorsanız capture özelliğini user, dışa bakan kamerayı istiyorsanız environment olarak ayarlayabilirsiniz.

<input type="file" accept="video/*" capture="user" />
<input type="file" accept="video/*" capture="environment" />

Bunun yalnızca bir ipucu olduğunu unutmayın. Tarayıcı bu seçeneği desteklemiyorsa veya istediğiniz kamera türü mevcut değilse tarayıcı başka bir kamera seçebilir.

Kullanıcı kaydı tamamlayıp web sitesine döndüğünde dosya verilerini bir şekilde almanız gerekir. Giriş öğesine bir onchange etkinliği ekleyip etkinlik nesnesinin files özelliğini okuyarak hızlı erişim sağlayabilirsiniz.

<input type="file" accept="video/*" capture="camera" id="recorder" />
<video id="player" controls></video>
<script>
  var recorder = document.getElementById('recorder');
  var player = document.getElementById('player');

  recorder.addEventListener('change', function (e) {
    var file = e.target.files[0];
    // Do something with the video file.
    player.src = URL.createObjectURL(file);
  });
</script>

Dosyaya erişiminiz olduğunda dosyayla istediğiniz her şeyi yapabilirsiniz. Örneğin, şunları yapabilirsiniz:

  • Oynatabilmek için doğrudan bir <video> öğesine ekleyin.
  • Kullanıcının cihazına indirin.
  • XMLHttpRequest öğesine ekleyerek sunucuya yükleyin
  • Kareleri bir tuvale çizme ve filtre uygulama

Video verilerine erişmek için giriş öğesi yöntemini kullanmak yaygın olsa da en az tercih edilen seçenektir. Kameraya erişmek ve doğrudan sayfada güzel bir deneyim sunmak istiyoruz.

Kameraya etkileşimli olarak erişme

Modern tarayıcılar, kameraya doğrudan erişim sağlayarak web sayfasıyla tamamen entegre deneyimler oluşturmamıza olanak tanır ve kullanıcı tarayıcıdan hiç ayrılmaz.

Kameraya erişim izni alma

WebRTC spesifikasyonunda getUserMedia() adlı bir API kullanarak kameraya doğrudan erişebiliriz. getUserMedia(), kullanıcıdan bağlı mikrofon ve kameralarına erişim izni vermesini ister.

İşlem başarılı olursa API, kameradan veya mikrofondan gelen verileri içeren bir Stream döndürür. Ardından bunu bir <video> öğesine ekleyebilir, WebRTC akışına ekleyebilir veya MediaRecorder API'yi kullanarak kaydedebiliriz.

Kameradan veri almak için getUserMedia() API'sine iletilen kısıtlama nesnesinde video: true değerini ayarladık.

<video id="player" controls></video>
<script>
  var player = document.getElementById('player');

  var handleSuccess = function (stream) {
    player.srcObject = stream;
  };

  navigator.mediaDevices
    .getUserMedia({audio: true, video: true})
    .then(handleSuccess);
</script>

Belirli bir kamerayı seçmek istiyorsanız önce mevcut kameraları listeleyebilirsiniz.

navigator.mediaDevices.enumerateDevices().then((devices) => {
  devices = devices.filter((d) => d.kind === 'videoinput');
});

Ardından, getUserMedia çağrısı yaparken kullanmak istediğiniz deviceId'yi iletebilirsiniz.

navigator.mediaDevices.getUserMedia({
  audio: true,
  video: {
    deviceId: devices[0].deviceId,
  },
});

Bu tek başına pek kullanışlı değildir. Tek yapabileceğimiz, video verilerini alıp oynatmak.

Kameradan ham verilere erişme

Kameradan gelen ham video verilerine erişmek için her kareyi bir <canvas> içine çizip pikselleri doğrudan değiştirebilirsiniz.

2D tuval için bağlamın drawImage yöntemini kullanarak bir <video> öğesinin geçerli karesini tuvale çizebilirsiniz.

context.drawImage(myVideoElement, 0, 0);

WebGL tuvaliyle, doku kaynağı olarak bir <video> öğesi kullanabilirsiniz.

gl.texImage2D(
  gl.TEXTURE_2D,
  0,
  gl.RGBA,
  gl.RGBA,
  gl.UNSIGNED_BYTE,
  myVideoElement,
);

Her iki durumda da oynatılan videonun mevcut karesinin kullanılacağını unutmayın. Birden fazla kareyi işlemek için videoyu her seferinde tuvale yeniden çizmeniz gerekir.

Bu konu hakkında daha fazla bilgiyi resim ve videolara gerçek zamanlı efektler uygulama ile ilgili makalemizde bulabilirsiniz.

Kameradaki verileri kaydetme

Kameradan gelen verileri kaydetmenin en kolay yolu MediaRecorder API'sini kullanmaktır.

MediaRecorder API, getUserMedia tarafından oluşturulan akışı alır ve akıştaki verileri tercih ettiğiniz hedefe kademeli olarak kaydeder.

<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
  let shouldStop = false;
  let stopped = false;
  const downloadLink = document.getElementById('download');
  const stopButton = document.getElementById('stop');

  stopButton.addEventListener('click', function() {
    shouldStop = true;
  })

  var handleSuccess = function(stream) {
    const options = {mimeType: 'video/webm'};
    const recordedChunks = [];
    const mediaRecorder = new MediaRecorder(stream, options);

    mediaRecorder.addEventListener('dataavailable', function(e) {
      if (e.data.size > 0) {
        recordedChunks.push(e.data);
      }

      if(shouldStop === true && stopped === false) {
        mediaRecorder.stop();
        stopped = true;
      }
    });

    mediaRecorder.addEventListener('stop', function() {
      downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
      downloadLink.download = 'acetest.webm';
    });

    mediaRecorder.start();
  };

  navigator.mediaDevices.getUserMedia({ audio: true, video: true })
      .then(handleSuccess);
</script>

Bizim örneğimizde verileri doğrudan bir diziye kaydediyoruz. Bu diziyi daha sonra Blob biçimine dönüştürerek web sunucumuza veya doğrudan kullanıcının cihazındaki depolama alanına kaydedebiliriz.

Kamerayı sorumlu bir şekilde kullanmak için izin isteme

Kullanıcı daha önce sitenize kamera erişimi izni vermediyse getUserMedia yöntemini çağırdığınız anda tarayıcı, kullanıcıdan sitenize kamera izni vermesini ister.

Kullanıcılar, makinelerindeki güçlü cihazlara erişim izni istenmesinden hoşlanmaz. Bu nedenle, isteği genellikle engellerler veya istemin oluşturulduğu bağlamı anlamazlarsa yok sayarlar. Kameraya erişim iznini yalnızca ilk ihtiyaç duyulduğunda istemek en iyi uygulamadır. Kullanıcı erişim izni verdikten sonra tekrar sorulmaz. Ancak erişim izni reddedilirse kullanıcıdan izin istemek için tekrar erişim elde edemezsiniz.

Erişiminiz olup olmadığını kontrol etmek için Permissions API'yi kullanın.

getUserMedia API'si, kameraya erişiminiz olup olmadığı konusunda bilgi vermez. Bu durum, kullanıcıdan kameraya erişim izni almak için güzel bir kullanıcı arayüzü sunmanız gerektiğinden bir sorun teşkil eder. Kameraya erişim izni istemeniz gerekir.

Bu sorun, bazı tarayıcılarda Permission API kullanılarak çözülebilir. navigator.permission API'si, tekrar istemde bulunmak zorunda kalmadan belirli API'lere erişme özelliğinin durumunu sorgulamanıza olanak tanır.

Kullanıcının kamerasına erişiminiz olup olmadığını sorgulamak için sorgu yöntemine {name: 'camera'} değerini iletebilirsiniz. Bu yöntem, aşağıdaki değerlerden birini döndürür:

  • granted: Kullanıcı daha önce kameraya erişim izni vermiştir.
  • prompt: Kullanıcı size erişim izni vermemiştir ve getUserMedia numaralı telefonu aradığınızda kullanıcıdan izin istenir.
  • denied: Sistem veya kullanıcı, kameraya erişimi açıkça engelledi ve kameraya erişemezsiniz.

Kullanıcının yapması gereken işlemleri barındırmak için kullanıcı arayüzünüzü değiştirmeniz gerekip gerekmediğini hızlıca kontrol edebilirsiniz.

navigator.permissions.query({name: 'camera'}).then(function (result) {
  if (result.state == 'granted') {
  } else if (result.state == 'prompt') {
  } else if (result.state == 'denied') {
  }
  result.onchange = function () {};
});

Geri bildirim