Giriş
Ses/video yakalama, uzun zamandır web geliştirmenin en "kutsal kâsesi" olmuştur. Bu işi yapmak için yıllardır tarayıcı eklentilerine (Flash veya Silverlight) güvenmek zorunda kaldık. Hadi!
HTML5'in yardımına ihtiyacınız var. Bu durum açıkça anlaşılamayabilir ancak HTML5'in yükselişi, cihaz donanımına erişimin artmasına neden oldu. Coğrafi Konum (GPS), Orientation API (ivme ölçer), WebGL (GPU) ve Web Audio API (ses donanımı) buna mükemmel örneklerdir. Bu özellikler inanılmaz derecede güçlüdür ve sistemin temel donanım özelliklerinin üzerine yerleştirilmiş yüksek düzey JavaScript API'lerini gösterir.
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() işlevine giden yol
getUserMedia()
API'ye nasıl ulaştığımızın ilginç bir hikayesi var.
"Media Capture API'lerinin" çeşitli varyantları son birkaç yılda gelişti. Birçok kişi web'de yerel cihazlara erişebilmenin gerekliliğini fark etti, ancak bu durum herkesi yeni bir özellik oluşturmaya yöneltti. İşler o kadar karışık bir hal aldı ki W3C sonunda bir çalışma grubu oluşturmaya karar verdi. Tek amaçları bu mu? Bu çılgınlığı anlayın. Cihaz API'leri Politikası (DAP) Çalışma Grubu'na, çok sayıdaki öneriyi birleştirip standartlaştırma görevi verildi.
2011'de neler olduğunu özetlemeye çalışacağım…
1. Tur: HTML Medya Yakalama
HTML Medya Yakalama, DAP'nin web'de medya yakalamayı standartlaştırmaya yönelik ilk denemesidir. Bu yöntem, <input type="file">
parametresini aşırı yükleyerek ve accept
parametresine 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 kaydı yapmak için:
<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">
Güzel bir özellik değil mi? Özellikle dosya girişini yeniden kullanmasından hoşlandım. Anlamsal olarak bu çok mantıklı. Bu "API"nin eksik kaldığı nokta, gerçek zamanlı efektler (ör. canlı web kamerası verilerini <canvas>
olarak oluşturma ve WebGL filtreleri uygulama) oluşturma özelliğidir.
HTML Medya Yakalama yalnızca bir medya dosyası kaydetmenize veya zamanda anlık görüntü almanıza olanak tanır.
Destek:
- Android 3.0 tarayıcı: İlk uygulamalardan biridir. Bu özelliğin işleyişini bu videoda görebilirsiniz.
- Android için Chrome (0.16)
- Firefox Mobil 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üğü için her tür (gelecekteki) cihazı destekleyen yeni bir özellik ortaya çıktı. Tasarım, getUserMedia()
'ın öncülü olan yeni bir öğe (<device>
öğesi) gerektirdi.
Opera, <device>
öğesine dayalı video yakalama ilk uygulamalarını oluşturan ilk tarayıcılar arasındaydı. Bundan kısa bir süre sonra (tam olarak aynı gün), WhatWG, <device>
etiketini kullanımdan kaldırıp yerine navigator.getUserMedia()
adlı yeni bir JavaScript API'yi kullanmaya karar verdi. Bir hafta sonra Opera, güncellenmiş getUserMedia()
spesifikasyonuna destek içeren yeni derlemeler yayınladı. Aynı yılın ilerleyen dönemlerinde Microsoft da yeni spesifikasyonu destekleyen bir IE9 için Lab yayınladı.
<device>
şu şekilde görünür:
<device type="media" onchange="update(this.data)"></device>
<video autoplay></video>
<script>
function update(stream) {
document.querySelector('video').src = stream.url;
}
</script>
Destek:
Maalesef <device>
, piyasaya sürülen hiçbir tarayıcıda yer almamıştır.
Endişelenmeniz gereken bir API daha azaldı. :) <device>
'ün iki önemli özelliği vardı: 1.) anlamsaldı ve 2.) yalnızca ses/video cihazlarını değil, daha fazlasını desteklemek için kolayca genişletilebilirdi.
Derin bir nefes alın. Bu gelişmeler çok hızlı gerçekleşiyor.
3. Tur: WebRTC
<device>
öğesi zaman içinde Dodo kuşunun yolunu izledi.
Daha kapsamlı WebRTC (Web Gerçek Zamanlı İletişim) çalışmaları sayesinde uygun bir yakalama API'si bulma hızı arttı. Bu spesifikasyon, W3C WebRTC Çalışma Grubu tarafından denetlenir. Google, Opera, Mozilla ve birkaç diğer tarayıcı bu teknolojiyi kullanmaktadır.
getUserMedia()
, bu API grubuna giden ağ geçidi olduğundan WebRTC ile ilgilidir.
Kullanıcının yerel kamera/mikrofon akışına erişme olanağı sağlar.
Destek:
getUserMedia()
, Chrome 21, Opera 18 ve Firefox 17 sürümlerinden itibaren desteklenmektedir.
Başlarken
navigator.mediaDevices.getUserMedia()
sayesinde artık web kamerası ve mikrofon girişini eklenti olmadan kullanabiliyoruz.
Artık kamera erişimi için uygulama yüklemeniz gerekmiyor. Doğrudan tarayıcıya yerleştirilmiştir. Heyecanlandınız mı?
Özellik algılama
Özellik algılama, navigator.mediaDevices.getUserMedia
öğesinin 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şim
Web kamerasını veya mikrofonu kullanmak için izin almamız gerekir.
navigator.mediaDevices.getUserMedia()
parametresinin ilk parametresi, erişmek istediğiniz her medya türüne ilişkin 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}
parametresini 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, neden böyle oldu? Medya yakalama, yeni HTML5 API'lerinin birlikte çalışmasını gösteren mükemmel bir örnektir. Diğer HTML5 arkadaşlarımız <audio>
ve <video>
ile birlikte çalışır.
<video>
öğesinde src
özelliği ayarlamadığımızı veya <source>
öğeleri eklemediğimizi unutmayın. Videoya bir medya dosyasının URL'sini beslemek yerine srcObject
'ü web kamerasını temsil eden LocalMediaStream
nesnesine ayarlıyoruz.
Ayrıca <video>
'e autoplay
'yi de söylüyorum. Aksi takdirde ilk karede donar. controls
eklemek de beklediğiniz gibi çalışır.
Medya kısıtlamalarını ayarlama (çözünürlük, yükseklik, genişlik)
getUserMedia()
için ilk parametre, döndürülen medya akışıyla ilgili daha fazla koşul (veya kısıtlama) belirtmek için de kullanılabilir. Örneğin, videoya yalnızca temel erişmek istediğinizi belirtmek yerine (ör. {video: true}
) yayını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 constraints API'ye bakın.
Medya kaynağı seçme
MediaDevices
arayüzünün enumerateDevices()
yöntemi, mikrofon, kamera, kulaklık vb. gibi mevcut medya giriş ve çıkış cihazlarının listesini ister. Döndürülen Promise, cihazları açıklayan bir MediaDeviceInfo
nesnesi dizisiyle çözülür.
Bu örnekte, medya akışı kaynağı olarak bulunan son mikrofon ve kamera 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çmelerine izin vermeyle ilgili Sam Dutton'un harika demosuna göz atın.
Güvenlik
Tarayıcılarda, navigator.mediaDevices.getUserMedia()
çağrıldıktan sonra kullanıcılara kameralarına/mikrofonlarına erişim izni verme veya verme seçeneği sunan bir izin iletişim kutusu gösterilir. Örneğin, Chrome'un izin iletişim kutusu aşağıda verilmiştir:
Yedek sunma
navigator.mediaDevices.getUserMedia()
desteği olmayan kullanıcılar için API desteklenmiyorsa ve/veya çağrı bir nedenle başarısız olursa mevcut bir video dosyasına yedek olarak başvurabilirsiniz:
if (!navigator.mediaDevices?.getUserMedia) {
video.src = "fallbackvideo.webm";
} else {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = stream;
}