একটি ক্যাপচার করা ট্যাব স্ক্রোল এবং জুম করুন, একটি ক্যাপচার করা ট্যাব স্ক্রোল করুন এবং জুম করুন৷

ফ্রাঁসোয়া বিউফোর্ট
François Beaufort

স্ক্রিন ক্যাপচার API এর সাথে ওয়েব প্ল্যাটফর্মে ইতিমধ্যেই ট্যাব, উইন্ডো এবং স্ক্রিন শেয়ার করা সম্ভব। যখন একটি ওয়েব অ্যাপ getDisplayMedia() কল করে, Chrome ব্যবহারকারীকে একটি ট্যাব, উইন্ডো বা স্ক্রীন ওয়েব অ্যাপের সাথে MediaStreamTrack ভিডিও হিসেবে শেয়ার করার জন্য অনুরোধ করে।

getDisplayMedia() ব্যবহার করে এমন অনেক ওয়েব অ্যাপ ব্যবহারকারীকে ক্যাপচার করা পৃষ্ঠের একটি ভিডিও পূর্বরূপ দেখায়। উদাহরণস্বরূপ, ভিডিও কনফারেন্সিং অ্যাপগুলি প্রায়শই এই ভিডিওটি দূরবর্তী ব্যবহারকারীদের কাছে স্ট্রিম করবে এবং এটিকে একটি স্থানীয় HTMLVideoElement এ রেন্ডার করবে, যাতে স্থানীয় ব্যবহারকারী ক্রমাগত তারা কী শেয়ার করছেন তার একটি পূর্বরূপ দেখতে পান৷

এই ডকুমেন্টেশনটি Chrome-এ নতুন ক্যাপচার করা সারফেস কন্ট্রোল API-এর পরিচয় দেয়, যা আপনার ওয়েব অ্যাপকে একটি ক্যাপচার করা ট্যাব স্ক্রোল করতে দেয়, সেইসাথে ক্যাপচার করা ট্যাবের জুম লেভেল পড়তে ও লিখতে দেয়।

একজন ব্যবহারকারী একটি ক্যাপচার করা ট্যাব ( ডেমো ) স্ক্রোল করে এবং জুম করে।

কেন ক্যাপচারড সারফেস কন্ট্রোল ব্যবহার করবেন?

সমস্ত ভিডিও কনফারেন্সিং অ্যাপ্লিকেশানগুলি একই ত্রুটিতে ভোগে: ব্যবহারকারী যদি একটি ক্যাপচার করা ট্যাব বা উইন্ডোর সাথে ইন্টারঅ্যাক্ট করতে চান, তাহলে ব্যবহারকারীকে ভিডিও কনফারেন্সিং অ্যাপ থেকে দূরে সরিয়ে সেই পৃষ্ঠে যেতে হবে। এটি কিছু চ্যালেঞ্জ উপস্থাপন করে:

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

ক্যাপচারড সারফেস কন্ট্রোল এপিআই এই সমস্যার সমাধান করে।

আমি কিভাবে ক্যাপচারড সারফেস কন্ট্রোল ব্যবহার করব?

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

একটি ব্রাউজার ট্যাব ক্যাপচার

ব্যবহারকারীকে getDisplayMedia() ব্যবহার করে শেয়ার করার জন্য একটি সারফেস বেছে নিতে অনুরোধ করে শুরু করুন এবং প্রক্রিয়ায় ক্যাপচার সেশনের সাথে একটি CaptureController অবজেক্ট যুক্ত করুন। আমরা শীঘ্রই ক্যাপচার করা পৃষ্ঠ নিয়ন্ত্রণ করতে সেই বস্তুটি ব্যবহার করব।

const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });

এরপরে, একটি <video> উপাদান আকারে ক্যাপচার করা পৃষ্ঠের একটি স্থানীয় পূর্বরূপ তৈরি করুন:

const previewTile = document.querySelector('video');
previewTile.srcObject = stream;

ব্যবহারকারী যদি একটি উইন্ডো বা একটি স্ক্রীন শেয়ার করতে পছন্দ করেন, তবে তা আপাতত সুযোগের বাইরে—কিন্তু যদি তারা একটি ট্যাব শেয়ার করা বেছে নেন, তাহলে আমরা এগিয়ে যেতে পারি।

