requestVideoFrameCallback() की मदद से, हर वीडियो फ़्रेम के हिसाब से बेहतर कार्रवाइयां करें

ब्राउज़र में वीडियो के साथ बेहतर तरीके से काम करने के लिए, requestVideoFrameCallback() इस्तेमाल करने का तरीका जानें.

HTMLVideoElement.requestVideoFrameCallback() वाला तरीका, वेब राइटर को एक कॉलबैक रजिस्टर करने की अनुमति देता है. यह कॉलबैक कंपोज़िटर को नया वीडियो फ़्रेम भेजे जाने पर, रेंडरिंग के चरणों में चलता है. इससे डेवलपर को वीडियो पर हर वीडियो-फ़्रेम के लिए बेहतर कार्रवाइयां करने में मदद मिलती है. जैसे, वीडियो को प्रोसेस करना और पेंटिंग को कैनवस पर बनाना, वीडियो का विश्लेषण करना या बाहरी ऑडियो सोर्स से सिंक करना.

requestAnimationFrame() के साथ अंतर

इस एपीआई की मदद से बनाई गई drawImage() सुविधा का इस्तेमाल करके, किसी कैनवस पर वीडियो फ़्रेम बनाने जैसी कार्रवाइयां, स्क्रीन पर चल रहे वीडियो के फ़्रेम रेट के हिसाब से सिंक हो जाएंगी. आम तौर पर, window.requestAnimationFrame() एक सेकंड में करीब 60 बार सक्रिय होता है. requestVideoFrameCallback() से अलग है, क्योंकि वीडियो का असल फ़्रेम रेट होता है. इसमें एक ज़रूरी अपवाद है:

कॉलबैक के चालू होने की दर, वीडियो के रेट और ब्राउज़र के रेट के बीच कम दर होती है. इसका मतलब है कि 60 हर्ट्ज़ पर पेंट करने वाले ब्राउज़र में चल रहा 25 FPS (फ़्रेम प्रति सेकंड) वीडियो, 25 हर्ट्ज़ पर कॉलबैक बंद करेगा. उसी 60 हर्ट्ज़ वाले ब्राउज़र में 120 एफ़पीएस (फ़्रेम प्रति सेकंड) वाला वीडियो, 60 हर्ट्ज़ पर कॉलबैक फ़ायर करेगा.

साइटमैप को क्या नाम दिया जाना चाहिए?

window.requestAnimationFrame() से मिलते-जुलते होने की वजह से, शुरुआत में इस तरीके को video.requestAnimationFrame() के तौर पर सुझाया गया था और इसका नाम बदलकर requestVideoFrameCallback() किया गया था. लंबी चर्चा के बाद, इस पर सहमति मिली थी.

सुविधा की पहचान करने की सुविधा

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

ब्राउज़र समर्थन

ब्राउज़र सहायता

  • 83
  • 83
  • x
  • 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 टाइप: दिखाए गए फ़्रेम के सेकंड में मीडिया प्रज़ेंटेशन टाइमस्टैंप (पीटीएस). उदाहरण के लिए, video.currentTime टाइमलाइन पर इसका टाइमस्टैंप.
  • unsigned long टाइप presentedFrames: कंपोज़िशन के लिए सबमिट किए गए फ़्रेम की संख्या. क्लाइंट को यह तय करने की अनुमति देता है कि VideoFrameRequestCallback के इंस्टेंस के बीच फ़्रेम छूट गए हैं या नहीं.
  • double टाइप का processingDuration: कोड में बदले गए पैकेट सबमिट करने के बाद, इस फ़्रेम (जैसे, mediaTime की तरह) से डिकोड किया गया फ़्रेम, प्रज़ेंटेशन के लिए तैयार होने तक सेकंड में दिखता है.

