RequestVideoFrameCallback() সহ ভিডিওতে দক্ষ প্রতি-ভিডিও-ফ্রেম অপারেশনগুলি সম্পাদন করুন

ব্রাউজারে ভিডিওগুলির সাথে আরও দক্ষতার সাথে কাজ করতে requestVideoFrameCallback() কীভাবে ব্যবহার করবেন তা শিখুন।

HTMLVideoElement.requestVideoFrameCallback() পদ্ধতি ওয়েব লেখকদের একটি কলব্যাক নিবন্ধন করতে দেয় যা রেন্ডারিং ধাপে চলে যখন কম্পোজিটরে একটি নতুন ভিডিও ফ্রেম পাঠানো হয়। এটি ডেভেলপারদের ভিডিওতে দক্ষ প্রতি-ভিডিও-ফ্রেম ক্রিয়াকলাপ সম্পাদন করতে দেয়, যেমন ভিডিও প্রক্রিয়াকরণ এবং একটি ক্যানভাসে পেইন্টিং, ভিডিও বিশ্লেষণ বা বহিরাগত অডিও উত্সগুলির সাথে সিঙ্ক্রোনাইজেশন।

এই API-এর মাধ্যমে তৈরি drawImage() ব্যবহার করে একটি ক্যানভাসে একটি ভিডিও ফ্রেম আঁকার মতো কাজগুলি স্ক্রীনে চলা ভিডিওর ফ্রেম হারের সাথে সেরা প্রচেষ্টা হিসাবে সিঙ্ক্রোনাইজ করা হবে৷ window.requestAnimationFrame() থেকে ভিন্ন, যা সাধারণত প্রতি সেকেন্ডে প্রায় 60 বার ফায়ার করে, requestVideoFrameCallback() প্রকৃত ভিডিও ফ্রেম হারের সাথে আবদ্ধ—একটি গুরুত্বপূর্ণ ব্যতিক্রম সহ:

যে কার্যকর হারে কলব্যাক চালানো হয় সেটি হল ভিডিওর রেট এবং ব্রাউজারের হারের মধ্যে কম হার। এর মানে হল একটি 25fps ভিডিও একটি ব্রাউজারে প্লে হচ্ছে যা 60Hz এ পেইন্ট করলে 25Hz এ কলব্যাক চালু হবে। একই 60Hz ব্রাউজারে একটি 120fps ভিডিও 60Hz এ কলব্যাক ফায়ার করবে।

একটি নামে কি আছে?

window.requestAnimationFrame() এর সাথে এর মিলের কারণে, পদ্ধতিটি প্রথমে video.requestAnimationFrame() হিসাবে প্রস্তাবিত হয়েছিল এবং requestVideoFrameCallback() নামকরণ করা হয়েছিল, যা দীর্ঘ আলোচনার পরে সম্মত হয়েছিল।

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

if ('requestVideoFrameCallback' in HTMLVideoElement.prototype) {
  // The API is supported!
}

ব্রাউজার সমর্থন

ব্রাউজার সমর্থন

  • ক্রোম: 83।
  • প্রান্ত: 83।
  • ফায়ারফক্স: 132।
  • সাফারি: 15.4.

উৎস

পলিফিল

Window.requestAnimationFrame() এবং HTMLVideoElement.getVideoPlaybackQuality() এর উপর ভিত্তি করে requestVideoFrameCallback() পদ্ধতির জন্য একটি পলিফিল উপলব্ধ। এটি ব্যবহার করার আগে, README এ উল্লিখিত সীমাবদ্ধতা সম্পর্কে সচেতন হন।

requestVideoFrameCallback() পদ্ধতি ব্যবহার করে

আপনি যদি কখনো requestAnimationFrame() পদ্ধতি ব্যবহার করে থাকেন, তাহলে আপনি অবিলম্বে requestVideoFrameCallback() পদ্ধতির সাথে পরিচিত বোধ করবেন। আপনি একবার একটি প্রাথমিক কলব্যাক নিবন্ধন করুন, এবং তারপর যখনই কলব্যাক শুরু হবে তখন পুনরায় নিবন্ধন করুন৷

const doSomethingWithTheFrame = (now, metadata) => {
  // Do something with the frame.
  console.log(now, metadata);
  // Re-register the callback to be notified about the next frame.
  video.requestVideoFrameCallback(doSomethingWithTheFrame);
};
// Initially register the callback to be notified about the first frame.
video.requestVideoFrameCallback(doSomethingWithTheFrame);