const [track] = stream.getVideoTracks();

if (track.getSettings().displaySurface !== 'browser') {
  // Bail out early if the user didn't pick a tab.
  return;
}

অনুমতি প্রম্পট

একটি প্রদত্ত CaptureController অবজেক্টে sendWheel() বা setZoomLevel() এর প্রথম আহ্বান একটি অনুমতি প্রম্পট তৈরি করে। ব্যবহারকারী যদি অনুমতি দেয়, তাহলে সেই CaptureController অবজেক্টে এই পদ্ধতিগুলির আরও আহ্বান অনুমোদিত। যদি ব্যবহারকারী অনুমতি অস্বীকার করে, তবে প্রত্যাবর্তিত প্রতিশ্রুতি প্রত্যাখ্যান করা হয়।

মনে রাখবেন CaptureController বস্তুগুলি একটি নির্দিষ্ট ক্যাপচার-সেশনের সাথে অনন্যভাবে যুক্ত, অন্য ক্যাপচার-সেশনের সাথে যুক্ত হতে পারে না এবং পৃষ্ঠার নেভিগেশনে টিকে থাকে না যেখানে সেগুলি সংজ্ঞায়িত করা হয়েছে। যাইহোক, ক্যাপচার-সেশনগুলি ক্যাপচার করা পৃষ্ঠার নেভিগেশনে টিকে থাকে

ব্যবহারকারীর কাছে একটি অনুমতি প্রম্পট দেখানোর জন্য একটি ব্যবহারকারী অঙ্গভঙ্গি প্রয়োজন। শুধুমাত্র sendWheel() এবং setZoomLevel() কলগুলির জন্য একটি ব্যবহারকারীর অঙ্গভঙ্গি প্রয়োজন, এবং শুধুমাত্র যদি প্রম্পট দেখানোর প্রয়োজন হয়। ব্যবহারকারী যদি ওয়েব অ্যাপে একটি জুম-ইন বা জুম-আউট বোতামে ক্লিক করেন, তাহলে সেই ব্যবহারকারীর অঙ্গভঙ্গি দেওয়া হয়; কিন্তু অ্যাপটি যদি প্রথমে স্ক্রোল-কন্ট্রোল অফার করতে চায়, তাহলে ডেভেলপারদের মনে রাখতে হবে যে স্ক্রোলিং ব্যবহারকারীর অঙ্গভঙ্গি গঠন করে না । একটি সম্ভাবনা হল ব্যবহারকারীকে প্রথমে একটি "স্ক্রলিং শুরু করুন" বোতাম অফার করা, নিম্নলিখিত উদাহরণ অনুসারে:

const startScrollingButton = document.querySelector('button');

startScrollingButton.addEventListener('click', async () => {
  try {
    const noOpWheelAction = {};

    await controller.sendWheel(noOpWheelAction);
    // The user approved the permission prompt.
    // You can now scroll and zoom the captured tab as shown later in the article.
  } catch (error) {
    return; // Permission denied. Bail.
  }
});

স্ক্রল করুন

sendWheel() ব্যবহার করে, একটি ক্যাপচারিং অ্যাপ একটি ট্যাবের ভিউপোর্টের মধ্যে তার পছন্দের স্থানাঙ্কের উপর তার নির্বাচিত মাত্রার চাকা ইভেন্টগুলি সরবরাহ করতে পারে। ইভেন্টটি সরাসরি ব্যবহারকারীর মিথস্ক্রিয়া থেকে ক্যাপচার করা অ্যাপের সাথে আলাদা করা যায় না।

ধরুন ক্যাপচারিং অ্যাপটি "previewTile" নামক একটি <video> উপাদান নিয়োগ করে, নিম্নলিখিত কোডটি দেখায় কিভাবে ক্যাপচার করা ট্যাবে চাকা ইভেন্ট পাঠাতে হয়:

const previewTile = document.querySelector('video');

previewTile.addEventListener('wheel', async (event) => {
  // Translate the offsets into coordinates which sendWheel() can understand.
  // The implementation of this translation is explained further below.
  const [x, y] = translateCoordinates(event.offsetX, event.offsetY);
  const [wheelDeltaX, wheelDeltaY] = [-event.deltaX, -event.deltaY];

  try {
    // Relay the user's action to the captured tab.
    await controller.sendWheel({ x, y, wheelDeltaX, wheelDeltaY });
  } catch (error) {
    // Inspect the error.
    // ...
  }
});

