उपयोगकर्ता से वीडियो रिकॉर्ड करना

Mat Scales

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

सबसे आसान तरीका यह है कि उपयोगकर्ता से पहले से रिकॉर्ड की गई फ़ाइल मांगें. ऐसा करने के लिए, एक आसान फ़ाइल इनपुट एलिमेंट बनाएं और accept फ़िल्टर जोड़ें. इससे पता चलता है कि हम सिर्फ़ वीडियो फ़ाइलें स्वीकार कर सकते हैं. साथ ही, एक capture एट्रिब्यूट जोड़ें. इससे पता चलता है कि हमें इसे सीधे कैमरे से चाहिए.

<input type="file" accept="video/*" capture />

यह तरीका सभी प्लैटफ़ॉर्म पर काम करता है. डेस्कटॉप पर, यह उपयोगकर्ता से फ़ाइल सिस्टम से कोई फ़ाइल अपलोड करने के लिए कहेगा. इसमें capture एट्रिब्यूट को अनदेखा किया जाएगा. iOS पर Safari में यह कैमरा ऐप्लिकेशन खोलेगा, जिससे आप वीडियो रिकॉर्ड करके उसे वापस वेब पेज पर भेज सकते हैं; Android पर यह उपयोगकर्ता को वेब पेज पर वापस भेजने से पहले उसे चुनने का विकल्प देगा कि वीडियो रिकॉर्ड करने के लिए उसे किस ऐप्लिकेशन में रिकॉर्ड करना है.

कई मोबाइल डिवाइसों में एक से ज़्यादा कैमरे होते हैं. अगर आपकी कोई प्राथमिकता है, तो capture एट्रिब्यूट को user पर सेट करें. अगर आपको ऐसा कैमरा चाहिए जो व्यक्ति के सामने हो, या अगर आपको सामने की ओर वाला कैमरा चाहिए, तो environment को सेट करें.

<input type="file" accept="video/*" capture="user" />
<input type="file" accept="video/*" capture="environment" />

ध्यान दें कि यह सिर्फ़ एक सुझाव है - अगर ब्राउज़र में यह विकल्प काम नहीं करता है या आपने जिस कैमरे का अनुरोध किया है वह उपलब्ध नहीं है, तो ब्राउज़र कोई दूसरा कैमरा चुन सकता है.

जब उपयोगकर्ता रिकॉर्डिंग पूरी कर लेता है और वह वेबसाइट पर वापस आ जाता है, तो आपको किसी तरह से फ़ाइल का डेटा हासिल करना होगा. इनपुट एलिमेंट में onchange इवेंट अटैच करके और फिर इवेंट ऑब्जेक्ट की files प्रॉपर्टी पढ़कर, तुरंत ऐक्सेस किया जा सकता है.

<input type="file" accept="video/*" capture="camera" id="recorder" />
<video id="player" controls></video>
<script>
  var recorder = document.getElementById('recorder');
  var player = document.getElementById('player');

  recorder.addEventListener('change', function (e) {
    var file = e.target.files[0];
    // Do something with the video file.
    player.src = URL.createObjectURL(file);
  });
</script>

फ़ाइल का ऐक्सेस मिलने के बाद, उसमें अपनी पसंद के मुताबिक बदलाव किए जा सकते हैं. उदाहरण के लिए, ये काम किए जा सकते हैं:

  • इसे सीधे किसी <video> एलिमेंट से अटैच करें, ताकि आप इसे चला सकें
  • इसे उपयोगकर्ता के डिवाइस पर डाउनलोड करें
  • इसे XMLHttpRequest से अटैच करके, सर्वर पर अपलोड करें
  • फ़्रेम को कैनवस में खींचें और उन पर फ़िल्टर लगाएं

वीडियो डेटा का ऐक्सेस पाने के लिए, इनपुट एलिमेंट का तरीका हर जगह इस्तेमाल किया जाता है. हालांकि, यह सबसे कम पसंद किया जाने वाला विकल्प है. हम वाकई में कैमरे का ऐक्सेस पाना चाहते हैं और सीधे पेज पर ही अच्छा अनुभव देना चाहते हैं.