WebRTC ऐप्लिकेशन के लिए, अन्य प्रॉपर्टी दिख सकती हैं:

  • captureTime, DOMHighResTimeStamp टाइप: लोकल या रिमोट सोर्स से आने वाले वीडियो फ़्रेम के लिए, इस समय कैमरे से फ़्रेम कैप्चर किया जाता है. रिमोट सोर्स के लिए, कैप्चर किए जाने के समय का अनुमान लगाने के लिए, घड़ी का सिंक होना और आरटीसीपी भेजने वाले की रिपोर्ट का इस्तेमाल किया जाता है. इससे आरटीपी टाइमस्टैंप को समय कैप्चर करने में मदद मिलती है.
  • DOMHighResTimeStamp टाइप का receiveTime: रिमोट सोर्स से आने वाले वीडियो फ़्रेम के लिए, वह समय होता है जब प्लैटफ़ॉर्म को कोड में बदला गया फ़्रेम मिला था. इसका मतलब है कि वह समय जब इस फ़्रेम से जुड़ा आखिरी पैकेट नेटवर्क को मिला था.
  • rtpTimestamp, unsigned long टाइप: इस वीडियो फ़्रेम से जुड़ा आरटीपी टाइमस्टैंप.

इस सूची में विशेष रुचि mediaTime है. Chromium, ऑडियो क्लॉक को video.currentTime के टाइम सोर्स के तौर पर इस्तेमाल करता है, जबकि mediaTime को सीधे फ़्रेम के presentationTimestamp से अपने-आप भरा जाता है. अगर आपको दोबारा बनाए जा सकने वाले फ़्रेम की सटीक पहचान करनी है, तो mediaTime का इस्तेमाल करें. इसमें यह भी पता करना शामिल है कि आपसे कौनसे फ़्रेम छूट गए हैं.

अगर ऐसा लगता है कि मान एक फ़्रेम में है...

वर्टिकल सिंक्रोनाइज़ेशन (या सिर्फ़ vsync), एक ग्राफ़िक टेक्नोलॉजी है, जो वीडियो के फ़्रेम रेट और मॉनिटर के रीफ़्रेश रेट को एक साथ सिंक करती है. requestVideoFrameCallback() मुख्य थ्रेड पर चलता है, लेकिन हुड के तहत, कंपोज़िटर थ्रेड पर वीडियो कंपोज़िटिंग होती है. इसलिए, इस एपीआई से मिलने वाली हर चीज़ सबसे सही है. साथ ही, ब्राउज़र कोई भी सख्त गारंटी नहीं देता. इसलिए, हो सकता है कि किसी वीडियो फ़्रेम के रेंडर होने के बाद, एपीआई एक vsync लेट हो सकता है. एपीआई के ज़रिए वेब पेज पर किए गए बदलावों को स्क्रीन पर (window.requestAnimationFrame() की तरह) दिखाने के लिए एक vsync लिया जाता है. इसलिए, अगर आप अपने वेब पेज पर mediaTime या फ़्रेम नंबर को अपडेट करते रहते हैं और उसकी तुलना, नंबर वाले वीडियो फ़्रेम से करते हैं, तो आखिरकार वीडियो एक फ़्रेम आगे का दिखेगा.

असल में बात यह है कि फ़्रेम vsync x पर तैयार है, कॉलबैक ट्रिगर होता है, फ़्रेम vsync x+1 पर रेंडर होता है, और कॉलबैक में किए गए बदलाव vsync x+2 पर रेंडर किए जाते हैं. यह जांचकर कि क्या कॉलबैक कोई vsync लेट है (और फ़्रेम पहले से ही स्क्रीन पर रेंडर हो चुका है) है. इसके लिए, यह देखें कि metadata.expectedDisplayTime करीब now है या आने वाले समय में एक vsync. अगर यह now के पांच से दस माइक्रोसेकंड के अंदर है, तो फ़्रेम पहले ही रेंडर हो चुका है. अगर expectedDisplayTime आने वाले समय में करीब सोलह मिलीसेकंड है (यह मानते हुए कि आपका ब्राउज़र/स्क्रीन 60 हर्ट्ज़ पर रीफ़्रेश हो रहा है), तो फ़्रेम के साथ सिंक हो रहा है.

डेमो

मैंने Glitch पर एक छोटा डेमो बनाया है. इसमें दिखाया गया है कि कैनवस पर फ़्रेम को बिलकुल वीडियो के फ़्रेम रेट के हिसाब से कैसे खींचा जाता है. साथ ही, डीबग करने के लिए, फ़्रेम मेटाडेटा को लॉग किया जाता है.

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 एपीआई को थॉमस गिल्बर्ट ने तय और लागू किया था. इस पोस्ट की समीक्षा जो मेडली और केसी बास्क ने की थी. अनस्प्लैश पर डेनीज़ जैन्स की हीरो इमेज.