HTML5 में ऑडियो और वीडियो कैप्चर करें

परिचय

ऑडियो/वीडियो कैप्चर करना, लंबे समय से वेब डेवलपमेंट के लिए सबसे अहम रहा है. कई सालों तक, हमें इस काम के लिए ब्राउज़र प्लग इन (Flash या Silverlight) पर निर्भर रहना पड़ा. क्या कह रहे हो!

HTML5 की मदद से. शायद यह साफ़ तौर पर न दिखे, लेकिन HTML5 के आने से डिवाइस के हार्डवेयर को ऐक्सेस करने की सुविधा काफ़ी बढ़ गई है. जियोलोकेशन (जीपीएस), ओरिएंटेशन एपीआई (ऐक्सेलरोमीटर), WebGL (जीपीयू), और Web Audio API (ऑडियो हार्डवेयर) इसके बेहतरीन उदाहरण हैं. ये सुविधाएं बहुत दमदार हैं. ये सिस्टम के हार्डवेयर की क्षमताओं के ऊपर मौजूद, हाई लेवल JavaScript एपीआई को एक्सपोज़ करती हैं.

इस ट्यूटोरियल में, एक नए एपीआई GetUserMedia के बारे में बताया गया है. इसकी मदद से, वेब ऐप्लिकेशन किसी उपयोगकर्ता के कैमरे और माइक्रोफ़ोन को ऐक्सेस कर सकते हैं.

getUserMedia() का सफ़र

अगर आपको इसके इतिहास के बारे में नहीं पता है, तो getUserMedia() एपीआई तक पहुंचने का हमारा सफ़र एक दिलचस्प कहानी है.

पिछले कुछ सालों में, "मीडिया कैप्चर एपीआई" के कई वैरिएंट डेवलप हुए हैं. कई लोगों को यह महसूस हुआ कि वेब पर नेटिव डिवाइसों को ऐक्सेस करने की सुविधा होनी चाहिए. हालांकि, इस वजह से हर कोई एक नई स्पेसिफ़िकेशन बनाने में जुट गया. इससे चीज़ें इतनी उलझ गईं कि आखिरकार W3C को एक वर्किंग ग्रुप बनाना पड़ा. उनका मकसद क्या है? इस पागलपन को समझें! डिवाइस एपीआई पॉलिसी (डीएपी) वर्किंग ग्रुप को कई प्रस्तावों को इकट्ठा करने और उन्हें स्टैंडर्ड बनाने का काम सौंपा गया है.

मैं 2011 में हुई घटनाओं को कम शब्दों में बताने की कोशिश करूंगा…

पहला राउंड: एचटीएमएल मीडिया कैप्चर

एचटीएमएल मीडिया कैप्चर, डीएपी की पहली कोशिश थी, ताकि वेब पर मीडिया कैप्चर करने की सुविधा को स्टैंडर्ड बनाया जा सके. यह <input type="file"> को ओवरलोड करके और accept पैरामीटर के लिए नई वैल्यू जोड़कर काम करता है.

अगर आपको उपयोगकर्ताओं को वेबकैम से अपना स्नैपशॉट लेने की सुविधा देनी है, तो capture=camera का इस्तेमाल करें:

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

वीडियो या ऑडियो रिकॉर्ड करने का तरीका एक जैसा है:

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

यह काफ़ी अच्छा है, है न? मुझे खास तौर पर यह पसंद आया कि इसमें फ़ाइल इनपुट का फिर से इस्तेमाल किया जा सकता है. सिमैंटिक तौर पर, यह काफ़ी सही है. इस "एपीआई" में रीयल टाइम इफ़ेक्ट की सुविधा नहीं है. उदाहरण के लिए, लाइव वेबकैम डेटा को <canvas> पर रेंडर करना और WebGL फ़िल्टर लागू करना. एचटीएमएल मीडिया कैप्चर की मदद से, सिर्फ़ मीडिया फ़ाइल रिकॉर्ड की जा सकती है या स्नैपशॉट लिया जा सकता है.

सहायता:

  • Android 3.0 ब्राउज़र - यह सबसे पहले लागू किए गए ब्राउज़र में से एक है. इसका उदाहरण देखने के लिए, यह वीडियो देखें.
  • Android के लिए Chrome (0.16)
  • Firefox Mobile 10.0
  • iOS6 Safari और Chrome (आंशिक सहायता)