कैमरे को इंटरैक्टिव तरीके से ऐक्सेस करना

आधुनिक ब्राउज़र में कैमरे से सीधे तौर पर कनेक्ट करने की सुविधा होती है. इससे हमें वेब पेज के साथ पूरी तरह से इंटिग्रेट किए गए ऐसे अनुभव बनाने में मदद मिलती है जिनसे उपयोगकर्ता कभी ब्राउज़र से बाहर नहीं निकलता.

कैमरे का ऐक्सेस पाना

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

अगर एपीआई सफल होता है, तो एपीआई एक Stream दिखाएगा, जिसमें कैमरा या माइक्रोफ़ोन का डेटा शामिल होगा. इसके बाद, हम उसे किसी <video> एलिमेंट से अटैच कर सकते हैं, WebRTC स्ट्रीम में अटैच कर सकते हैं या MediaRecorder एपीआई का इस्तेमाल करके सेव कर सकते हैं.

कैमरे से डेटा पाने के लिए, हमने getUserMedia() एपीआई को पास किए गए constraints ऑब्जेक्ट में video: true सेट किया है

<video id="player" controls></video>
<script>
  var player = document.getElementById('player');

  var handleSuccess = function (stream) {
    player.srcObject = stream;
  };

  navigator.mediaDevices
    .getUserMedia({audio: true, video: true})
    .then(handleSuccess);
</script>

अगर आपको कोई खास कैमरा चुनना है, तो पहले उपलब्ध कैमरों की सूची देखें.

navigator.mediaDevices.enumerateDevices().then((devices) => {
  devices = devices.filter((d) => d.kind === 'videoinput');
});

इसके बाद, getUserMedia को कॉल करते समय, उस डिवाइस का आईडी पास किया जा सकता है जिसका इस्तेमाल करना है.

navigator.mediaDevices.getUserMedia({
  audio: true,
  video: {
    deviceId: devices[0].deviceId,
  },
});

यह अपने-आप इतना काम का नहीं है. हम बस वीडियो का डेटा लेकर उसे वापस चला सकते हैं.

कैमरे से रॉ डेटा ऐक्सेस करना

कैमरे से रॉ वीडियो डेटा ऐक्सेस करने के लिए, हर फ़्रेम को <canvas> में ड्रॉ किया जा सकता है और पिक्सल में सीधे बदलाव किया जा सकता है.

2D कैनवस के लिए, कैनवस में <video> एलिमेंट का मौजूदा फ़्रेम खींचने के लिए, कॉन्टेक्स्ट के drawImage तरीके का इस्तेमाल किया जा सकता है.

context.drawImage(myVideoElement, 0, 0);

WebGL कैनवस के साथ, किसी टेक्सचर के लिए सोर्स के तौर पर <video> एलिमेंट का इस्तेमाल किया जा सकता है.

gl.texImage2D(
  gl.TEXTURE_2D,
  0,
  gl.RGBA,
  gl.RGBA,
  gl.UNSIGNED_BYTE,
  myVideoElement,
);

ध्यान दें कि दोनों ही मामलों में, यह चल रहे वीडियो के मौजूदा फ़्रेम का इस्तेमाल करेगा. एक से ज़्यादा फ़्रेम प्रोसेस करने के लिए, आपको हर बार कैनवस पर वीडियो को फिर से ड्रॉ करना होगा.

इमेज और वीडियो में रीयल-टाइम इफ़ेक्ट लागू करने के बारे में हमारे लेख में, इसके बारे में ज़्यादा जानें.

कैमरे से डेटा सेव करें

कैमरे से डेटा सेव करने का सबसे आसान तरीका, MediaRecorder एपीआई का इस्तेमाल करना है.

MediaRecorder एपीआई, getUserMedia की बनाई गई स्ट्रीम को अपने-आप सेव करेगा. इसके बाद, स्ट्रीम से डेटा को आपके पसंदीदा डेस्टिनेशन पर सेव करता रहेगा.

