ব্যবহারকারীর কাছ থেকে একটি ছবি ক্যাপচার করা

বেশিরভাগ ব্রাউজার ব্যবহারকারীর ক্যামেরায় অ্যাক্সেস পেতে পারে।

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

সহজ এবং ধীরে ধীরে শুরু করুন

আপনি যদি ধীরে ধীরে আপনার অভিজ্ঞতা বাড়াতে চান, তাহলে আপনাকে এমন কিছু দিয়ে শুরু করতে হবে যা সর্বত্র কাজ করে। সবচেয়ে সহজ কাজটি হল ব্যবহারকারীকে প্রাক-রেকর্ড করা ফাইলের জন্য জিজ্ঞাসা করা।

একটি URL এর জন্য জিজ্ঞাসা করুন

এটি সর্বোত্তম সমর্থিত কিন্তু কম সন্তোষজনক বিকল্প। আপনাকে একটি URL দিতে ব্যবহারকারী পান, এবং তারপর এটি ব্যবহার করুন. শুধু ইমেজ প্রদর্শনের জন্য এটি সর্বত্র কাজ করে। একটি img উপাদান তৈরি করুন, src সেট করুন এবং আপনার কাজ শেষ।

যদিও, আপনি যদি কোনও উপায়ে চিত্রটি ম্যানিপুলেট করতে চান তবে জিনিসগুলি কিছুটা জটিল। CORS আপনাকে প্রকৃত পিক্সেল অ্যাক্সেস করতে বাধা দেয় যদি না সার্ভার উপযুক্ত হেডার সেট করে এবং আপনি চিত্রটিকে ক্রসরিজিন হিসাবে চিহ্নিত করেন ; এর চারপাশে একমাত্র ব্যবহারিক উপায় হল একটি প্রক্সি সার্ভার চালানো।

ফাইল ইনপুট

আপনি একটি সাধারণ ফাইল ইনপুট উপাদানও ব্যবহার করতে পারেন, একটি accept ফিল্টার সহ যা নির্দেশ করে যে আপনি শুধুমাত্র চিত্র ফাইল চান।

<input type="file" accept="image/*" />

এই পদ্ধতিটি সমস্ত প্ল্যাটফর্মে কাজ করে। ডেস্কটপে এটি ব্যবহারকারীকে ফাইল সিস্টেম থেকে একটি ইমেজ ফাইল আপলোড করতে অনুরোধ করবে। আইওএস এবং অ্যান্ড্রয়েডের ক্রোম এবং সাফারিতে এই পদ্ধতিটি ব্যবহারকারীকে ছবি ক্যাপচার করার জন্য কোন অ্যাপ ব্যবহার করতে হবে তার একটি পছন্দ দেবে, যার মধ্যে ক্যামেরার সাথে সরাসরি একটি ছবি তোলা বা একটি বিদ্যমান চিত্র ফাইল বেছে নেওয়ার বিকল্প রয়েছে।

একটি অ্যান্ড্রয়েড মেনু, দুটি বিকল্প সহ: চিত্র এবং ফাইলগুলি ক্যাপচার করুন৷একটি iOS মেনু, তিনটি বিকল্প সহ: ফটো তুলুন, ফটো লাইব্রেরি, iCloud

তথ্য তারপর একটি <form> সাথে সংযুক্ত করা যেতে পারে বা ইনপুট উপাদানে একটি onchange ইভেন্টের জন্য শুনে এবং তারপর ইভেন্ট target files বৈশিষ্ট্য পড়ে জাভাস্ক্রিপ্টের সাথে ম্যানিপুলেট করা যেতে পারে।

<input type="file" accept="image/*" id="file-input" />
<script>
  const fileInput = document.getElementById('file-input');

  fileInput.addEventListener('change', (e) =>
    doSomethingWithFiles(e.target.files),
  );
</script>

files সম্পত্তি একটি FileList অবজেক্ট, যা আমি পরে আরও কথা বলব।

আপনি ঐচ্ছিকভাবে উপাদানটিতে capture অ্যাট্রিবিউট যোগ করতে পারেন, যা ব্রাউজারকে নির্দেশ করে যে আপনি ক্যামেরা থেকে একটি ছবি পেতে পছন্দ করেন।

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

কোনো মান ছাড়াই capture অ্যাট্রিবিউট যোগ করলে ব্রাউজার ঠিক করে দেয় কোন ক্যামেরা ব্যবহার করবে, যখন "user" এবং "environment" মান ব্রাউজারকে যথাক্রমে সামনে এবং পিছনের ক্যামেরা পছন্দ করতে বলে।