sendWheel() পদ্ধতিটি দুটি মানের সেট সহ একটি অভিধান নেয়:

  • x এবং y : স্থানাঙ্ক যেখানে চাকা ইভেন্ট বিতরণ করা হবে।
  • wheelDeltaX এবং wheelDeltaY : অনুভূমিক এবং উল্লম্ব স্ক্রোলগুলির জন্য যথাক্রমে স্ক্রোলগুলির আকার, পিক্সেলে। লক্ষ্য করুন যে এই মানগুলি মূল চাকা ইভেন্টের তুলনায় উল্টানো।

translateCoordinates() এর একটি সম্ভাব্য বাস্তবায়ন হল:

function translateCoordinates(offsetX, offsetY) {
  const previewDimensions = previewTile.getBoundingClientRect();
  const trackSettings = previewTile.srcObject.getVideoTracks()[0].getSettings();

  const x = trackSettings.width * offsetX / previewDimensions.width;
  const y = trackSettings.height * offsetY / previewDimensions.height;

  return [Math.floor(x), Math.floor(y)];
}

নোট করুন যে কোডে আগে তিনটি ভিন্ন মাপ আছে:

  • <video> উপাদানের আকার।
  • ক্যাপচার করা ফ্রেমের আকার (এখানে trackSettings.width এবং trackSettings.height হিসাবে উপস্থাপন করা হয়েছে)।
  • ট্যাবের আকার।

<video> উপাদানটির আকার সম্পূর্ণরূপে ক্যাপচারিং অ্যাপের ডোমেনের মধ্যে এবং ব্রাউজারে অজানা। ট্যাবের আকার সম্পূর্ণরূপে ব্রাউজারের ডোমেনের মধ্যে, এবং ওয়েব অ্যাপের কাছে অজানা।

ওয়েব অ্যাপটি ভিডিও ট্র্যাকের নিজস্ব স্থানাঙ্ক স্থানের মধ্যে স্থানাঙ্কে <video> উপাদানের সাপেক্ষে অফসেটগুলিকে অনুবাদ করতে translateCoordinates() ব্যবহার করে। ব্রাউজার একইভাবে ক্যাপচার করা ফ্রেমের আকার এবং ট্যাবের আকারের মধ্যে অনুবাদ করবে এবং ওয়েব অ্যাপের প্রত্যাশার সাথে সামঞ্জস্যপূর্ণ একটি অফসেটে স্ক্রোল ইভেন্ট সরবরাহ করবে।

sendWheel() দ্বারা প্রত্যাবর্তিত প্রতিশ্রুতি নিম্নলিখিত ক্ষেত্রে প্রত্যাখ্যান করা যেতে পারে:

  • যদি ক্যাপচার সেশন এখনও শুরু না হয় বা ইতিমধ্যেই বন্ধ হয়ে যায়, ব্রাউজার দ্বারা sendWheel() অ্যাকশন পরিচালনা করার সময় অ্যাসিঙ্ক্রোনাসভাবে বন্ধ করা সহ।
  • ব্যবহারকারী যদি অ্যাপ্লিকেশনটিকে sendWheel() ব্যবহার করার অনুমতি না দেয়।
  • যদি ক্যাপচারিং অ্যাপটি [trackSettings.width, trackSettings.height] এর বাইরের স্থানাঙ্কগুলিতে একটি স্ক্রোল ইভেন্ট সরবরাহ করার চেষ্টা করে। মনে রাখবেন যে এই মানগুলি অ্যাসিঙ্ক্রোনাসভাবে পরিবর্তিত হতে পারে, তাই ত্রুটিটি ধরা এবং এটি উপেক্ষা করা একটি ভাল ধারণা। (উল্লেখ্য যে 0, 0 সাধারণত সীমার বাইরে হবে না, তাই ব্যবহারকারীকে অনুমতির জন্য অনুরোধ করার জন্য তাদের ব্যবহার করা নিরাপদ।)

জুম

