'पिक्चर में पिक्चर' सुविधा का इस्तेमाल करके वीडियो देखना

François Beaufort
François Beaufort

पिक्चर में पिक्चर (पीआईपी) सुविधा की मदद से उपयोगकर्ता, फ़्लोटिंग विंडो में वीडियो देख सकते हैं. यह सुविधा हमेशा दूसरी विंडो पर सबसे ऊपर होती है. इससे, वे इस बात पर नज़र रख सकते हैं कि दूसरी साइटों या ऐप्लिकेशन से इंटरैक्ट करते समय वे क्या देख रहे हैं.

पिक्चर में पिक्चर वेब एपीआई की मदद से, अपनी वेबसाइट पर वीडियो एलिमेंट के लिए पिक्चर में पिक्चर मोड शुरू किया जा सकता है और उसे कंट्रोल किया जा सकता है. इसे हमारे पिक्चर में पिक्चर के आधिकारिक सैंपल पर आज़माएं.

बैकग्राउंड

सितंबर 2016 में, Safari ने macOS Sierra में WebKit API के ज़रिए, पिक्चर में पिक्चर की सुविधा जोड़ी थी. छह महीने बाद, Android O के रिलीज़ होने के साथ, Chrome ने मोबाइल पर नेटिव Android API का इस्तेमाल करके, पिक्चर में पिक्चर मोड में वीडियो अपने-आप चलाया. छह महीने बाद, हमने अपने इंटेंट का एलान किया. इसमें हमने बताया था कि हम एक वेब एपीआई बनाएंगे और उसे स्टैंडर्ड बनाएंगे. यह एपीआई, Safari के साथ काम करेगा. इससे वेब डेवलपर, पिक्चर में पिक्चर की सुविधा को पूरी तरह से बना और कंट्रोल कर पाएंगे. और अब हम यहां हैं!

कोड डालें

पिक्चर में पिक्चर मोड चालू करना

सबसे पहले, वीडियो एलिमेंट और उपयोगकर्ता के लिए उससे इंटरैक्ट करने का तरीका, जैसे कि बटन एलिमेंट से शुरू करते हैं.

<video id="videoElement" src="https://example.com/file.mp4"></video>
<button id="pipButtonElement"></button>

पिक्चर में पिक्चर की सुविधा का अनुरोध, सिर्फ़ उपयोगकर्ता के जेस्चर के जवाब में करें. videoElement.play() से मिले वाद में कभी भी ऐसा अनुरोध न करें. ऐसा इसलिए है, क्योंकि अभी तक, वादे उपयोगकर्ता के जेस्चर को प्रोपेगेट नहीं करते. इसके बजाय, pipButtonElement पर क्लिक करने पर होने वाली कार्रवाई के हैंडलर में requestPictureInPicture() को कॉल करें, जैसा कि यहां दिखाया गया है. अगर कोई उपयोगकर्ता दो बार क्लिक करता है, तो यह तय करना आपकी ज़िम्मेदारी है कि क्या करना है.

pipButtonElement.addEventListener('click', async function () {
  pipButtonElement.disabled = true;

  await videoElement.requestPictureInPicture();

  pipButtonElement.disabled = false;
});

प्रॉमिस पूरा होने के बाद, Chrome वीडियो को छोटी विंडो में बदल देता है. इस विंडो को उपयोगकर्ता, अपनी पसंद के मुताबिक कहीं भी ले जा सकता है और दूसरी विंडो के ऊपर रख सकता है.

आपका काम हो गया. बहुत बढ़िया! अब पढ़ना बंद करके, अपनी ज़रूरत के मुताबिक छुट्टियां लें. माफ़ करें, ऐसा हमेशा नहीं होता. इनमें से किसी भी वजह से, वादा अस्वीकार किया जा सकता है:

  • सिस्टम पर 'पिक्चर में पिक्चर' सुविधा काम नहीं करती.
  • अनुमतियों से जुड़ी नीति की वजह से, दस्तावेज़ में पिक्चर में पिक्चर मोड का इस्तेमाल नहीं किया जा सकता.
  • वीडियो का मेटाडेटा अभी तक लोड नहीं हुआ है (videoElement.readyState === 0).
  • वीडियो फ़ाइल सिर्फ़ ऑडियो फ़ॉर्मैट में है.
  • नया disablePictureInPicture एट्रिब्यूट, वीडियो एलिमेंट पर मौजूद होता है.
  • कॉल, उपयोगकर्ता के जेस्चर इवेंट हैंडलर (उदाहरण के लिए, बटन पर क्लिक) में नहीं किया गया था. Chrome 74 से, यह सिर्फ़ तब लागू होगा, जब पिक्चर में पिक्चर मोड में कोई एलिमेंट पहले से मौजूद न हो.

