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

मैट स्केल

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

आसान शुरुआत करें और धीरे-धीरे आगे बढ़ें

सबसे आसान तरीका है कि उपयोगकर्ता से पहले से रिकॉर्ड की गई फ़ाइल के लिए कहें. ऐसा करने के लिए, एक आसान फ़ाइल इनपुट एलिमेंट बनाएं और एक 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() API को पास किए गए कंस्ट्रेंट ऑब्जेक्ट में अभी 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 को कॉल करते समय आपको जिस deviceId का इस्तेमाल करना है उसे पास करें.

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

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

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

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

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

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

कुछ ब्राउज़र में, अनुमति वाले एपीआई का इस्तेमाल करके, इस समस्या को हल किया जा सकता है. 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 () {};
});

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