capture অ্যাট্রিবিউট অ্যান্ড্রয়েড এবং iOS এ কাজ করে, কিন্তু ডেস্কটপে উপেক্ষা করা হয়। যাইহোক, সচেতন থাকুন যে অ্যান্ড্রয়েডে এর মানে ব্যবহারকারীর কাছে আর বিদ্যমান ছবি বেছে নেওয়ার বিকল্প থাকবে না। পরিবর্তে সিস্টেম ক্যামেরা অ্যাপ সরাসরি শুরু হবে।

টানা এবং পতন

আপনি যদি ইতিমধ্যেই একটি ফাইল আপলোড করার ক্ষমতা যোগ করে থাকেন তবে কয়েকটি সহজ উপায় রয়েছে যা আপনি ব্যবহারকারীর অভিজ্ঞতাকে আরও সমৃদ্ধ করতে পারেন।

প্রথমটি হল আপনার পৃষ্ঠায় একটি ড্রপ টার্গেট যুক্ত করা যা ব্যবহারকারীকে ডেস্কটপ বা অন্য অ্যাপ্লিকেশন থেকে একটি ফাইল টেনে আনতে দেয়।

<div id="target">You can drag an image file here</div>
<script>
  const target = document.getElementById('target');

  target.addEventListener('drop', (e) => {
    e.stopPropagation();
    e.preventDefault();

    doSomethingWithFiles(e.dataTransfer.files);
  });

  target.addEventListener('dragover', (e) => {
    e.stopPropagation();
    e.preventDefault();

    e.dataTransfer.dropEffect = 'copy';
  });
</script>

ফাইল ইনপুটের অনুরূপ, আপনি drop ইভেন্টের dataTransfer.files বৈশিষ্ট্য থেকে একটি FileList অবজেক্ট পেতে পারেন;

dragover ইভেন্ট হ্যান্ডলার আপনাকে ব্যবহারকারীকে সংকেত দিতে দেয় যখন তারা dropEffect প্রপার্টি ব্যবহার করে ফাইল ড্রপ করে তখন কী ঘটবে।

ড্র্যাগ অ্যান্ড ড্রপ দীর্ঘকাল ধরে চলছে এবং প্রধান ব্রাউজারগুলি দ্বারা সমর্থিত।

ক্লিপবোর্ড থেকে পেস্ট করুন

একটি বিদ্যমান ইমেজ ফাইল পেতে চূড়ান্ত উপায় ক্লিপবোর্ড থেকে হয়. এর জন্য কোডটি খুবই সহজ, কিন্তু ব্যবহারকারীর অভিজ্ঞতা ঠিক করা একটু কঠিন।

<textarea id="target">Paste an image here</textarea>
<script>
  const target = document.getElementById('target');

  target.addEventListener('paste', (e) => {
    e.preventDefault();
    doSomethingWithFiles(e.clipboardData.files);
  });
</script>

( e.clipboardData.files হল আরেকটি FileList অবজেক্ট।)

ক্লিপবোর্ড API-এর সাথে জটিল অংশটি হল, সম্পূর্ণ ক্রস-ব্রাউজার সমর্থনের জন্য, লক্ষ্য উপাদানটি নির্বাচনযোগ্য এবং সম্পাদনাযোগ্য উভয়ই হতে হবে। <textarea> এবং <input type="text"> উভয়ই এখানে বিলের সাথে মানানসই, যেমন contenteditable বৈশিষ্ট্যের উপাদান রয়েছে। তবে এগুলি স্পষ্টতই পাঠ্য সম্পাদনার জন্য ডিজাইন করা হয়েছে।

আপনি যদি ব্যবহারকারীকে টেক্সট ইনপুট করতে সক্ষম না হন তবে এই কাজটি মসৃণভাবে করা কঠিন হতে পারে। একটি লুকানো ইনপুট থাকার মতো কৌশল যা আপনি অন্য কোনো উপাদানে ক্লিক করলে নির্বাচিত হয়ে যায় যা অ্যাক্সেসযোগ্যতা বজায় রাখা কঠিন করে তুলতে পারে।

একটি ফাইললিস্ট অবজেক্ট পরিচালনা করা

যেহেতু উপরের বেশিরভাগ পদ্ধতি একটি FileList তৈরি করে, তাই এটি কী তা সম্পর্কে আমার একটু কথা বলা উচিত।