नीचे दिए गए सुविधा से जुड़ी सहायता सेक्शन में, इन पाबंदियों के आधार पर बटन को चालू/बंद करने का तरीका बताया गया है.

इन संभावित गड़बड़ियों को कैप्चर करने के लिए, try...catch ब्लॉक जोड़ें और उपयोगकर्ता को बताएं कि क्या हो रहा है.

pipButtonElement.addEventListener('click', async function () {
  pipButtonElement.disabled = true;

  try {
    await videoElement.requestPictureInPicture();
  } catch (error) {
    // TODO: Show error message to user.
  } finally {
    pipButtonElement.disabled = false;
  }
});

वीडियो एलिमेंट, पिक्चर में पिक्चर मोड में होने पर भी वैसा ही काम करता है जैसा कि सामान्य मोड में होता है: इवेंट ट्रिगर होते हैं और कॉल करने के तरीके काम करते हैं. यह पिक्चर में पिक्चर विंडो की स्थिति में होने वाले बदलावों को दिखाता है. जैसे, चलाना, रोकना, आगे या पीछे जाना वगैरह. साथ ही, JavaScript में प्रोग्राम के हिसाब से भी स्थिति बदली जा सकती है.

पिक्चर में पिक्चर मोड से बाहर निकलना

अब, बटन को पिक्चर में पिक्चर मोड में जाने और उससे बाहर निकलने के लिए टॉगल करने वाला बनाएं. हमें सबसे पहले यह देखना होगा कि रीड-ओनली ऑब्जेक्ट document.pictureInPictureElement, हमारा वीडियो एलिमेंट है या नहीं. अगर ऐसा नहीं है, तो हम ऊपर बताए गए तरीके से पिक्चर में पिक्चर मोड में जाने का अनुरोध भेजते हैं. अगर ऐसा नहीं होता है, तो हम document.exitPictureInPicture() को कॉल करके, उसे छोड़ने के लिए कहते हैं. इसका मतलब है कि वीडियो, ओरिजनल टैब में फिर से दिखेगा. ध्यान दें कि यह तरीका भी एक प्रॉमिस दिखाता है.

    ...
    try {
      if (videoElement !== document.pictureInPictureElement) {
        await videoElement.requestPictureInPicture();
      } else {
        await document.exitPictureInPicture();
      }
    }
    ...

पिक्चर में पिक्चर मोड के इवेंट सुनना

ऑपरेटिंग सिस्टम आम तौर पर, पिक्चर में पिक्चर की सुविधा को एक विंडो तक ही सीमित रखते हैं. इसलिए, Chrome को इस पैटर्न के हिसाब से लागू किया जाता है. इसका मतलब है कि उपयोगकर्ता एक बार में सिर्फ़ एक पिक्चर में पिक्चर वीडियो चला सकते हैं. आपको यह उम्मीद रखनी चाहिए कि उपयोगकर्ता तब भी पिक्चर में पिक्चर मोड से बाहर निकल जाएंगे, जब आपने इसके लिए न पूछा हो.

नए enterpictureinpicture और leavepictureinpicture इवेंट हैंडलर की मदद से, हम उपयोगकर्ताओं के अनुभव को बेहतर बना सकते हैं. इसके लिए, वीडियो का कैटलॉग ब्राउज़ करने से लेकर लाइव स्ट्रीम चैट करने तक, सब कुछ हो सकता है.

videoElement.addEventListener('enterpictureinpicture', function (event) {
  // Video entered Picture-in-Picture.
});

videoElement.addEventListener('leavepictureinpicture', function (event) {
  // Video left Picture-in-Picture.
  // User may have played a Picture-in-Picture video from a different page.
});

पिक्चर में पिक्चर विंडो को पसंद के मुताबिक बनाना

Chrome 74 में, पिक्चर में पिक्चर विंडो में 'चलाएं/रोकें', पिछला ट्रैक, और अगला ट्रैक बटन काम करते हैं. इन्हें Media Session API का इस्तेमाल करके कंट्रोल किया जा सकता है.

&#39;पिक्चर में पिक्चर&#39; विंडो में मीडिया प्लेबैक कंट्रोल
पहला डायग्राम. 'पिक्चर में पिक्चर' विंडो में मीडिया प्लेबैक कंट्रोल