<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
  let shouldStop = false;
  let stopped = false;
  const downloadLink = document.getElementById('download');
  const stopButton = document.getElementById('stop');

  stopButton.addEventListener('click', function() {
    shouldStop = true;
  })

  var handleSuccess = function(stream) {
    const options = {mimeType: 'video/webm'};
    const recordedChunks = [];
    const mediaRecorder = new MediaRecorder(stream, options);

    mediaRecorder.addEventListener('dataavailable', function(e) {
      if (e.data.size > 0) {
        recordedChunks.push(e.data);
      }

      if(shouldStop === true && stopped === false) {
        mediaRecorder.stop();
        stopped = true;
      }
    });

    mediaRecorder.addEventListener('stop', function() {
      downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
      downloadLink.download = 'acetest.webm';
    });

    mediaRecorder.start();
  };

  navigator.mediaDevices.getUserMedia({ audio: true, video: true })
      .then(handleSuccess);
</script>

हमारे मामले में, हम डेटा को सीधे किसी ऐरे में सेव कर रहे हैं, जिसे बाद में Blob में बदला जा सकता है. इसके बाद, इसका इस्तेमाल हमारे वेब सर्वर या उपयोगकर्ता के डिवाइस के स्टोरेज में सेव करने के लिए किया जा सकता है.

कैमरे का सही तरीके से इस्तेमाल करने के लिए अनुमति मांगना

अगर उपयोगकर्ता ने पहले कभी आपकी साइट को कैमरे का ऐक्सेस नहीं दिया है, तो getUserMedia को कॉल करने के तुरंत बाद, ब्राउज़र उपयोगकर्ता को आपकी साइट को कैमरे का ऐक्सेस देने के लिए कहेगा.

जब उपयोगकर्ता को अपने डिवाइस पर दमदार डिवाइसों के ऐक्सेस के लिए प्रॉम्प्ट मिलने से नफ़रत होती है, तो वे बार-बार अनुरोध को ब्लॉक कर देते हैं. इसके अलावा, अगर उन्हें प्रॉम्प्ट का संदर्भ नहीं पता होता, तो वे उसे अनदेखा कर देते हैं. सबसे सही तरीका यह है कि जब ज़रूरत हो, तब ही कैमरे का ऐक्सेस मांगा जाए. उपयोगकर्ता से ऐक्सेस मिलने के बाद, आपसे फिर से ऐक्सेस मांगा नहीं जाएगा. हालांकि, अगर उपयोगकर्ता ऐक्सेस देने से मना कर देता है, तो आपके पास उपयोगकर्ता से अनुमति मांगने के लिए, फिर से ऐक्सेस पाने का विकल्प नहीं होगा.

अनुमतियां एपीआई का इस्तेमाल करके देखें कि आपके पास पहले से ऐक्सेस है या नहीं

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

कुछ ब्राउज़र में, Permission API का इस्तेमाल करके इस समस्या को हल किया जा सकता है. navigator.permission एपीआई की मदद से, किसी खास एपीआई को ऐक्सेस करने की स्थिति के बारे में क्वेरी की जा सकती है. इसके लिए, आपको फिर से अनुरोध करने की ज़रूरत नहीं पड़ती.

उपयोगकर्ता के कैमरे का ऐक्सेस है या नहीं, यह पता करने के लिए क्वेरी के तरीके में {name: 'camera'} डालें. इससे आपको इनमें से कोई एक नतीजा मिलेगा:

  • granted — उपयोगकर्ता ने पहले आपको कैमरे का ऐक्सेस दिया है;
  • prompt — उपयोगकर्ता ने आपको ऐक्सेस नहीं दिया है. जब आप getUserMedia को कॉल करेंगे, तब उसे सूचना दी जाएगी;
  • denied — सिस्टम या उपयोगकर्ता ने कैमरे का ऐक्सेस साफ़ तौर पर ब्लॉक कर दिया है और आपको इसका ऐक्सेस नहीं मिलेगा.

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

navigator.permissions.query({name: 'camera'}).then(function (result) {
  if (result.state == 'granted') {
  } else if (result.state == 'prompt') {
  } else if (result.state == 'denied') {
  }
  result.onchange = function () {};
});

सुझाव/राय दें या शिकायत करें