मीडिया सूचनाओं को मनमुताबिक बनाएं और प्लेलिस्ट मैनेज करें

François Beaufort
François Beaufort

नए Media Session API की मदद से, अब आपके पास मीडिया सूचनाओं को अपनी पसंद के मुताबिक बनाने का विकल्प है. इसके लिए, आपको अपने वेब ऐप्लिकेशन में चल रहे मीडिया का मेटाडेटा देना होगा. इससे आपको मीडिया से जुड़े इवेंट मैनेज करने की सुविधा भी मिलती है. जैसे, सूचनाओं या मीडिया बटन से आने वाले कॉन्टेंट में बदलाव करना या उसे ट्रैक करना. क्या आप उत्साहित हैं? आधिकारिक मीडिया सेशन सैंपल आज़माएं.

Media Session API, Chrome 57 में काम करता है (फ़रवरी 2017 में बीटा और मार्च 2017 में बना रहेगा).

मीडिया सेशन से कम शब्दों में, ज़्यादा जानकारी;
माइकल Alø-Nielsen / CC BY 2.0 की ओर से फ़ोटो

मुझे जो चाहिए वह मुझे दें

आपको Media Session 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() {});
}

कोड का इस्तेमाल करें

आइए खेलें journal

अपने वेब पेज में कोई आसान <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 की खास बात यह है कि सूचना ट्रे ही एक ऐसी जगह नहीं है जहां मीडिया मेटाडेटा और कंट्रोल दिखते हैं. मीडिया सूचना, पहने जाने वाले किसी भी डिवाइस से अपने-आप सिंक हो जाती है. और वह लॉक स्क्रीन पर भी दिखता है.

स्क्रीन लॉक करें
लॉक स्क्रीन - फ़ोटो माइकल आलो-नेल / CC BY 2.0
Wear सूचना
Wear से जुड़ी सूचना

ऑफ़लाइन होने पर आनंद लें

मुझे पता है कि तुम क्या सोच रही हो. सर्विस वर्कर को बचाने का काम!

सही है, लेकिन सबसे पहले, आपको यह पक्का करना होगा कि इस चेकलिस्ट के सभी आइटम पर सही का निशान लगा हो:

  • सभी मीडिया और आर्टवर्क फ़ाइलें, सही 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));
}

उपयोगकर्ता को कैश मेमोरी कंट्रोल करने दें

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

// 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); });

लागू करने से जुड़ी जानकारी

  • Android के लिए Chrome "फ़ुल" ऑडियो फ़ोकस का अनुरोध करता है कि वह मीडिया सूचनाएं सिर्फ़ तब दिखाए, जब मीडिया फ़ाइल की अवधि कम से कम 5 सेकंड हो.
  • सूचना आर्टवर्क, ब्लॉब यूआरएल और डेटा यूआरएल के साथ काम करता है.
  • अगर किसी आर्टवर्क के बारे में नहीं बताया गया है और मनमुताबिक साइज़ में कोई आइकॉन इमेज है, तो मीडिया से जुड़ी सूचनाओं में इसका इस्तेमाल किया जाएगा.
  • Android के लिए Chrome में, सूचना आर्टवर्क का साइज़ 512x512 है. कम सुविधाओं वाले डिवाइसों के लिए, यह 256x256 है.
  • audio.src = '' की मीडिया सूचनाएं खारिज करें.
  • Web Audio API, पुरानी वजहों से Android Audio Focus का अनुरोध नहीं करता. इसलिए, Media Session API के साथ यह काम करने का सिर्फ़ एक ही तरीका है कि <audio> एलिमेंट को Web Audio API के इनपुट सोर्स के तौर पर जोड़ा जाए. उम्मीद है कि सुझाए गए 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 की स्थिति पर मिल सकती है.

सैंपल और डेमो

हमारे आधिकारिक Chrome मीडिया सेशन सैंपल देखें. इनमें ब्लेंडर फ़ाउंडेशन और जैन मॉर्गनस्टर्न के काम दिखाए गए हैं.

रिसॉर्स

मीडिया सेशन स्पेसिफ़िकेशन: wicg.github.io/mediasession

खास जानकारी से जुड़ी समस्याएं: github.com/WICG/mediasession/issues

Chrome की गड़बड़ियां: crbug.com