ক্যাপচার করা ট্যাবের জুম লেভেলের সাথে ইন্টারঅ্যাক্ট করা নিম্নলিখিত CaptureController পৃষ্ঠের মাধ্যমে করা হয়:

  • getSupportedZoomLevels() ব্রাউজার দ্বারা সমর্থিত জুম স্তরগুলির একটি তালিকা প্রদান করে, যা "ডিফল্ট জুম স্তর" এর শতাংশ হিসাবে উপস্থাপিত হয়, যা 100% হিসাবে সংজ্ঞায়িত করা হয়। এই তালিকাটি একঘেয়েভাবে বাড়ছে এবং এতে 100 মান রয়েছে।
  • getZoomLevel() ট্যাবের বর্তমান জুম স্তর প্রদান করে।
  • setZoomLevel() ট্যাবের জুম-লেভেলকে getSupportedZoomLevels() এ উপস্থিত যেকোনো পূর্ণসংখ্যার মান সেট করে এবং এটি সফল হলে একটি প্রতিশ্রুতি প্রদান করে। নোট করুন যে জুম স্তরটি ক্যাপচার সেশনের শেষে পুনরায় সেট করা হয় না।
  • oncapturedzoomlevelchange আপনাকে একটি ক্যাপচার করা ট্যাবের জুম স্তরের পরিবর্তনগুলি শুনতে দেয় কারণ ব্যবহারকারীরা ক্যাপচারিং অ্যাপের মাধ্যমে বা ক্যাপচার করা ট্যাবের সাথে সরাসরি ইন্টারঅ্যাকশনের মাধ্যমে জুম স্তর পরিবর্তন করতে পারে৷

setZoomLevel() জন্য কল অনুমতি দ্বারা গেট করা হয়; অন্যকে কল করা, শুধুমাত্র পঠনযোগ্য জুম পদ্ধতিগুলি "বিনামূল্যে", যেমন ঘটনা শোনা।

নিম্নলিখিত উদাহরণটি আপনাকে একটি বিদ্যমান ক্যাপচার সেশনে একটি ক্যাপচার করা ট্যাবের জুম স্তর বৃদ্ধি করতে দেখায়:

const zoomIncreaseButton = document.getElementById('zoomInButton');

zoomIncreaseButton.addEventListener('click', async (event) => {
  const levels = CaptureController.getSupportedZoomLevels();
  const index = levels.indexOf(controller.getZoomLevel());
  const newZoomLevel = levels[Math.min(index + 1, levels.length - 1)];

  try {
    await controller.setZoomLevel(newZoomLevel);
  } catch (error) {
    // Inspect the error.
    // ...
  }
});

নিম্নলিখিত উদাহরণটি দেখায় যে আপনি একটি ক্যাপচার করা ট্যাবের জুম স্তরের পরিবর্তনগুলিতে প্রতিক্রিয়া জানাতে পারেন:

controller.addEventListener('capturedzoomlevelchange', (event) => {
  const zoomLevel = controller.getZoomLevel();
  document.querySelector('#zoomLevelLabel').textContent = `${zoomLevel}%`;
});

বৈশিষ্ট্য সনাক্তকরণ

চাকা ইভেন্ট পাঠানো সমর্থিত কিনা তা পরীক্ষা করতে, ব্যবহার করুন:

if (!!window.CaptureController?.prototype.sendWheel) {
  // CaptureController sendWheel() is supported.
}

জুম নিয়ন্ত্রণ করা সমর্থিত কিনা তা পরীক্ষা করতে, ব্যবহার করুন:

if (!!window.CaptureController?.prototype.setZoomLevel) {
  // CaptureController setZoomLevel() is supported.
}

ক্যাপচার করা সারফেস কন্ট্রোল সক্ষম করুন

ক্যাপচার করা সারফেস কন্ট্রোল এপিআই ডেস্কটপে ক্রোমে ক্যাপচার করা সারফেস কন্ট্রোল পতাকার পিছনে উপলব্ধ, এবং chrome://flags/#captured-surface-control এ সক্ষম করা যেতে পারে।