डिफ़ॉल्ट रूप से, 'चलाएं/रोकें' बटन हमेशा पिक्चर में पिक्चर विंडो में दिखता है. हालांकि, यह बटन तब तक दिखता है, जब तक वीडियो में MediaStream ऑब्जेक्ट (जैसे कि getUserMedia(), getDisplayMedia(), canvas.captureStream()) न चल रहा हो या वीडियो की MediaSource अवधि को +Infinity पर सेट किया गया हो (जैसे कि लाइव फ़ीड). यह पक्का करने के लिए कि चलाएं/रोकें बटन हमेशा दिखे, "चलाएं" और "रोकें", दोनों मीडिया इवेंट के लिए कुछ मीडिया सेशन ऐक्शन हैंडलर सेट करें. इसके लिए, नीचे दिया गया तरीका अपनाएं.

// Show a play/pause button in the Picture-in-Picture window
navigator.mediaSession.setActionHandler('play', function () {
  // User clicked "Play" button.
});
navigator.mediaSession.setActionHandler('pause', function () {
  // User clicked "Pause" button.
});

"पिछला ट्रैक" और "अगला ट्रैक" विंडो कंट्रोल दिखाने का तरीका एक जैसा है. उन मीडिया सेशन के लिए मीडिया सेशन ऐक्शन हैंडलर सेट करने पर, उन्हें पिक्चर में पिक्चर विंडो में दिखाया जाएगा. साथ ही, आपके पास इन कार्रवाइयों को मैनेज करने का विकल्प होगा.

navigator.mediaSession.setActionHandler('previoustrack', function () {
  // User clicked "Previous Track" button.
});

navigator.mediaSession.setActionHandler('nexttrack', function () {
  // User clicked "Next Track" button.
});

इसे काम करते हुए देखने के लिए, आधिकारिक मीडिया सेशन सैंपल आज़माएं.

पिक्चर में पिक्चर विंडो का साइज़ देखना

अगर आपको वीडियो को पिक्चर में पिक्चर मोड में जाने और उससे बाहर आने पर, वीडियो की क्वालिटी में बदलाव करना है, तो आपको पिक्चर में पिक्चर विंडो का साइज़ पता होना चाहिए. साथ ही, अगर कोई उपयोगकर्ता मैन्युअल तरीके से विंडो का साइज़ बदलता है, तो आपको इसकी सूचना भी मिलनी चाहिए.

नीचे दिए गए उदाहरण में, 'पिक्चर में पिक्चर' विंडो बनाने या उसका साइज़ बदलने पर, उसकी चौड़ाई और ऊंचाई पाने का तरीका बताया गया है.

let pipWindow;

videoElement.addEventListener('enterpictureinpicture', function (event) {
  pipWindow = event.pictureInPictureWindow;
  console.log(`> Window size is ${pipWindow.width}x${pipWindow.height}`);
  pipWindow.addEventListener('resize', onPipWindowResize);
});

videoElement.addEventListener('leavepictureinpicture', function (event) {
  pipWindow.removeEventListener('resize', onPipWindowResize);
});

function onPipWindowResize(event) {
  console.log(
    `> Window size changed to ${pipWindow.width}x${pipWindow.height}`
  );
  // TODO: Change video quality based on Picture-in-Picture window size.
}

हमारा सुझाव है कि आप सीधे तौर पर साइज़ बदलने वाले इवेंट से न जुड़ें. ऐसा इसलिए, क्योंकि पिक्चर में पिक्चर विंडो के साइज़ में किए गए हर छोटे बदलाव से एक अलग इवेंट ट्रिगर होगा. अगर हर बार साइज़ बदलने पर ज़्यादा समय लगने वाला कोई काम किया जा रहा है, तो परफ़ॉर्मेंस से जुड़ी समस्याएं हो सकती हैं. दूसरे शब्दों में, साइज़ बदलने की कार्रवाई से इवेंट बहुत तेज़ी से बार-बार ट्रिगर होंगे. हमारा सुझाव है कि इस समस्या को हल करने के लिए, थ्रॉटलिंग और डिबॉउंसिंग जैसी सामान्य तकनीकों का इस्तेमाल करें.

सुविधा के लिए सहायता

ऐसा हो सकता है कि पिक्चर में पिक्चर वेब एपीआई काम न करे. इसलिए, आपको समय के साथ बेहतर बनाने की सुविधा बनाने के लिए इसका पता लगाना होगा. भले ही, यह सुविधा काम करती हो, लेकिन हो सकता है कि उपयोगकर्ता ने इसे बंद कर दिया हो या अनुमतियों की नीति की वजह से यह बंद हो. अच्छी बात यह है कि इसे पता करने के लिए नए बूलियन document.pictureInPictureEnabled का इस्तेमाल किया जा सकता है.

