नए Media Session API की मदद से, अब मीडिया से जुड़ी सूचनाओं को अपनी पसंद के मुताबिक बनाया जा सकता है. इसके लिए, आपको उस मीडिया के लिए मेटाडेटा देना होगा जिसमें आपका वेब ऐप्लिकेशन चल रहा है. इसकी मदद से, मीडिया से जुड़े इवेंट को हैंडल भी किया जा सकता है. जैसे, वीडियो में आगे या पीछे जाना या ट्रैक बदलना. ये इवेंट, सूचनाओं या मीडिया बटन से मिल सकते हैं. क्या आप उत्साहित हैं? मीडिया सेशन के आधिकारिक सैंपल आज़माएं.
Media Session API, Chrome 57 में काम करता है. यह वर्शन फ़रवरी 2017 में बीटा और मार्च 2017 में स्टैबल के तौर पर रिलीज़ किया गया था.
Gimme what I want
क्या आपको MediaSession API के बारे में पहले से पता है और आपको कुछ बोयलरप्लेट कोड को कॉपी करके चिपकाना है? तो यह रहा.
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
artist: 'Rick Astley',
album: 'Whenever You Need Somebody',
artwork: [
{ src: 'https://dummyimage.com/96x96', sizes: '96x96', type: 'image/png' },
{ src: 'https://dummyimage.com/128x128', sizes: '128x128', type: 'image/png' },
{ src: 'https://dummyimage.com/192x192', sizes: '192x192', type: 'image/png' },
{ src: 'https://dummyimage.com/256x256', sizes: '256x256', type: 'image/png' },
{ src: 'https://dummyimage.com/384x384', sizes: '384x384', type: 'image/png' },
{ src: 'https://dummyimage.com/512x512', sizes: '512x512', type: 'image/png' },
]
});
navigator.mediaSession.setActionHandler('play', function() {});
navigator.mediaSession.setActionHandler('pause', function() {});
navigator.mediaSession.setActionHandler('seekbackward', function() {});
navigator.mediaSession.setActionHandler('seekforward', function() {});
navigator.mediaSession.setActionHandler('previoustrack', function() {});
navigator.mediaSession.setActionHandler('nexttrack', function() {});
}
कोड डालें
आइए, खेलते हैं 🎷
अपने वेब पेज में एक आसान <audio>
एलिमेंट जोड़ें और कई मीडिया सोर्स असाइन करें, ताकि ब्राउज़र यह चुन सके कि कौनसा सोर्स सबसे अच्छा काम करता है.
<audio controls>
<source src="audio.mp3" type="audio/mp3"/>
<source src="audio.ogg" type="audio/ogg"/>
</audio>
जैसा कि आपको पता होगा, Android के लिए Chrome पर ऑडियो एलिमेंट के लिए autoplay
बंद है. इसका मतलब है कि हमें ऑडियो एलिमेंट के लिए play()
तरीके का इस्तेमाल करना होगा. यह तरीका, उपयोगकर्ता के जेस्चर से ट्रिगर होना चाहिए. जैसे, टच या माउस क्लिक.
इसका मतलब है कि pointerup
, click
, और touchend
इवेंट को सुनना. दूसरे शब्दों में, आपके वेब ऐप्लिकेशन के असल में आवाज़ करने से पहले, उपयोगकर्ता को किसी बटन पर क्लिक करना होगा.
playButton.addEventListener('pointerup', function(event) {
let audio = document.querySelector('audio');
// User interacted with the page. Let's play audio...
audio.play()
.then(_ => { /* Set up media session... */ })
.catch(error => { console.log(error) });
});
अगर आपको पहले इंटरैक्शन के तुरंत बाद ऑडियो नहीं चलाना है, तो हमारा सुझाव है कि आप ऑडियो एलिमेंट के load()
तरीके का इस्तेमाल करें. ब्राउज़र के लिए, यह एक तरीका है जिससे यह पता लगाया जा सकता है कि उपयोगकर्ता ने एलिमेंट के साथ इंटरैक्ट किया है या नहीं. ध्यान दें कि इससे वीडियो को आसानी से चलाने में भी मदद मिल सकती है, क्योंकि कॉन्टेंट पहले से लोड हो जाएगा.
let audio = document.querySelector('audio');
welcomeButton.addEventListener('pointerup', function(event) {
// User interacted with the page. Let's load audio...
<strong>audio.load()</strong>
.then(_ => { /* Show play button for instance... */ })
.catch(error => { console.log(error) });
});
// Later...
playButton.addEventListener('pointerup', function(event) {
<strong>audio.play()</strong>
.then(_ => { /* Set up media session... */ })
.catch(error => { console.log(error) });
});
सूचना को अपनी पसंद के मुताबिक बनाएं
जब आपका वेब ऐप्लिकेशन ऑडियो चला रहा होता है, तब आपको सूचना ट्रे में मीडिया की सूचना दिखती है. Android पर, Chrome दस्तावेज़ के टाइटल और सबसे बड़ी आइकॉन इमेज का इस्तेमाल करके, सही जानकारी दिखाने की पूरी कोशिश करता है.
मेटाडेटा सेट करना
मीडिया सेशन एपीआई के ज़रिए टाइटल, कलाकार, एल्बम का नाम, और आर्टवर्क जैसे मीडिया सेशन का मेटाडेटा सेट करके, इस मीडिया सूचना को पसंद के मुताबिक बनाने का तरीका जानें.
// When audio starts playing...
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
artist: 'Rick Astley',
album: 'Whenever You Need Somebody',
artwork: [
{ src: 'https://dummyimage.com/96x96', sizes: '96x96', type: 'image/png' },
{ src: 'https://dummyimage.com/128x128', sizes: '128x128', type: 'image/png' },
{ src: 'https://dummyimage.com/192x192', sizes: '192x192', type: 'image/png' },
{ src: 'https://dummyimage.com/256x256', sizes: '256x256', type: 'image/png' },
{ src: 'https://dummyimage.com/384x384', sizes: '384x384', type: 'image/png' },
{ src: 'https://dummyimage.com/512x512', sizes: '512x512', type: 'image/png' },
]
});
}
वीडियो चलाने के बाद, आपको मीडिया सेशन को "रिलीज़" करने की ज़रूरत नहीं है, क्योंकि सूचना अपने-आप हट जाएगी. ध्यान रखें कि किसी भी वीडियो को चलाने पर, मौजूदा navigator.mediaSession.metadata
का इस्तेमाल किया जाएगा. इसलिए, आपको इसे अपडेट करना होगा, ताकि यह पक्का किया जा सके कि मीडिया सूचना में हमेशा काम की जानकारी दिख रही हो.
पिछला ट्रैक / अगला ट्रैक
अगर आपका वेब ऐप्लिकेशन कोई प्लेलिस्ट उपलब्ध कराता है, तो हो सकता है कि आप उपयोगकर्ता को "पिछला ट्रैक" और "अगला ट्रैक" आइकॉन की मदद से, सीधे मीडिया सूचना से अपनी प्लेलिस्ट पर नेविगेट करने की अनुमति देना चाहें.
let audio = document.createElement('audio');
let playlist = ['audio1.mp3', 'audio2.mp3', 'audio3.mp3'];
let index = 0;
navigator.mediaSession.setActionHandler('previoustrack', function() {
// User clicked "Previous Track" media notification icon.
index = (index - 1 + playlist.length) % playlist.length;
playAudio();
});
navigator.mediaSession.setActionHandler('nexttrack', function() {
// User clicked "Next Track" media notification icon.
index = (index + 1) % playlist.length;
playAudio();
});
function playAudio() {
audio.src = playlist[index];
audio.play()
.then(_ => { /* Set up media session... */ })
.catch(error => { console.log(error); });
}
playButton.addEventListener('pointerup', function(event) {
playAudio();
});
ध्यान दें कि मीडिया ऐक्शन हैंडलर मौजूद रहेंगे. यह इवेंट लिसनर पैटर्न से काफ़ी मिलता-जुलता है. हालांकि, इवेंट को हैंडल करने का मतलब है कि ब्राउज़र कोई भी डिफ़ॉल्ट व्यवहार करना बंद कर देता है. साथ ही, इसका इस्तेमाल इस सिग्नल के तौर पर किया जाता है कि आपका वेब ऐप्लिकेशन, मीडिया ऐक्शन के साथ काम करता है. इसलिए, जब तक सही ऐक्शन हैंडलर सेट नहीं किया जाता, तब तक मीडिया ऐक्शन कंट्रोल नहीं दिखाए जाएंगे.
वैसे, मीडिया ऐक्शन हैंडलर को अनसेट करना उतना ही आसान है जितना उसे null
को असाइन करना.
पीछे जाएं / आगे बढ़ाएं
Media Session API की मदद से, "पीछे जाएं" और "आगे जाएं" मीडिया सूचना आइकॉन दिखाए जा सकते हैं. ऐसा तब किया जा सकता है, जब आपको वीडियो में आगे या पीछे जाने के लिए, समय कंट्रोल करना हो.
let skipTime = 10; // Time to skip in seconds
navigator.mediaSession.setActionHandler('seekbackward', function() {
// User clicked "Seek Backward" media notification icon.
audio.currentTime = Math.max(audio.currentTime - skipTime, 0);
});
navigator.mediaSession.setActionHandler('seekforward', function() {
// User clicked "Seek Forward" media notification icon.
audio.currentTime = Math.min(audio.currentTime + skipTime, audio.duration);
});
चलाएं / रोकें
मीडिया की सूचना में "चलाएं/रोकें" आइकॉन हमेशा दिखता है. साथ ही, इससे जुड़े इवेंट को ब्राउज़र अपने-आप मैनेज करता है. अगर किसी वजह से डिफ़ॉल्ट कार्रवाई काम नहीं करती है, तब भी मीडिया इवेंट "चलाएं" और "रोकें" बटन को मैनेज किया जा सकता है.
navigator.mediaSession.setActionHandler('play', function() {
// User clicked "Play" media notification icon.
// Do something more than just playing current audio...
});
navigator.mediaSession.setActionHandler('pause', function() {
// User clicked "Pause" media notification icon.
// Do something more than just pausing current audio...
});
हर जगह सूचनाएं पाना
Media Session API की सबसे अच्छी बात यह है कि मीडिया का मेटाडेटा और कंट्रोल, सिर्फ़ सूचना ट्रे में ही नहीं दिखते. मीडिया सूचना, पहने जाने वाले किसी भी जोड़े गए डिवाइस से अपने-आप सिंक हो जाती है. यह लॉक स्क्रीन पर भी दिखता है.
इसे ऑफ़लाइन चलाने के लिए
मुझे पता है कि आपके मन में क्या चल रहा है. सेवा वर्कर की मदद से!
सही, लेकिन सबसे पहले आपको यह पक्का करना है कि इस चेकलिस्ट में दिए गए सभी आइटम की जांच की गई है:
- सभी मीडिया और आर्टवर्क फ़ाइलों को सही
Cache-Control
एचटीटीपी हेडर के साथ दिखाया जाता है. इससे ब्राउज़र, पहले फ़ेच किए गए संसाधनों को कैश मेमोरी में सेव कर पाएगा और उन्हें फिर से इस्तेमाल कर पाएगा. कैश मेमोरी से जुड़ी चेकलिस्ट देखें. - पक्का करें कि सभी मीडिया और आर्टवर्क फ़ाइलें,
Allow-Control-Allow-Origin: *
एचटीटीपी हेडर के साथ दिखाई जाएं. इससे तीसरे पक्ष के वेब ऐप्लिकेशन, आपके वेब सर्वर से एचटीटीपी रिस्पॉन्स फ़ेच और इस्तेमाल कर पाएंगे.
सर्विस वर्कर को कैश मेमोरी में सेव करने की रणनीति
मीडिया फ़ाइलों के लिए, मेरा सुझाव है कि आप "कैश मेमोरी का इस्तेमाल करें और नेटवर्क का इस्तेमाल तब करें, जब कैश मेमोरी में फ़ाइल उपलब्ध न हो" वाली आसान रणनीति अपनाएं. इस रणनीति के बारे में जैक आर्किबाल्ड ने बताया है.
हालांकि, आर्टवर्क के लिए, मैं थोड़ा ज़्यादा सटीक तरीके से काम करूंगा और यहां दिया गया तरीका चुनूंगा:
If
आर्टवर्क पहले से ही कैश मेमोरी में मौजूद है, उसे कैश मेमोरी से दिखाएंElse
नेटवर्क से आर्टवर्क फ़ेच करनाIf
फ़ेच हो गया है, नेटवर्क आर्टवर्क को कैश मेमोरी में जोड़ें और उसे दिखाएंElse
कैश मेमोरी से फ़ॉलबैक आर्टवर्क दिखाना
ऐसा करने से, मीडिया की मदद से सूचना पाने के आइकॉन हमेशा अच्छे दिखेंगे. भले ही, ब्राउज़र उन्हें फ़ेच न कर पाए. इसे लागू करने का तरीका यहां बताया गया है:
const FALLBACK_ARTWORK_URL = 'fallbackArtwork.png';
addEventListener('install', event => {
self.skipWaiting();
event.waitUntil(initArtworkCache());
});
function initArtworkCache() {
caches.open('artwork-cache-v1')
.then(cache => cache.add(FALLBACK_ARTWORK_URL));
}
addEventListener('fetch', event => {
if (/artwork-[0-9]+\.png$/.test(event.request.url)) {
event.respondWith(handleFetchArtwork(event.request));
}
});
function handleFetchArtwork(request) {
// Return cache request if it's in the cache already, otherwise fetch
// network artwork.
return getCacheArtwork(request)
.then(cacheResponse => cacheResponse || getNetworkArtwork(request));
}
function getCacheArtwork(request) {
return caches.open('artwork-cache-v1')
.then(cache => cache.match(request));
}
function getNetworkArtwork(request) {
// Fetch network artwork.
return fetch(request)
.then(networkResponse => {
if (networkResponse.status !== 200) {
return Promise.reject('Network artwork response is not valid');
}
// Add artwork to the cache for later use and return network response.
addArtworkToCache(request, networkResponse.clone())
return networkResponse;
})
.catch(error => {
// Return cached fallback artwork.
return getCacheArtwork(new Request(FALLBACK_ARTWORK_URL))
});
}
function addArtworkToCache(request, response) {
return caches.open('artwork-cache-v1')
.then(cache => cache.put(request, response));
}
उपयोगकर्ता को कैश मेमोरी को कंट्रोल करने की अनुमति देना
जब कोई उपयोगकर्ता आपके वेब ऐप्लिकेशन से कॉन्टेंट इस्तेमाल करता है, तो मीडिया और आर्टवर्क फ़ाइलें उसके डिवाइस पर बहुत ज़्यादा जगह ले सकती हैं. यह दिखाना आपकी ज़िम्मेदारी है कि कैश मेमोरी का कितना इस्तेमाल किया गया है और उपयोगकर्ताओं को इसे मिटाने की सुविधा दी गई है. हमारे लिए यह खुशी की बात है कि Cache API की मदद से, ऐसा करना काफ़ी आसान है.
// Here's how I'd compute how much cache is used by artwork files...
caches.open('artwork-cache-v1')
.then(cache => cache.matchAll())
.then(responses => {
let cacheSize = 0;
let blobQueue = Promise.resolve();
responses.forEach(response => {
let responseSize = response.headers.get('content-length');
if (responseSize) {
// Use content-length HTTP header when possible.
cacheSize += Number(responseSize);
} else {
// Otherwise, use the uncompressed blob size.
blobQueue = blobQueue.then(_ => response.blob())
.then(blob => { cacheSize += blob.size; blob.close(); });
}
});
return blobQueue.then(_ => {
console.log('Artwork cache is about ' + cacheSize + ' Bytes.');
});
})
.catch(error => { console.log(error); });
// And here's how to delete some artwork files...
const artworkFilesToDelete = ['artwork1.png', 'artwork2.png', 'artwork3.png'];
caches.open('artwork-cache-v1')
.then(cache => Promise.all(artworkFilesToDelete.map(artwork => cache.delete(artwork))))
.catch(error => { console.log(error); });
लागू करने के बारे में ज़रूरी बातें
- मीडिया की सूचनाएं दिखाने के लिए, Chrome for Android सिर्फ़ तब ऑडियो फ़ोकस का "पूरा" अनुरोध करता है, जब मीडिया फ़ाइल की अवधि कम से कम पांच सेकंड हो.
- सूचना आर्टवर्क, BLOB यूआरएल और डेटा यूआरएल के साथ काम करता है.
- अगर कोई आर्टवर्क तय नहीं किया गया है और सही साइज़ में कोई आइकॉन इमेज मौजूद है, तो मीडिया की सूचनाएं देने वाली सुविधा उसका इस्तेमाल करेगी.
- Android के लिए Chrome में, सूचना के आर्टवर्क का साइज़
512x512
है. कम कीमत वाले डिवाइसों के लिए, यह256x256
है. audio.src = ''
का इस्तेमाल करके, मीडिया से जुड़ी सूचनाएं खारिज करें.- Web Audio API, पुरानी वजहों से Android ऑडियो फ़ोकस का अनुरोध नहीं करता. इसलिए, इसे Media Session API के साथ काम करने के लिए, Web Audio API के इनपुट सोर्स के तौर पर
<audio>
एलिमेंट को जोड़ना ही एकमात्र तरीका है. हमें उम्मीद है कि Web AudioFocus API के सुझाव से, आने वाले समय में इस समस्या को हल किया जा सकेगा. - मीडिया सेशन के कॉल, मीडिया सूचनाओं पर सिर्फ़ तब असर डालेंगे, जब वे उसी फ़्रेम से हों जिससे मीडिया संसाधन का इस्तेमाल किया गया हो. नीचे दिया गया स्निपेट देखें.
<iframe id="iframe">
<audio>...</audio>
</iframe>
<script>
iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
...
});
</script>
सहायता
फ़िलहाल, Android के लिए Chrome ही ऐसा प्लैटफ़ॉर्म है जिस पर Media Session API काम करता है. ब्राउज़र में इस सुविधा के लागू होने की स्थिति के बारे में अप-टू-डेट जानकारी, Chrome Platform Status पर देखी जा सकती है.
सैंपल और डेमो
हमारे आधिकारिक Chrome मीडिया सेशन के सैंपल देखें. इनमें ब्लेंडर फ़ाउंडेशन और यान मॉर्गनस्टर्न के काम की जानकारी शामिल है.
संसाधन
मीडिया सेशन स्पेसिफ़िकेशन: wicg.github.io/mediasession
खास जानकारी से जुड़ी समस्याएं: github.com/WICG/mediasession/issues
Chrome में गड़बड़ियां: crbug.com