पिक्चर में पिक्चर (पीआईपी) सुविधा की मदद से उपयोगकर्ता, फ़्लोटिंग विंडो में हमेशा दूसरी विंडो में वीडियो देख सकते हैं. इससे वे यह देख सकते हैं कि दूसरी साइटों या ऐप्लिकेशन का इस्तेमाल करते समय वे क्या देख रहे हैं.
पिक्चर में पिक्चर वेब एपीआई का इस्तेमाल करके, अपनी वेबसाइट पर वीडियो एलिमेंट के लिए पिक्चर में पिक्चर सुविधा को चालू और कंट्रोल किया जा सकता है. इसे हमारे आधिकारिक पिक्चर में पिक्चर सैंपल पर आज़माएं.
बैकग्राउंड
सितंबर 2016 में, Safari ने macOS Sierra में WebKit API का इस्तेमाल करके, पिक्चर में पिक्चर की सुविधा जोड़ी. छह महीने बाद, Chrome ने नेटिव Android API का इस्तेमाल करके, Android O रिलीज़ होने पर मोबाइल पर अपने-आप पिक्चर में पिक्चर वीडियो चलाया. छह महीने बाद, हमने Safari के साथ काम करने वाला वेब एपीआई बनाने और उसे स्टैंडर्ड तय करने के अपने मकसद का एलान किया था. इससे वेब डेवलपर को पिक्चर में पिक्चर का पूरा अनुभव बनाने और उसे कंट्रोल करने में मदद मिलेगी. पेश है!
कोड का इस्तेमाल करें
पिक्चर में पिक्चर मोड चालू करें
चलिए, बस वीडियो एलिमेंट और उपयोगकर्ता के लिए उससे इंटरैक्ट करने के तरीके के बारे में जानते हैं, जैसे कि बटन एलिमेंट.
<video id="videoElement" src="https://example.com/file.mp4"></video>
<button id="pipButtonElement"></button>
उपयोगकर्ता के जेस्चर के हिसाब से ही, पिक्चर में पिक्चर का अनुरोध करें. videoElement.play()
के किए गए प्रॉमिस के लिए ही अनुरोध करें. ऐसा इसलिए होता है, क्योंकि प्रॉमिस,
अभी तक उपयोगकर्ता के जेस्चर को लागू नहीं करती. इसके बजाय, requestPictureInPicture()
को नीचे बताए गए
pipButtonElement
पर क्लिक हैंडलर में कॉल करें. यह आपकी ज़िम्मेदारी है कि अगर कोई उपयोगकर्ता दो बार क्लिक
करता है, तो क्या होगा.
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 का इस्तेमाल करके कंट्रोल किया जा सकता है.
![पिक्चर में पिक्चर विंडो में मीडिया प्लेबैक कंट्रोल](https://developer.chrome.com/static/blog/watch-video-using-picture-in-picture/image/media-playback-controls-b73d819a65211.png?authuser=7&hl=hi)
डिफ़ॉल्ट रूप से, 'पिक्चर में पिक्चर विंडो' में हमेशा चलाएं/रोकें बटन तब तक दिखता है, जब तक कि वीडियो में 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 वीडियो सहायता
MediaStream ऑब्जेक्ट (जैसे, getUserMedia()
, getDisplayMedia()
,
canvas.captureStream()
) चलाने वाले वीडियो के लिए भी Chrome 71 में पिक्चर में पिक्चर की सुविधा काम करती है. इसका मतलब है कि आपके पास एक पिक्चर में पिक्चर विंडो दिखाने का विकल्प होगा. इसमें उपयोगकर्ता का वेबकैम वीडियो स्ट्रीम, डिसप्ले वीडियो स्ट्रीम या कैनवस एलिमेंट भी शामिल होगा. ध्यान दें कि जैसा कि नीचे दिखाया गया है, पिक्चर में पिक्चर मोड में जाने के लिए, वीडियो एलिमेंट को डीओएम से अटैच करना ज़रूरी नहीं है.
उपयोगकर्ता का वेबकैम, पिक्चर में पिक्चर विंडो में दिखाएं
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 में एक ऑडियो प्लेलिस्ट विंडो बनाई जा सकती है. आधिकारिक ऑडियो प्लेलिस्ट सैंपल देखें.
![पिक्चर में पिक्चर विंडो में ऑडियो प्लेलिस्ट](https://developer.chrome.com/static/blog/watch-video-using-picture-in-picture/image/audio-playlist-a-picture-4c2f236920dae.jpeg?authuser=7&hl=hi)
सैंपल, डेमो, और कोडलैब (कोड बनाना सीखना)
पिक्चर में पिक्चर वाला वेब एपीआई आज़माने के लिए, हमारा आधिकारिक पिक्चर में पिक्चर वाला सैंपल देखें.
इसके बाद, डेमो और कोडलैब का इस्तेमाल किया जाएगा.
आगे क्या होगा
सबसे पहले, लागू करने की स्थिति वाले पेज पर जाकर देखें कि फ़िलहाल Chrome और दूसरे ब्राउज़र पर एपीआई के कौनसे हिस्से लागू किए गए हैं.
आने वाले समय में, आपको ये बदलाव दिख सकते हैं:
- वेब डेवलपर, पसंद के मुताबिक पिक्चर में पिक्चर सेटिंग जोड़ सकेंगे.
- फ़्लोटिंग विंडो में आर्बिट्रेरी
HTMLElement
ऑब्जेक्ट दिखाने के लिए, एक वेब एपीआई दिया जाएगा.
ब्राउज़र समर्थन
पिक्चर में पिक्चर वेब एपीआई, Chrome, Edge, Opera, और Safari में काम करता है. ज़्यादा जानकारी के लिए एमडीएन देखें.
रिसॉर्स
- Chrome सुविधा की स्थिति: https://www.chromestatus.com/feature/5729206566649856
- Chrome को लागू करने से जुड़ी गड़बड़ियां: https://crbug.com/?q=component:Blink>Media>PictureInPicture
- पिक्चर में पिक्चर वेब एपीआई की खास जानकारी: https://wicg.github.io/picture-in-picture
- खास जानकारी से जुड़ी समस्याएं: https://github.com/WICG/picture-in-picture/issues
- सैंपल: https://googlechrome.github.io/samples/picture-in-picture/
- अनाधिकारिक पिक्चर-इन-पिक्चर पॉलीफ़िल: https://github.com/gbentaieb/pip-polyfill/
इस लेख को समझने और इस लेख को समझने में मदद करने के लिए, मुनीर लामोरी और जेनिफ़र अपैसिबल को बहुत-बहुत धन्यवाद. मानक तय करने की कोशिश में शामिल सभी लोगों को बहुत-बहुत धन्यवाद.