HTML5 ile ses ve video yakalama

Giriş

Ses/Görüntü yakalama, uzun süredir web geliştirmenin hedefi. Uzun yıllar boyunca bu işi yapabilmek için tarayıcı eklentilerine (Flash veya Silverlight) güvenmek zorunda kaldık. Haydi!

HTML5 imdadınıza yetişir. Bu çok belirgin olmasa da, HTML5'in yükselişi sayesinde cihaz donanımına erişimde ani bir artış yaşandı. Coğrafi Konum (GPS), Orientation API (ivme ölçer), WebGL (GPU) ve Web Audio API (ses donanımı) harika örneklerdir. Bu özellikler inanılmaz derecede güçlüdür ve sistemin temel donanım özelliklerinin yanında bulunan üst düzey JavaScript API'lerini ortaya çıkarır.

Bu eğiticide, web uygulamalarının kullanıcının kamerasına ve mikrofonuna erişmesine olanak tanıyan yeni bir API olan GetUserMedia tanıtılmaktadır.

getUserMedia() yolu

Geçmişinden haberdar değilseniz getUserMedia() API'ya ulaşma şeklimiz ilginç bir hikayedir.

"Medya Yakalama API'lerinin" çeşitli varyantları son birkaç yıl içinde gelişmiştir. Birçok kişi web'deki yerel cihazlara erişme ihtiyacının farkındaydı, ancak bu durum herkesi ve annelerini yeni bir spesifikasyon oluşturmaya yöneltti. İşler o kadar karmaşıktı ki W3C sonunda bir çalışma grubu oluşturmaya karar verdi. Tek amacı ne mi? Bu çılgınlığı anlayın! Cihaz API'leri Politikası (DAP) Çalışma Grubu, çok sayıda teklifi birleştirmek ve standart hale getirmekle görevlendirilmiştir.

2011'de neler olduğunu özetlemeye çalışacağım...

1. Tur: HTML Medyası Yakalama

HTML Media Capture, DAP'nin web'de medya yakalamayı standartlaştırmak için yaptığı ilk şeydi. Bu, <input type="file"> öğesinin aşırı yüklenmesi ve accept parametresi için yeni değerler eklenmesiyle çalışır.

Kullanıcıların web kamerasıyla kendi fotoğraflarını çekmelerine izin vermek istiyorsanız, capture=camera ile bu mümkündür:

<input type="file" accept="image/*;capture=camera">

Video veya ses kaydı şu şekildedir:

<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">

Biraz hoş, değil mi? Özellikle bir dosya girişini yeniden kullanmasını seviyorum. Anlamsal olarak çok mantıklı. Bu "API" yetersiz kalırsa gerçek zamanlı efektler uygulayabilme imkanıdır (ör. canlı web kamerası verilerini bir <canvas> öğesine oluşturma ve WebGL filtreleri uygulama). HTML Media Capture yalnızca bir medya dosyasını kaydetmenize veya anlık bir görüntü almanıza izin verir.

Destek:

  • Android 3.0 tarayıcı - İlk uygulamalardan biri. İşleyiş şeklini görmek için bu videoya göz atın.
  • Android için Chrome (0.16)
  • Firefox Mobile 10.0
  • iOS6 Safari ve Chrome (kısmi destek)

2. tur: Cihaz öğesi

Birçok kişi HTML Media Capture'ın çok sınırlayıcı olduğunu düşündü ve bu yüzden her türlü (gelecek) cihazı destekleyen yeni bir özellik ortaya çıktı. Beklendiği gibi tasarım, getUserMedia() öğesinin öncekisi haline gelen yeni bir öğe olan <device> öğesini gerekli kılıyordu.

Opera, <device> öğesine dayalı video yakalama ilk uygulamalarını oluşturan ilk tarayıcılardan biridir. Kısa bir süre sonra (tam olarak belirtmek gerekirse aynı gün) WhatWG, <device> etiketini kaldırıp gelen başka bir etiket kullanmaya karar verdi. Bu sefer de navigator.getUserMedia() adlı JavaScript API'si kullanılmaya başlandı. Bir hafta sonra Opera, güncellenen getUserMedia() spesifikasyonunu destekleyen yeni derlemeler yayınladı. Aynı yılın ilerleyen dönemlerinde Microsoft, yeni spesifikasyonu destekleyen IE9 için bir Lab yayınlayarak bu partilere katıldı.

<device> şöyle görünmelidir:

<device type="media" onchange="update(this.data)"></device>
<video autoplay></video>
<script>
  function update(stream) {
    document.querySelector('video').src = stream.url;
  }
</script>

Destek:

Maalesef yayınlanan hiçbir tarayıcı <device> dahil edilmemiştir. Sanırım endişelenmenize gerek yok :) <device>, bunun için iki harika avantaja sahipti: 1.) anlamsaldı ve 2.) ses/video cihazlarından daha fazlasını destekleyecek şekilde kolayca genişletildi.

Derin bir nefes alın. Bu işler hızlı ilerler!

3. Tur: WebRTC

<device> öğesi sonunda Dodo'nun yöntemini uyguladı.

Daha büyük olan WebRTC (Gerçek Zamanlı Web İletişimi) çabaları sayesinde uygun bir yakalama API'si bulma hızı arttı. Bu spesifikasyon, W3C WebRTC Çalışma Grubu tarafından denetlenir. Google, Opera, Mozilla ve diğer birkaç şirket için bazı uygulamalar bulunmaktadır.

getUserMedia(), ilgili API grubuna ağ geçidi olduğu için WebRTC ile ilgilidir. Kullanıcının yerel kamera/mikrofon akışına erişim sağlar.

Destek:

getUserMedia(); Chrome 21, Opera 18 ve Firefox 17'den beri desteklenmektedir.

Başlarken

navigator.mediaDevices.getUserMedia() ile nihayet bir eklenti kullanmadan web kamerasına ve mikrofon girişine dokunabiliyoruz. Kamera erişimi artık bir kurulum uzaklıkta değil, bir telefon kadar yakın. Doğrudan tarayıcıya eklenir. Heyecanlandınız mı?

Özellik algılama

Özellik algılama, navigator.mediaDevices.getUserMedia öğesinin mevcut olup olmadığına yönelik basit bir kontroldür:

if (navigator.mediaDevices?.getUserMedia) {
  // Good to go!
} else {
  alert("navigator.mediaDevices.getUserMedia() is not supported");
}

Giriş cihazına erişim kazanma

Web kamerasını veya mikrofonu kullanmak için izin istememiz gerekiyor. navigator.mediaDevices.getUserMedia() öğesinin ilk parametresi, erişmek istediğiniz her medya türünün ayrıntılarını ve gereksinimlerini belirten bir nesnedir. Örneğin, web kamerasına erişmek istiyorsanız ilk parametre {video: true} olmalıdır. Hem mikrofonu hem de kamerayı kullanmak için {video: true, audio: true} geçin:

<video autoplay></video>

<script>
  navigator.mediaDevices
    .getUserMedia({ video: true, audio: true })
    .then((localMediaStream) => {
      const video = document.querySelector("video");
      video.srcObject = localMediaStream;
    })
    .catch((error) => {
      console.log("Rejected!", error);
    });
</script>

Tamam'a dokunun. Burada ne oluyor? Medya yakalama, yeni HTML5 API'larının birlikte çalışmasına mükemmel bir örnektir. Diğer HTML5 arkadaşlarımız <audio> ve <video> ile birlikte çalışır. <video> öğesinde bir src özelliği ayarlamadığımıza veya <source> öğeleri eklemediğimize dikkat edin. Videoyu bir medya dosyasının URL'sini beslemek yerine, srcObject özelliğini web kamerasını temsil eden LocalMediaStream nesnesine ayarlıyoruz.

<video> öğesine de autoplay talimatını veriyorum, aksi takdirde ilk karede donacaktı. controls ekleme işlemi de beklediğiniz gibi çalışıyor.

Medya kısıtlamalarını (çözünürlük, yükseklik, genişlik) ayarlama

getUserMedia() işlevinin ilk parametresi, döndürülen medya akışıyla ilgili daha fazla gereksinim (veya sınırlama) belirtmek için de kullanılabilir. Örneğin, sadece videoya temel erişim istediğinizi (ör. {video: true}) belirtmek yerine akışın HD olmasını da gerekli kılabilirsiniz:

const hdConstraints = {
  video: { width: { exact:  1280} , height: { exact: 720 } },
};

const stream = await navigator.mediaDevices.getUserMedia(hdConstraints);
const vgaConstraints = {
  video: { width: { exact:  640} , height: { exact: 360 } },
};

const stream = await navigator.mediaDevices.getUserMedia(hdConstraints);

Daha fazla yapılandırma için restrictionts API'ye bakın.

Medya kaynağı seçme

MediaDevices arayüzünün enumerateDevices() yöntemi; mikrofon, kamera, mikrofonlu kulaklık gibi kullanılabilir medya giriş ve çıkış cihazlarının listesini ister. Döndürülen Promise, cihazları açıklayan MediaDeviceInfo nesne dizisiyle çözümlenir.

Bu örnekte, bulunan son mikrofon ve kamera medya akışı kaynağı olarak seçilmiştir:

if (!navigator.mediaDevices?.enumerateDevices) {
  console.log("enumerateDevices() not supported.");
} else {
  // List cameras and microphones.
  navigator.mediaDevices
    .enumerateDevices()
    .then((devices) => {
      let audioSource = null;
      let videoSource = null;

      devices.forEach((device) => {
        if (device.kind === "audioinput") {
          audioSource = device.deviceId;
        } else if (device.kind === "videoinput") {
          videoSource = device.deviceId;
        }
      });
      sourceSelected(audioSource, videoSource);
    })
    .catch((err) => {
      console.error(`${err.name}: ${err.message}`);
    });
}

async function sourceSelected(audioSource, videoSource) {
  const constraints = {
    audio: { deviceId: audioSource },
    video: { deviceId: videoSource },
  };
  const stream = await navigator.mediaDevices.getUserMedia(constraints);
}

Sam Dutton'un, kullanıcıların medya kaynağını seçmelerine nasıl olanak sağlayacağını gösteren harika demosuna göz atın.

Güvenlik

Tarayıcılar navigator.mediaDevices.getUserMedia() çağırdığında bir izin iletişim kutusu gösterir. Bu iletişim kutusu, kullanıcılara kameralarına/mikrofonlarına erişim izni verme veya erişimi reddetme seçeneği sunar. Örneğin, Chrome'un izin iletişim kutusunu aşağıda görebilirsiniz:

Chrome&#39;daki izin iletişim kutusu
Chrome'daki izin iletişim kutusu

Yedek sağlanıyor

navigator.mediaDevices.getUserMedia() desteği olmayan kullanıcılar için, API desteklenmiyorsa ve/veya çağrı bir nedenden dolayı başarısız olursa mevcut bir video dosyasını yedek olarak kullanabilirsiniz:

if (!navigator.mediaDevices?.getUserMedia) {
  video.src = "fallbackvideo.webm";
} else {
  const stream = await navigator.mediaDevices.getUserMedia({ video: true });
  video.srcObject = stream;
}