এই বৈশিষ্ট্যটি ডেস্কটপে Chrome 122 দিয়ে শুরু হওয়া একটি অরিজিন ট্রায়ালে প্রবেশ করছে , যা ডেভেলপারদের তাদের সাইটের দর্শকদের প্রকৃত ব্যবহারকারীদের কাছ থেকে ডেটা সংগ্রহ করতে বৈশিষ্ট্যটি সক্ষম করতে দেয়৷ অরিজিন ট্রায়াল এবং সেগুলি কীভাবে কাজ করে সে সম্পর্কে আরও তথ্যের জন্য অরিজিন ট্রায়াল দিয়ে শুরু করুন দেখুন।

নিরাপত্তা এবং গোপনীয়তা

"captured-surface-control" অনুমতি নীতি আপনাকে কীভাবে আপনার ক্যাপচারিং অ্যাপ এবং এমবেড করা তৃতীয় পক্ষের আইফ্রেমগুলি ক্যাপচার করা সারফেস কন্ট্রোলে অ্যাক্সেস করতে পারে তা পরিচালনা করতে দেয়। নিরাপত্তা ট্রেডঅফগুলি বোঝার জন্য, ক্যাপচারড সারফেস কন্ট্রোল ব্যাখ্যাকারীর গোপনীয়তা এবং নিরাপত্তা বিবেচনা বিভাগটি দেখুন।

ডেমো

আপনি গ্লিচে ডেমো চালিয়ে ক্যাপচারড সারফেস কন্ট্রোলের সাথে খেলতে পারেন। সোর্স কোড চেক আউট করতে ভুলবেন না.

Chrome এর পূর্ববর্তী সংস্করণ থেকে পরিবর্তন

এখানে ক্যাপচারড সারফেস কন্ট্রোল সম্পর্কে কিছু মূল আচরণগত পার্থক্য রয়েছে যা আপনার সচেতন হওয়া উচিত:

  • Chrome 124 এবং তার আগে:
    • অনুমতি—যদি দেওয়া হয়—তা CaptureController সাথে যুক্ত ক্যাপচার সেশনে স্কোপ করা হয়, ক্যাপচারিং মূলের জন্য নয়।
  • Chrome 122-এ:
    • getZoomLevel() ট্যাবের বর্তমান জুম স্তরের সাথে একটি প্রতিশ্রুতি প্রদান করে।
    • sendWheel() ত্রুটি বার্তা দিয়ে প্রত্যাখ্যান করা একটি প্রতিশ্রুতি প্রদান করে "No permission." যদি ব্যবহারকারী অ্যাপটিকে ব্যবহারের অনুমতি না দেয়। ত্রুটির ধরনটি Chrome 123 এবং পরবর্তীতে "NotAllowedError"
    • oncapturedzoomlevelchange উপলব্ধ নয়। আপনি setInterval() ব্যবহার করে এই বৈশিষ্ট্যটি পলিফিল করতে পারেন।

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

Chrome টিম এবং ওয়েব স্ট্যান্ডার্ড সম্প্রদায় ক্যাপচারড সারফেস কন্ট্রোলের সাথে আপনার অভিজ্ঞতার কথা শুনতে চায়৷

ডিজাইন সম্পর্কে বলুন

ক্যাপচারড সারফেস ক্যাপচার সম্পর্কে এমন কিছু আছে যা আপনার প্রত্যাশা অনুযায়ী কাজ করে না? অথবা আপনার ধারণা বাস্তবায়নের জন্য আপনার প্রয়োজনীয় পদ্ধতি বা বৈশিষ্ট্যগুলি অনুপস্থিত আছে? নিরাপত্তা মডেল সম্পর্কে একটি প্রশ্ন বা মন্তব্য আছে? GitHub রেপোতে একটি বিশেষ সমস্যা ফাইল করুন, বা বিদ্যমান সমস্যাটিতে আপনার চিন্তা যোগ করুন।

বাস্তবায়নে সমস্যা?

আপনি কি Chrome এর বাস্তবায়নের সাথে একটি বাগ খুঁজে পেয়েছেন? অথবা বাস্তবায়ন বৈশিষ্ট থেকে ভিন্ন? https://new.crbug.com এ একটি বাগ ফাইল করুন। আপনি যতটা সম্ভব বিস্তারিত, সেইসাথে পুনরুত্পাদনের জন্য নির্দেশাবলী অন্তর্ভুক্ত করতে ভুলবেন না। গ্লিচ প্রজননযোগ্য বাগগুলি ভাগ করার জন্য দুর্দান্ত কাজ করে।