কলব্যাকে, now একটি DOMHighResTimeStamp এবং metadata হল একটি VideoFrameMetadata অভিধান যার নিম্নলিখিত বৈশিষ্ট্য রয়েছে:

  • presentationTime , DOMHighResTimeStamp টাইপ: যে সময়ে ব্যবহারকারী এজেন্ট রচনার জন্য ফ্রেম জমা দিয়েছেন।
  • expectedDisplayTime , DOMHighResTimeStamp টাইপ: যে সময়ে ব্যবহারকারী এজেন্ট ফ্রেমটি দৃশ্যমান হবে বলে আশা করে।
  • width , unsigned long টাইপের : মিডিয়া পিক্সেলে ভিডিও ফ্রেমের প্রস্থ।
  • height , unsigned long : ভিডিও ফ্রেমের উচ্চতা, মিডিয়া পিক্সেলে।
  • mediaTime , টাইপ double : মিডিয়া প্রেজেন্টেশন টাইমস্ট্যাম্প (PTS) ফ্রেমের সেকেন্ডের মধ্যে (যেমন, video.currentTime টাইমলাইনে এর টাইমস্ট্যাম্প)।
  • presentedFrames , unsigned long টাইপের : রচনার জন্য জমা দেওয়া ফ্রেমের সংখ্যার একটি গণনা৷ VideoFrameRequestCallback এর দৃষ্টান্তগুলির মধ্যে ফ্রেমগুলি মিস হয়েছে কিনা তা নির্ধারণ করতে ক্লায়েন্টদের অনুমতি দেয়৷
  • processingDuration , double প্রকারের: ডিকোডেড ফ্রেম উপস্থাপনার জন্য প্রস্তুত না হওয়া পর্যন্ত এই ফ্রেমের মতো একই প্রেজেন্টেশন টাইমস্ট্যাম্প ( mediaTime ) সহ ডিকোডারে এনকোড করা প্যাকেট জমা দেওয়ার পর থেকে সেকেন্ডের মধ্যে অতিবাহিত সময়কাল।

WebRTC অ্যাপ্লিকেশনের জন্য, অতিরিক্ত বৈশিষ্ট্য উপস্থিত হতে পারে:

  • captureTime , DOMHighResTimeStamp টাইপ: স্থানীয় বা দূরবর্তী উত্স থেকে আসা ভিডিও ফ্রেমের জন্য, এই সময়টি হল ফ্রেমটি ক্যামেরা দ্বারা বন্দী করা হয়েছে৷ দূরবর্তী উত্সের জন্য, সময় ক্যাপচার করতে RTP টাইমস্ট্যাম্পগুলিকে রূপান্তর করতে ঘড়ি সিঙ্ক্রোনাইজেশন এবং RTCP প্রেরকের রিপোর্ট ব্যবহার করে ক্যাপচারের সময় অনুমান করা হয়।
  • receiveTime , DOMHighResTimeStamp টাইপ: দূরবর্তী উৎস থেকে আসা ভিডিও ফ্রেমের জন্য, প্ল্যাটফর্ম দ্বারা এনকোড করা ফ্রেমটি পাওয়ার সময়, অর্থাৎ, নেটওয়ার্কে এই ফ্রেমের অন্তর্গত শেষ প্যাকেটটি যে সময়ে গৃহীত হয়েছিল।
  • rtpTimestamp , টাইপের unsigned long : এই ভিডিও ফ্রেমের সাথে যুক্ত RTP টাইমস্ট্যাম্প।

এই তালিকায় বিশেষ আগ্রহ mediaTime । Chromium-এর বাস্তবায়ন অডিও ঘড়িকে সময়ের উৎস হিসেবে ব্যবহার করে যা video.currentTime কে সমর্থন করে, যেখানে mediaTime সরাসরি ফ্রেমের presentationTimestamp দ্বারা পপুলেট করা হয়। আপনি কোন ফ্রেমগুলি মিস করেছেন তা শনাক্ত করা সহ, আপনি যদি পুনরুত্পাদনযোগ্য উপায়ে ফ্রেমগুলিকে সঠিকভাবে সনাক্ত করতে চান তবে আপনার যা ব্যবহার করা উচিত তা mediaTime

যদি জিনিসগুলি এক ফ্রেম বন্ধ বলে মনে হয়...

