ব্যবহারকারীর থেকে ভিডিও রেকর্ড করা হচ্ছে

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() নামক API ব্যবহার করে সরাসরি ক্যামেরা অ্যাক্সেস করতে পারি। getUserMedia() ব্যবহারকারীকে তার কানেক্ট করা মাইক্রোফোন এবং ক্যামেরা অ্যাক্সেস করার জন্য প্রম্পট করবে।

সফল হলে, API একটি Stream রিটার্ন করবে যাতে ক্যামেরা বা মাইক্রোফোন থেকে পাওয়া ডেটা থাকবে এবং আমরা তখন এটিকে <video> এলিমেন্টের সাথে অ্যাটাচ করতে পারব, WebRTC স্ট্রিমের সাথে অ্যাটাচ করতে পারব অথবা MediaRecorder API ব্যবহার করে সেভ করতে পারব।

ক্যামেরা থেকে ডেটা পেতে আমরা শুধু video: true কনস্ট্রেন্ট অবজেক্টে সেট করেছি যা getUserMedia() API-তে পাস করা হয়েছে

<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 ক্যানভাসের জন্য, আপনি ক্যানভাসে <video> এলিমেন্টের বর্তমান ফ্রেম আঁকতে, কন্টেক্সটের drawImage পদ্ধতি ব্যবহার করতে পারেন।

context.drawImage(myVideoElement, 0, 0);

WebGL ক্যানভাসের সাহায্যে আপনি টেক্সচারের সোর্স হিসেবে <video> এলিমেন্ট ব্যবহার করতে পারবেন।

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

মনে রাখবেন, যেকোনও ক্ষেত্রেই এটি কোনও ভিডিও চালানোর সময় বর্তমান ফ্রেম ব্যবহার করবে। একাধিক ফ্রেম প্রসেস করতে আপনাকে প্রতিবার ক্যানভাসে ভিডিওটি আবার আঁকতে হবে।

আপনি এই বিষয়ে আরও জানতে পারবেন আমাদের এই নিবন্ধ থেকে: ছবি ও ভিডিওতে রিয়েল-টাইম এফেক্ট প্রয়োগ করা।

ক্যামেরা থেকে ডেটা সেভ করুন

ক্যামেরা থেকে ডেটা সেভ করার সবচেয়ে সহজ উপায় হল MediaRecorder API ব্যবহার করা।

MediaRecorder API, 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 কল করার সাথে সাথেই ব্রাউজার ব্যবহারকারীকে আপনার সাইটকে ক্যামেরা অ্যাক্সেস করার অনুমতি দিতে প্রম্পট করবে।

ব্যবহারকারীরা তাদের মেশিনে শক্তিশালী ডিভাইসে অ্যাক্সেসের জন্য প্রম্পট পেতে ঘৃণা করে এবং তারা প্রায়শই অনুরোধটি ব্লক করবে, অথবা তারা এটি উপেক্ষা করবে যদি তারা না করে প্রম্পটটি তৈরি করা হয়েছে এমন প্রসঙ্গটি বুঝুন। প্রথমবার প্রয়োজন হলে ক্যামেরা অ্যাক্সেস করার অনুমতি চাওয়া পেশাদার পদ্ধতি। ব্যবহারকারী একবার অ্যাক্সেস প্রদান করলে তাকে আর জিজ্ঞাসা করা হবে না, তবে, তিনি অ্যাক্সেস প্রত্যাখ্যান করলে, আপনি ব্যবহারকারীর কাছে অনুমতি চাওয়ার জন্য আবার অ্যাক্সেস পাবেন না।

আপনার কাছে আগে থেকেই অ্যাক্সেস আছে কিনা তা চেক করতে অনুমতি API ব্যবহার করুন

আপনার কাছে ক্যামেরার অ্যাক্সেস আগে থেকেই আছে কিনা সেই সম্পর্কে getUserMedia API আপনাকে কোনও তথ্য প্রদান করে না। এটি আপনার জন্য একটি সমস্যা তৈরি করে, ব্যবহারকারীকে ক্যামেরার অ্যাক্সেস দেওয়ার জন্য একটি সুন্দর UI প্রদান করতে, আপনাকে ক্যামেরার অ্যাক্সেসের জন্য অনুরোধ করতে হবে।

কিছু ব্রাউজারে Permission API ব্যবহার করে এই সমস্যার সমাধান করা যেতে পারে। navigator.permission API আপনাকে আবার প্রম্পট না করেই নির্দিষ্ট API অ্যাক্সেস করার ক্ষমতার অবস্থা সম্পর্কে কোয়েরি করার অনুমতি দেয়।

ব্যবহারকারীর ক্যামেরায় আপনার অ্যাক্সেস আছে কিনা তা জানতে, আপনি কোয়েরি পদ্ধতিতে {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 () {};
});

মতামত