if (!('pictureInPictureEnabled' in document)) {
  console.log('The Picture-in-Picture Web API is not available.');
} else if (!document.pictureInPictureEnabled) {
  console.log('The Picture-in-Picture Web API is disabled.');
}

वीडियो के लिए किसी खास बटन एलिमेंट पर लागू किया गया, यह तरीका 'पिक्चर में पिक्चर' बटन की दिखने की सुविधा को मैनेज करने के लिए इस्तेमाल किया जा सकता है.

if ('pictureInPictureEnabled' in document) {
  // Set button ability depending on whether Picture-in-Picture can be used.
  setPipButton();
  videoElement.addEventListener('loadedmetadata', setPipButton);
  videoElement.addEventListener('emptied', setPipButton);
} else {
  // Hide button if Picture-in-Picture is not supported.
  pipButtonElement.hidden = true;
}

function setPipButton() {
  pipButtonElement.disabled =
    videoElement.readyState === 0 ||
    !document.pictureInPictureEnabled ||
    videoElement.disablePictureInPicture;
}

MediaStream वीडियो के लिए सहायता

Chrome 71 में, वीडियो चलाने वाले MediaStream ऑब्जेक्ट (जैसे, getUserMedia(), getDisplayMedia(), canvas.captureStream()) भी पिक्चर में पिक्चर मोड के साथ काम करते हैं. इसका मतलब है कि आपके पास पिक्चर में पिक्चर वाली ऐसी विंडो दिखाने का विकल्प है जिसमें उपयोगकर्ता के वेबकैम की वीडियो स्ट्रीम, डिसप्ले वीडियो स्ट्रीम या कैनवस एलिमेंट शामिल हो. ध्यान दें कि यहां दिखाए गए तरीके के मुताबिक, पिक्चर में पिक्चर मोड में जाने के लिए, वीडियो एलिमेंट को डीओएम से अटैच करने की ज़रूरत नहीं है.

'पिक्चर में पिक्चर' विंडो में उपयोगकर्ता का वेबकैम दिखाना

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getUserMedia({video: true});
video.play();

// Later on, video.requestPictureInPicture();

डिसप्ले को पिक्चर में पिक्चर विंडो में दिखाना

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getDisplayMedia({video: true});
video.play();

// Later on, video.requestPictureInPicture();

पिक्चर में पिक्चर विंडो में कैनवस एलिमेंट दिखाना

const canvas = document.createElement('canvas');
// Draw something to canvas.
canvas.getContext('2d').fillRect(0, 0, canvas.width, canvas.height);

const video = document.createElement('video');
video.muted = true;
video.srcObject = canvas.captureStream();
video.play();

// Later on, video.requestPictureInPicture();

canvas.captureStream() को Media Session API के साथ इस्तेमाल करके, Chrome 74 में ऑडियो प्लेलिस्ट की विंडो बनाई जा सकती है. ऑडियो प्लेलिस्ट का आधिकारिक सैंपल देखें.

पिक्चर में पिक्चर विंडो में ऑडियो प्लेलिस्ट
दूसरा डायग्राम. पिक्चर में पिक्चर विंडो में ऑडियो प्लेलिस्ट

सैंपल, डेमो, और कोडलैब

पिक्चर में पिक्चर वाला वेब एपीआई आज़माने के लिए, पिक्चर में पिक्चर का आधिकारिक सैंपल देखें.

इसके बाद, डेमो और कोडलैब उपलब्ध कराए जाएंगे.

अब क्या होगा

सबसे पहले, लागू करने की स्थिति वाला पेज देखें. इससे आपको पता चलेगा कि फ़िलहाल Chrome और दूसरे ब्राउज़र में एपीआई के कौनसे हिस्से लागू हैं.

आने वाले समय में, आपको ये सुविधाएं मिल सकती हैं:

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

पिक्चर में पिक्चर वेब एपीआई, Chrome, Edge, Opera, और Safari पर काम करता है. ज़्यादा जानकारी के लिए, MDN देखें.

संसाधन

पिक्चर में पिक्चर की सुविधा पर काम करने और इस लेख को तैयार करने में मदद करने के लिए, जेनिफर अपैसिबल और मौनीर लामौरी का धन्यवाद. साथ ही, स्टैंडर्ड बनाने की प्रोसेस में शामिल सभी लोगों का बहुत-बहुत धन्यवाद.