दूसरा राउंड: डिवाइस एलिमेंट

कई लोगों को लगा कि एचटीएमएल मीडिया कैप्चर में बहुत कम सुविधाएं हैं. इसलिए, एक नया स्पेसिफ़िकेशन सामने आया, जो आने वाले समय में किसी भी तरह के डिवाइस के साथ काम कर सकता है. इसमें कोई हैरानी की बात नहीं है कि इस डिज़ाइन के लिए एक नए एलिमेंट की ज़रूरत थी. यह एलिमेंट था <device> एलिमेंट, जो getUserMedia() का पूर्वज बना.

Opera उन शुरुआती ब्राउज़र में से एक था जिन्होंने <device> एलिमेंट के आधार पर, वीडियो कैप्चर करने की सुविधा को शुरुआती तौर पर लागू किया. इसके तुरंत बाद (सटीक तौर पर उसी दिन), WhatWG ने <device> टैग को हटाने का फ़ैसला किया. इसकी जगह, एक नए और बेहतर JavaScript API को शामिल किया गया, जिसका नाम था navigator.getUserMedia(). एक हफ़्ते बाद, Opera ने नए बिल्ड रिलीज़ किए. इनमें अपडेट किए गए getUserMedia() स्पेसिफ़िकेशन के लिए सहायता शामिल थी. उसी साल, Microsoft ने भी नए स्पेसिफ़िकेशन के साथ IE9 के लिए लैब रिलीज़ की.

<device> ऐसा दिखता:

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

सहायता:

माफ़ करें, रिलीज़ किए गए किसी भी ब्राउज़र में <device> शामिल नहीं है. मुझे लगता है कि अब आपको एक कम एपीआई के बारे में चिंता करनी होगी :) हालांकि, <device> में दो बेहतरीन चीज़ें थीं: 1.) यह सिमैंटिक था और 2.) इसे ऑडियो/वीडियो डिवाइसों के अलावा, अन्य डिवाइसों के साथ भी आसानी से इस्तेमाल किया जा सकता था.

सांस लें. यह बहुत तेज़ी से आगे बढ़ता है!

तीसरा राउंड: WebRTC

<device> एलिमेंट को आखिरकार हटा दिया गया.

WebRTC (वेब रीयल टाइम कम्यूनिकेशन) की मदद से, कैप्चर करने के लिए सही एपीआई ढूंढने की प्रोसेस तेज़ हो गई. इस खास जानकारी की निगरानी, W3C WebRTC वर्किंग ग्रुप करता है. Google, Opera, Mozilla, और कुछ अन्य ब्राउज़र में यह सुविधा उपलब्ध है.

getUserMedia(), WebRTC से जुड़ा है, क्योंकि यह एपीआई के उस सेट का गेटवे है. यह उपयोगकर्ता के लोकल कैमरे/माइक्रोफ़ोन स्ट्रीम को ऐक्सेस करने का तरीका उपलब्ध कराता है.

सहायता:

getUserMedia(), Chrome 21, Opera 18, और Firefox 17 के बाद के वर्शन पर काम करता है.

शुरू करना

navigator.mediaDevices.getUserMedia() की मदद से, अब हम बिना किसी प्लग इन के वेबकैम और माइक्रोफ़ोन इनपुट का इस्तेमाल कर सकते हैं. अब कैमरा ऐक्सेस करने के लिए, आपको कोई ऐप्लिकेशन इंस्टॉल करने की ज़रूरत नहीं है. बस एक कॉल करें और कैमरा ऐक्सेस करें. यह सीधे ब्राउज़र में मौजूद है. क्या आप उत्साहित हैं?

सुविधा का पता लगाने की सुविधा

सुविधा की पहचान करने के लिए, navigator.mediaDevices.getUserMedia की मौजूदगी की जांच की जाती है:

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

इनपुट डिवाइस का ऐक्सेस पाना