উল্লম্ব সিঙ্ক্রোনাইজেশন (বা শুধু vsync), একটি গ্রাফিক্স প্রযুক্তি যা একটি ভিডিওর ফ্রেম রেট এবং একটি মনিটরের রিফ্রেশ রেট সিঙ্ক্রোনাইজ করে। যেহেতু requestVideoFrameCallback() মূল থ্রেডে চলে, কিন্তু, হুডের নিচে, কম্পোজিটর থ্রেডে ভিডিও কম্পোজিটিং হয়, তাই এই API থেকে সবকিছুই একটি সর্বোত্তম প্রচেষ্টা, এবং ব্রাউজার কোনো কঠোর গ্যারান্টি দেয় না। কি ঘটতে পারে যে API একটি ভিডিও ফ্রেম রেন্ডার করা হয় আপেক্ষিক এক vsync দেরী হতে পারে. API-এর মাধ্যমে ওয়েব পৃষ্ঠায় করা পরিবর্তনগুলি স্ক্রিনে প্রদর্শিত হতে এটি একটি vsync লাগে ( window.requestAnimationFrame() এর মতোই)৷ সুতরাং আপনি যদি আপনার ওয়েব পৃষ্ঠায় mediaTime বা ফ্রেম নম্বর আপডেট করতে থাকেন এবং সংখ্যাযুক্ত ভিডিও ফ্রেমের সাথে তুলনা করেন, অবশেষে ভিডিওটি দেখতে এক ফ্রেম এগিয়ে রয়েছে।

আসলে যা ঘটছে তা হল ফ্রেমটি vsync x এ প্রস্তুত, কলব্যাক ফায়ার করা হয়েছে এবং ফ্রেমটি vsync x+1 এ রেন্ডার করা হয়েছে এবং কলব্যাকে করা পরিবর্তনগুলি vsync x+2 এ রেন্ডার করা হয়েছে। metadata.expectedDisplayTime মোটামুটি now নাকি ভবিষ্যতে একটি vsync আছে কিনা তা পরীক্ষা করে আপনি কলব্যাকটি একটি vsync দেরিতে (এবং ফ্রেমটি ইতিমধ্যেই স্ক্রিনে রেন্ডার করা হয়েছে) কিনা তা পরীক্ষা করতে পারেন৷ যদি এটি now প্রায় পাঁচ থেকে দশ মাইক্রোসেকেন্ডের মধ্যে হয়, ফ্রেমটি ইতিমধ্যে রেন্ডার করা হয়েছে; যদি expectedDisplayTime ভবিষ্যতে প্রায় ষোল মিলিসেকেন্ড হয় (ধরে নিচ্ছি আপনার ব্রাউজার/স্ক্রিন 60Hz এ রিফ্রেশ হচ্ছে), তাহলে আপনি ফ্রেমের সাথে সিঙ্ক করছেন।

ডেমো

আমি গ্লিচ-এ একটি ছোট ডেমো তৈরি করেছি যা দেখায় যে কীভাবে ভিডিওর ফ্রেম হারে একটি ক্যানভাসে ফ্রেম আঁকা হয় এবং ডিবাগিংয়ের উদ্দেশ্যে ফ্রেম মেটাডেটা কোথায় লগ করা হয়।

let paintCount = 0;
let startTime = 0.0;

const updateCanvas = (now, metadata) => {
  if (startTime === 0.0) {
    startTime = now;
  }

  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

  const elapsed = (now - startTime) / 1000.0;
  const fps = (++paintCount / elapsed).toFixed(3);
  fpsInfo.innerText = `video fps: ${fps}`;
  metadataInfo.innerText = JSON.stringify(metadata, null, 2);

  video.requestVideoFrameCallback(updateCanvas);
};

video.requestVideoFrameCallback(updateCanvas);

উপসংহার

লোকেরা দীর্ঘ সময়ের জন্য ফ্রেম-লেভেল প্রক্রিয়াকরণ করেছে—প্রকৃত ফ্রেমে অ্যাক্সেস না করেই, শুধুমাত্র video.currentTime এর উপর ভিত্তি করে। requestVideoFrameCallback() পদ্ধতিটি এই সমাধানে ব্যাপকভাবে উন্নতি করে।

স্বীকৃতি

requestVideoFrameCallback API টমাস গুইলবার্ট দ্বারা নির্দিষ্ট এবং প্রয়োগ করা হয়েছিল। এই পোস্টটি Joe Medley এবং Kayce Basques দ্বারা পর্যালোচনা করা হয়েছে। আনস্প্ল্যাশে ডেনিস জানসের নায়কের ছবি