একটি FileList একটি Array অনুরূপ। এটিতে সাংখ্যিক কী এবং একটি length বৈশিষ্ট্য রয়েছে তবে এটি আসলে একটি অ্যারে নয়। কোন অ্যারে পদ্ধতি নেই, যেমন forEach() বা pop() , এবং এটি পুনরাবৃত্তিযোগ্য নয়। অবশ্যই, আপনি Array.from(fileList) ব্যবহার করে একটি বাস্তব অ্যারে পেতে পারেন।

FileList এন্ট্রিগুলি হল File অবজেক্ট। এগুলি ঠিক Blob অবজেক্টের মতই, ব্যতীত তাদের অতিরিক্ত name এবং lastModified পঠনযোগ্য বৈশিষ্ট্য রয়েছে।

<img id="output" />
<script>
  const output = document.getElementById('output');

  function doSomethingWithFiles(fileList) {
    let file = null;

    for (let i = 0; i < fileList.length; i++) {
      if (fileList[i].type.match(/^image\//)) {
        file = fileList[i];
        break;
      }
    }

    if (file !== null) {
      output.src = URL.createObjectURL(file);
    }
  }
</script>

এই উদাহরণটি প্রথম ফাইলটি খুঁজে পায় যেটিতে একটি চিত্র MIME প্রকার রয়েছে, তবে এটি একাধিক ছবিকে একবারে নির্বাচিত/পেস্ট করা/ড্রপ করাও পরিচালনা করতে পারে।

একবার আপনি ফাইলটিতে অ্যাক্সেস পেয়ে গেলে আপনি এটি দিয়ে যা চান তা করতে পারেন। উদাহরণস্বরূপ, আপনি করতে পারেন:

  • এটিকে একটি <canvas> উপাদানে আঁকুন যাতে আপনি এটি পরিচালনা করতে পারেন
  • ব্যবহারকারীর ডিভাইসে এটি ডাউনলোড করুন
  • fetch() সহ একটি সার্ভারে এটি আপলোড করুন

ইন্টারেক্টিভভাবে ক্যামেরা অ্যাক্সেস করুন

এখন আপনি আপনার ঘাঁটি কভার করেছেন, এটি ক্রমবর্ধমানভাবে উন্নত করার সময়!

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

ক্যামেরা অ্যাক্সেস অর্জন

getUserMedia() নামক WebRTC স্পেসিফিকেশনে API ব্যবহার করে আপনি সরাসরি ক্যামেরা এবং মাইক্রোফোন অ্যাক্সেস করতে পারেন। এটি ব্যবহারকারীকে তাদের সংযুক্ত মাইক্রোফোন এবং ক্যামেরাগুলিতে অ্যাক্সেসের জন্য অনুরোধ করবে৷

getUserMedia() এর জন্য সমর্থন বেশ ভাল, কিন্তু এটি এখনও সর্বত্র নেই। বিশেষ করে, এটি Safari 10 বা তার নিচের সংস্করণে উপলব্ধ নয়, যা লেখার সময় এখনও সর্বশেষ স্থিতিশীল সংস্করণ। তবে অ্যাপল ঘোষণা করেছে যে এটি Safari 11 এ পাওয়া যাবে।

তবে সমর্থন সনাক্ত করা খুবই সহজ।

const supported = 'mediaDevices' in navigator;

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

ক্যামেরা থেকে ডেটা পেতে, যাইহোক, আপনার শুধুমাত্র একটি সীমাবদ্ধতা প্রয়োজন, এবং তা হল video: true

সফল হলে এপিআই একটি MediaStream ফেরত দেবে যাতে ক্যামেরা থেকে ডেটা রয়েছে এবং আপনি হয় এটিকে একটি <video> উপাদানের সাথে সংযুক্ত করতে পারেন এবং একটি রিয়েল টাইম প্রিভিউ দেখানোর জন্য এটি চালাতে পারেন, অথবা একটি স্ন্যাপশট পেতে এটি একটি <canvas> এর সাথে সংযুক্ত করতে পারেন। .

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

  const constraints = {
    video: true,
  };

  navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
    player.srcObject = stream;
  });
</script>

নিজেই, এই যে দরকারী নয়. আপনি যা করতে পারেন তা হল ভিডিও ডেটা নেওয়া এবং এটি আবার প্লে করা। ইমেজ পেতে হলে একটু বাড়তি কাজ করতে হবে।

একটি স্ন্যাপশট দখল

একটি ছবি পাওয়ার জন্য আপনার সেরা সমর্থিত বিকল্প হল ভিডিও থেকে একটি ক্যানভাসে একটি ফ্রেম আঁকা।

