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

परिचय

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

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

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

getUserMedia() का इस्तेमाल करने का तरीका

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

पिछले कुछ सालों में, "Media Capture API" के कई वैरिएंट बेहतर हुए हैं. कई लोगों ने वेब पर नेटिव डिवाइसों को ऐक्सेस करने की ज़रूरत को समझा, लेकिन इससे सभी ने एक नई खास जानकारी इकट्ठा की. मामला इतना बिगड़ गया कि 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 फ़िल्टर लागू करना) करने की सुविधा उपलब्ध है. HTML मीडिया कैप्चर आपको सिर्फ़ मीडिया फ़ाइल रिकॉर्ड करने या समय पर स्नैपशॉट लेने की अनुमति देता है.

सहायता:

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

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

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

Opera, उन पहले ब्राउज़र में से एक था जिसने <device> एलिमेंट के आधार पर, वीडियो कैप्चर करने की सुविधा को शुरुआती तौर पर लागू किया था. इसके कुछ समय बाद (उसी दिन), WhatWG ने <device> टैग को हटाने का फ़ैसला लिया. इसकी जगह, एक नए टैग को इस्तेमाल करने का फ़ैसला लिया गया. यह टैग, navigator.getUserMedia() नाम का JavaScript API था. एक हफ़्ते बाद, 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 API के साथ काम करने का बेहतरीन उदाहरण है. यह हमारे अन्य एचटीएमएल5 एट्रिब्यूट, <audio> और <video> के साथ काम करता है. ध्यान दें कि हम src एट्रिब्यूट सेट नहीं कर रहे हैं या <video> एलिमेंट में <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;
}