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:
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;
}