वेबकैम या माइक्रोफ़ोन का इस्तेमाल करने के लिए, हमें अनुमति लेनी होगी. navigator.mediaDevices.getUserMedia() का पहला पैरामीटर एक ऑब्जेक्ट है, जो हर उस मीडिया टाइप की जानकारी और ज़रूरी शर्तों के बारे में बताता है जिसे आपको ऐक्सेस करना है. उदाहरण के लिए, अगर आपको वेबकैम को ऐक्सेस करना है, तो पहला पैरामीटर {video: true} होना चाहिए. माइक्रोफ़ोन और कैमरा, दोनों का इस्तेमाल करने के लिए, {video: true, audio: true} पास करें:

<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>

ठीक है। तो यहां क्या हो रहा है? मीडिया कैप्चर, नए HTML5 एपीआई के साथ मिलकर काम करने का एक बेहतरीन उदाहरण है. यह हमारे अन्य HTML5 एलिमेंट, <audio> और <video> के साथ काम करता है. ध्यान दें कि हम <video> एलिमेंट पर src एट्रिब्यूट सेट नहीं कर रहे हैं या <source> एलिमेंट शामिल नहीं कर रहे हैं. वीडियो को किसी मीडिया फ़ाइल का यूआरएल देने के बजाय, हम srcObject को वेबकैम दिखाने वाले LocalMediaStream ऑब्जेक्ट पर सेट कर रहे हैं.

मैं <video> को autoplay करने के लिए भी कह रहा हूं. ऐसा न करने पर, यह पहले फ़्रेम पर ही फ़्रीज़ हो जाएगा. controls को जोड़ने पर भी, आपको उम्मीद के मुताबिक नतीजे मिलेंगे.

मीडिया की सीमाएं सेट करना (रिज़ॉल्यूशन, ऊंचाई, चौड़ाई)

getUserMedia() के पहले पैरामीटर का इस्तेमाल, वापस की गई मीडिया स्ट्रीम पर ज़्यादा ज़रूरी शर्तों (या पाबंदियों) के बारे में बताने के लिए भी किया जा सकता है. उदाहरण के लिए, सिर्फ़ यह बताने के बजाय कि आपको वीडियो का बेसिक ऐक्सेस चाहिए (जैसे, {video: true}), यह भी बताया जा सकता है कि आपको एचडी क्वालिटी में स्ट्रीम चाहिए:

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);

ज़्यादा कॉन्फ़िगरेशन के लिए, constraints API देखें.

मीडिया सोर्स चुनना

MediaDevices इंटरफ़ेस का enumerateDevices() तरीका, उपलब्ध मीडिया इनपुट और आउटपुट डिवाइसों की सूची का अनुरोध करता है. जैसे, माइक्रोफ़ोन, कैमरे, हेडसेट वगैरह. डिवाइसों के बारे में जानकारी देने वाले MediaDeviceInfo ऑब्जेक्ट के कलेक्शन के साथ, रिटर्न किया गया प्रॉमिस रिज़ॉल्व हो जाता है.

इस उदाहरण में, मीडिया स्ट्रीम के सोर्स के तौर पर, आखिरी बार इस्तेमाल किए गए माइक्रोफ़ोन और कैमरे को चुना गया है:

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

सैम डटन का शानदार डेमो देखें. इसमें बताया गया है कि उपयोगकर्ताओं को मीडिया सोर्स चुनने की अनुमति कैसे दी जाए.

सुरक्षा

navigator.mediaDevices.getUserMedia() को कॉल करने पर, ब्राउज़र अनुमति वाला डायलॉग बॉक्स दिखाते हैं. इससे उपयोगकर्ताओं को अपने कैमरे/माइक्रोफ़ोन का ऐक्सेस देने या न देने का विकल्प मिलता है. उदाहरण के लिए, यहां Chrome का अनुमति वाला डायलॉग बॉक्स दिया गया है:

Chrome में अनुमति वाला डायलॉग बॉक्स
Chrome में अनुमति वाला डायलॉग बॉक्स

फ़ॉलबैक उपलब्ध कराना

जिन उपयोगकर्ताओं के पास navigator.mediaDevices.getUserMedia() के लिए सहायता नहीं है उनके लिए एक विकल्प यह है कि अगर एपीआई काम नहीं करता है और/या किसी वजह से कॉल नहीं हो पाता है, तो वे किसी मौजूदा वीडियो फ़ाइल का इस्तेमाल करें:

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