ওয়েব অডিও API-এর বিপরীতে, ওয়েবে ভিডিওর জন্য একটি ডেডিকেটেড স্ট্রিম প্রসেসিং API নেই তাই ব্যবহারকারীর ক্যামেরা থেকে একটি স্ন্যাপশট ক্যাপচার করার জন্য আপনাকে সামান্য হ্যাকারির আশ্রয় নিতে হবে।

প্রক্রিয়াটি নিম্নরূপ:

  1. একটি ক্যানভাস অবজেক্ট তৈরি করুন যা ক্যামেরা থেকে ফ্রেম ধরে রাখবে
  2. ক্যামেরা স্ট্রিম অ্যাক্সেস পান
  3. এটি একটি ভিডিও উপাদান সংযুক্ত করুন
  4. আপনি যখন একটি সুনির্দিষ্ট ফ্রেম ক্যাপচার করতে চান, তখন drawImage() ব্যবহার করে একটি ক্যানভাস অবজেক্টে ভিডিও উপাদান থেকে ডেটা যোগ করুন।
<video id="player" controls autoplay></video>
<button id="capture">Capture</button>
<canvas id="canvas" width="320" height="240"></canvas>
<script>
  const player = document.getElementById('player');
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const captureButton = document.getElementById('capture');

  const constraints = {
    video: true,
  };

  captureButton.addEventListener('click', () => {
    // Draw the video frame to the canvas.
    context.drawImage(player, 0, 0, canvas.width, canvas.height);
  });

  // Attach the video stream to the video element and autoplay.
  navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
    player.srcObject = stream;
  });
</script>

ক্যানভাসে সংরক্ষিত ক্যামেরা থেকে ডেটা থাকলে আপনি এটি দিয়ে অনেক কিছু করতে পারবেন। আপনি পারেন:

  • এটি সরাসরি সার্ভারে আপলোড করুন
  • এটি স্থানীয়ভাবে সংরক্ষণ করুন
  • ছবিতে মজাদার প্রভাব প্রয়োগ করুন

পরামর্শ

প্রয়োজন না হলে ক্যামেরা থেকে স্ট্রিমিং বন্ধ করুন

আপনার আর প্রয়োজন না হলে ক্যামেরা ব্যবহার করা বন্ধ করা ভালো অভ্যাস। এটি শুধুমাত্র ব্যাটারি এবং প্রক্রিয়াকরণের শক্তিই সাশ্রয় করবে না, এটি ব্যবহারকারীদের আপনার অ্যাপ্লিকেশনে আস্থাও দেবে।

ক্যামেরায় অ্যাক্সেস বন্ধ করতে আপনি getUserMedia() দ্বারা প্রত্যাবর্তিত স্ট্রিমের জন্য প্রতিটি ভিডিও ট্র্যাকে শুধু stop() কল করতে পারেন।

<video id="player" controls autoplay></video>
<button id="capture">Capture</button>
<canvas id="canvas" width="320" height="240"></canvas>
<script>
  const player = document.getElementById('player');
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const captureButton = document.getElementById('capture');

  const constraints = {
    video: true,
  };

  captureButton.addEventListener('click', () => {
    context.drawImage(player, 0, 0, canvas.width, canvas.height);

    // Stop all video streams.
    player.srcObject.getVideoTracks().forEach(track => track.stop());
  });

  navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
    // Attach the video stream to the video element and autoplay.
    player.srcObject = stream;
  });
</script>

দায়িত্বের সাথে ক্যামেরা ব্যবহার করার অনুমতি জিজ্ঞাসা করুন

ব্যবহারকারী যদি আগে ক্যামেরায় আপনার সাইটের অ্যাক্সেস মঞ্জুর না করে থাকে তাহলে আপনি যে মুহূর্তে getUserMedia() কল করবেন ব্রাউজারটি ব্যবহারকারীকে ক্যামেরায় আপনার সাইটের অনুমতি দেওয়ার জন্য অনুরোধ করবে।

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

সামঞ্জস্য

মোবাইল এবং ডেস্কটপ ব্রাউজার বাস্তবায়ন সম্পর্কে আরও তথ্য:

WebRTC স্পেস পরিবর্তন এবং প্রিফিক্স পার্থক্য থেকে অ্যাপগুলিকে রক্ষা করতে আমরা adapter.js শিম ব্যবহার করারও সুপারিশ করি।

প্রতিক্রিয়া