Kullanıcının Videosunu Kaydetme

Mat Scales

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

Basit ve kademeli bir şekilde başlayın

En kolay yöntem, kullanıcıdan önceden kaydedilmiş bir dosya istemektir. Bunu yapmak için basit bir dosya girişi öğesi oluşturun ve yalnızca video dosyalarını kabul edebileceğimizi belirten bir accept filtresi ve dosyayı 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'teki Safari'de kamera uygulaması açılır. Bu uygulama, videoyu kaydetmenizi ve ardından videoyu web sayfasına geri göndermenizi sağlar. Android'de ise kullanıcıya, videoyu web sayfasına geri göndermeden önce hangi uygulamada kaydedileceğini seçme hakkı verilir.

Birçok mobil cihazın birden fazla kamerası vardır. Tercihiniz varsa kameranın kullanıcıya dönük olmasını istiyorsanız capture özelliğini user, kameranın dışa dönük olmasını 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ü kullanılamıyorsa tarayıcı başka bir kamera seçebilir.

Kullanıcı kayıt işlemini tamamlayıp web sitesine geri döndüğünde, dosya verilerini bir şekilde almanız gerekir. Giriş öğesine bir onchange etkinliği ekleyip ardından etkinlik nesnesinin files özelliğini okuyarak hızlı erişim elde edebilirsiniz.

<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ştikten sonra istediğiniz işlemi yapabilirsiniz. Örneğin, şunları yapabilirsiniz:

  • Oynayabilmek için doğrudan bir <video> öğesine ekleyin.
  • Kullanıcının cihazına indirin
  • XMLHttpRequest dosyasına ekleyerek bir sunucuya yükleyin.
  • Çerçeveleri bir kanvas üzerine çizip filtre uygulayın

Video verilerine erişmek için giriş öğesi yöntemini kullanmak yaygın olsa da bu yöntem en az ilgi çekici 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 bağlanabilir. Bu sayede, web sayfasıyla tamamen entegre olan ve kullanıcının tarayıcıdan hiç ayrılmadığı deneyimler oluşturabiliriz.

Kameraya erişim elde etme

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

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

Kameradan veri almak için getUserMedia() API'ye iletilen constraints nesnesinde video: true değerini ayarlamamız yeterlidir.

<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ı numaralandırabilirsiniz.

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

Ardından getUserMedia numaralı telefonu aradığınızda kullanmak istediğiniz deviceId değerini iletebilirsiniz.

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

Bu bilgi tek başına çok faydalı değildir. Tek yapabileceğimiz, video verilerini alıp oynatmaktır.

Ham verilere kameradan erişin

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

2D kanvaslarda bir <video> öğesinin geçerli karesini zemine çizmek için bağlamın drawImage yöntemini kullanabilirsiniz.

context.drawImage(myVideoElement, 0, 0);

WebGL kanvaslarında doku kaynağı olarak <video> öğesini 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 resimlere ve videolara gerçek zamanlı efekt uygulama konulu makalemizde bulabilirsiniz.

Kameradaki verileri kaydetme

Kameradaki verileri kaydetmenin en kolay yolu MediaRecorder API'yi kullanmaktır.

MediaRecorder API, getUserMedia tarafından oluşturulan akışı alır ve ardından 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>

Örneğimizde verileri doğrudan bir diziye kaydediyoruz. Daha sonra bu diziyi Blob biçimine dönüştürüyoruz. Daha sonra bu diziyi 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 sitenizin kameraya erişmesine izin vermediyse getUserMedia hizmetini çağırdığınız anda tarayıcı kullanıcıdan sitenizin kameraya erişmesine izin vermesini ister.

Kullanıcılar, makinelerindeki güçlü cihazlara erişim isteminden nefret eder ve isteği sık sık engeller ya da istemin oluşturulduğu bağlamı anlamazlarsa yoksayar. Kameraya erişimi yalnızca ilk kez ihtiyaç duyulduğunda istemek en iyi uygulamadır. Kullanıcı erişim izni verdikten sonra bu istek tekrar gösterilmez. Ancak kullanıcı erişim iznini reddederse kullanıcıdan izin istemek için tekrar erişim izni alamazsınız.

Erişiminiz olup olmadığını kontrol etmek için izinler API'sini kullanın

getUserMedia API, kameraya erişiminiz olup olmadığı konusunda size bilgi vermez. Bu durum size bir sorun teşkil eder. Kullanıcının kameraya erişim izni vermesini sağlamak için güzel bir kullanıcı arayüzü sunmanız gerekir.

Bu sorun, bazı tarayıcılarda Permission API kullanılarak çözülebilir. navigator.permission API, belirli API'lere erişme yeteneğiyle ilgili durumu tekrar istemek zorunda kalmadan sorgulamanıza olanak tanır.

Kullanıcının kamerasına erişiminiz olup olmadığını sorgulamak için sorgu yöntemine {name: 'camera'} öğesini iletebilirsiniz. İşlem, aşağıdakilerden birini döndürür:

  • granted — Kullanıcı daha önce size kamera için erişim izni verdiyse;
  • prompt — kullanıcı size erişim izni vermedi ve getUserMedia numarasını aradığınızda bu kişiden istenecek;
  • denied: Sistem veya kullanıcı kameraya erişimi açıkça engellemiştir ve kameraya erişemezsiniz.

Artık kullanıcı arayüzünüzü, kullanıcının yapması gereken işlemlere uygun olacak şekilde 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