Giriş
Ses/video yakalama, uzun süredir web geliştirmenin en önemli hedefi olmuştur. Yıllardır bu işi yapmak için tarayıcı eklentilerine (Flash veya Silverlight) güvenmek zorunda kaldık. Haydi!
HTML5'in yardımıyla HTML5'in yükselişi, cihaz donanımına erişimde artışa yol açtı. Coğrafi konum (GPS), Orientation API (ivmeölçer), WebGL (GPU) ve Web Audio API (ses donanımı) bu konuda mükemmel örneklerdir. Bu özellikler, sistemin temel donanım özelliklerinin üzerinde yer alan üst düzey JavaScript API'lerini kullanıma sunarak inanılmaz derecede güçlü bir deneyim sağlar.
Bu eğitimde, 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()'ya giden yol
Geçmişini bilmiyorsanız getUserMedia()
API'ye nasıl ulaştığımızı anlatan ilginç bir hikaye var.
Son birkaç yılda "Media Capture API'leri"nin çeşitli varyantları geliştirildi. Birçok kişi web'de yerel cihazlara erişebilme ihtiyacının farkındaydı ancak bu durum, herkesin yeni bir spesifikasyon oluşturmasına yol açtı. İşler o kadar karıştı ki W3C sonunda bir çalışma grubu oluşturmaya karar verdi. Tek amaçları ne? Bu çılgınlığı anlamlandırın. Çok sayıda teklifi birleştirip standartlaştırmak için Cihaz API'leri Politikası (DAP) Çalışma Grubu görevlendirilmiştir.
2011'de yaşananları özetlemeye çalışacağım…
1. Tur: HTML ile Medya Yakalama
HTML Media Capture, DAP'nin web'de medya yakalamayı standartlaştırma konusundaki ilk girişimiydi. Bu işlev, <input type="file">
parametresini aşırı yükleyerek ve accept
parametresi için yeni değerler ekleyerek çalışır.
Kullanıcıların web kamerasıyla kendi fotoğraflarını çekmelerine izin vermek istiyorsanız capture=camera
ile bunu yapabilirsiniz:
<input type="file" accept="image/*;capture=camera">
Video veya ses kaydetme işlemi benzerdir:
<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">
Kullanışlı, değil mi? Özellikle bir dosya girişini yeniden kullanmasını beğeniyorum. Anlamsal olarak çok mantıklı. Bu "API"nin yetersiz kaldığı nokta, gerçek zamanlı efektler uygulama (ör. canlı web kamerası verilerini <canvas>
olarak oluşturma ve WebGL filtreleri uygulama) özelliğidir.
HTML Media Capture yalnızca bir medya dosyası kaydetmenize veya anlık görüntü almanıza olanak tanır.
Destek:
- Android 3.0 tarayıcı: İlk uygulamalardan biri. Özelliğin nasıl çalıştığını 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üğünden her tür (gelecekteki) cihazı destekleyen yeni bir spesifikasyon ortaya çıktı. Bu tasarımda, getUserMedia()
öğesinin öncüsü olan <device>
öğesi kullanıldı.
Opera, <device>
öğesine dayalı video yakalama ilk uygulamalarını oluşturan ilk tarayıcılardan biriydi. Kısa bir süre sonra (tam olarak aynı gün), WhatWG, <device>
etiketini bırakıp bu kez navigator.getUserMedia()
adlı bir JavaScript API'si olan başka bir yeni etiketi kullanmaya karar verdi. Bir hafta sonra Opera, güncellenmiş getUserMedia()
spesifikasyonunu destekleyen yeni derlemeler yayınladı. Aynı yılın ilerleyen dönemlerinde Microsoft, yeni spesifikasyonu destekleyen IE9 için bir Laboratuvar yayınlayarak bu akıma katıldı.
<device>
şu şekilde görünürdü:
<device type="media" onchange="update(this.data)"></device>
<video autoplay></video>
<script>
function update(stream) {
document.querySelector('video').src = stream.url;
}
</script>
Destek:
Maalesef hiçbir yayınlanmış tarayıcıda <device>
yer almadı.
Sanırım endişelenecek bir API daha az :) <device>
'nın iki harika özelliği vardı: 1) Semantikti ve 2) Ses/video cihazlarından daha fazlasını destekleyecek şekilde kolayca genişletilebiliyordu.
Bir nefes alın. Bu tür içerikler hızla yayılır.
3. Tur: WebRTC
<device>
öğesi sonunda kullanımdan kaldırıldı.
Uygun bir yakalama API'si bulma hızı, daha büyük WebRTC (Web Tabanlı Gerçek Zamanlı İletişim) sayesinde hızlandı. Bu spesifikasyon, W3C WebRTC Çalışma Grubu tarafından denetlenir. Google, Opera, Mozilla ve birkaç başka tarayıcıda bu özellik uygulanmaktadır.
getUserMedia()
, bu API'ler grubuna erişim noktası olduğundan WebRTC ile ilişkilidir.
Kullanıcının yerel kamera/mikrofon akışına erişim imkanı sağlar.
Destek:
getUserMedia()
, Chrome 21, Opera 18 ve Firefox 17'den beri desteklenmektedir.
Başlarken
navigator.mediaDevices.getUserMedia()
ile nihayet bir eklenti olmadan web kamerası ve mikrofon girişinden yararlanabiliriz.
Kamera erişimi artık yükleme değil, arama gerektiriyor. Bu özellik doğrudan tarayıcıya entegre edilmiştir. Heyecanlandınız mı?
Özellik algılama
Özellik algılama, navigator.mediaDevices.getUserMedia
özelliğinin varlığını kontrol eden basit bir işlemdir:
if (navigator.mediaDevices?.getUserMedia) {
// Good to go!
} else {
alert("navigator.mediaDevices.getUserMedia() is not supported");
}
Giriş cihazına erişme
Web kamerasını veya mikrofonu kullanmak için izin istememiz gerekir.
navigator.mediaDevices.getUserMedia()
işlevinin ilk parametresi, erişmek istediğiniz her medya türüyle ilgili ayrıntıları ve koşulları 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}
değerini iletin:
<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. Peki burada neler oluyor? Medya yakalama, birlikte çalışan yeni HTML5 API'lerinin mükemmel bir örneğidir. Bu özellik, diğer HTML5 yardımcılarımız olan <audio>
ve <video>
ile birlikte çalışır.
src
özelliği ayarlamadığımızı veya <video>
öğesine <source>
öğeleri eklemediğimizi unutmayın. Videoya medya dosyası URL'si iletmek yerine, srcObject
öğesini web kamerasını temsil eden LocalMediaStream
nesnesine ayarlıyoruz.
Ayrıca <video>
'ya autoplay
demesini de söylüyorum. Aksi takdirde, ilk karede donup kalır. controls
eklemek de beklediğiniz gibi çalışır.
Medya kısıtlamalarını ayarlama (çözünürlük, yükseklik, genişlik)
getUserMedia()
işlevinin ilk parametresi, döndürülen medya akışıyla ilgili daha fazla koşul (veya kısıtlama) belirtmek için de kullanılabilir. Örneğin, yalnızca videoya temel erişim istediğinizi belirtmek yerine (ör. {video: true}
) akışın HD olmasını da isteyebilirsiniz:
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 kısıtlamalar API'si başlıklı makaleyi inceleyin.
Medya kaynağı seçme
enumerateDevices()
arayüzünün MediaDevices
yöntemi, mikrofon, kamera, kulaklık vb. gibi kullanılabilir medya giriş ve çıkış cihazlarının listesini ister. Döndürülen Promise, cihazları açıklayan MediaDeviceInfo
nesneleri dizisiyle çözümlenir.
Bu örnekte, bulunan son mikrofon ve kamera medya akışı kaynağı olarak seçilir:
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);
}
Kullanıcıların medya kaynağını seçmesine nasıl izin vereceğinizle ilgili Sam Dutton'ın harika demosuna göz atın.
Güvenlik
Tarayıcılar, navigator.mediaDevices.getUserMedia()
çağrıldığında bir izin iletişim kutusu gösterir. Bu iletişim kutusu, kullanıcılara kamera/mikrofon erişimi verme veya reddetme seçeneği sunar. Örneğin, Chrome'un izin iletişim kutusu aşağıda gösterilmiştir:

Yedek sunma
navigator.mediaDevices.getUserMedia()
desteği olmayan kullanıcılar için bir seçenek, API desteklenmiyorsa ve/veya çağrı herhangi bir nedenle başarısız olursa mevcut bir video dosyasına geri dönmektir:
if (!navigator.mediaDevices?.getUserMedia) {
video.src = "fallbackvideo.webm";
} else {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = stream;
}