মিডিয়া বিজ্ঞপ্তিগুলি কাস্টমাইজ করুন এবং প্লেলিস্টগুলি পরিচালনা করুন৷

ফ্রাঁসোয়া বিউফোর্ট
François Beaufort

একেবারে নতুন মিডিয়া সেশন API এর সাথে, আপনি এখন আপনার ওয়েব অ্যাপ যে মিডিয়াটি চালাচ্ছে তার জন্য মেটাডেটা প্রদান করে মিডিয়া বিজ্ঞপ্তিগুলি কাস্টমাইজ করতে পারেন৷ এটি আপনাকে মিডিয়া সম্পর্কিত ইভেন্টগুলি যেমন চাওয়া বা ট্র্যাক পরিবর্তন করার অনুমতি দেয় যা বিজ্ঞপ্তি বা মিডিয়া কী থেকে আসতে পারে। উত্তেজিত? অফিসিয়াল মিডিয়া সেশনের নমুনাগুলি ব্যবহার করে দেখুন।

মিডিয়া সেশন API Chrome 57-এ সমর্থিত (ফেব্রুয়ারি 2017-এ বিটা, মার্চ 2017-এ স্থিতিশীল)।

মিডিয়া সেশন TL;DR;
মাইকেল আল-নিলসেন / CC BY 2.0 এর ছবি

আমি যা চাই তা দাও

আপনি ইতিমধ্যে মিডিয়া সেশন 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) });
});

বিজ্ঞপ্তি কাস্টমাইজ করুন

যখন আপনার ওয়েব অ্যাপ অডিও চালাচ্ছে, আপনি ইতিমধ্যেই বিজ্ঞপ্তি ট্রেতে বসে একটি মিডিয়া বিজ্ঞপ্তি দেখতে পাবেন। অ্যান্ড্রয়েডে, দস্তাবেজের শিরোনাম এবং এটি খুঁজে পেতে পারে এমন বৃহত্তম আইকন চিত্র ব্যবহার করে উপযুক্ত তথ্য দেখানোর জন্য Chrome তার যথাসাধ্য চেষ্টা করে৷

মিডিয়া সেশন ছাড়া
মিডিয়া সেশন ছাড়া
মিডিয়া সেশনের সাথে
মিডিয়া সেশনের সাথে

মেটাডেটা সেট করুন

মিডিয়া সেশন API এর সাথে শিরোনাম, শিল্পী, অ্যালবামের নাম এবং আর্টওয়ার্কের মতো কিছু মিডিয়া সেশন মেটাডেটা সেট করে এই মিডিয়া বিজ্ঞপ্তিটি কীভাবে কাস্টমাইজ করা যায় তা দেখা যাক।

// 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 এ বরাদ্দ করার মতোই সহজ।

পিছনের দিকে চাও

আপনি যদি এড়িয়ে যাওয়া সময়ের পরিমাণ নিয়ন্ত্রণ করতে চান তাহলে মিডিয়া সেশন 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...
});

সর্বত্র বিজ্ঞপ্তি

মিডিয়া সেশন API সম্পর্কে দুর্দান্ত জিনিস হল যে বিজ্ঞপ্তি ট্রেই একমাত্র জায়গা নয় যেখানে মিডিয়া মেটাডেটা এবং নিয়ন্ত্রণগুলি দৃশ্যমান। মিডিয়া বিজ্ঞপ্তি স্বয়ংক্রিয়ভাবে যেকোনো জোড়া পরিধানযোগ্য ডিভাইসে সিঙ্ক হয়। এবং এটি লক স্ক্রিনেও দেখায়।

বন্ধ পর্দা
লক স্ক্রিন - মাইকেল আল-নিলসেন / সিসি বাই ২.০ এর ছবি
পরিধান বিজ্ঞপ্তি
পরিধান বিজ্ঞপ্তি

এটা সুন্দর অফলাইনে খেলা করুন

আমি জানি আপনি এখন কি ভাবছেন। উদ্ধারে সেবা কর্মী !

সত্য কিন্তু প্রথম এবং সর্বাগ্রে, আপনি নিশ্চিত করতে চান যে এই চেকলিস্টের সমস্ত আইটেম চেক করা হয়েছে :

  • সমস্ত মিডিয়া এবং আর্টওয়ার্ক ফাইল উপযুক্ত Cache-Control HTTP হেডারের সাথে পরিবেশন করা হয়। এটি ব্রাউজারটিকে পূর্বে আনা সংস্থানগুলি ক্যাশে এবং পুনরায় ব্যবহার করার অনুমতি দেবে৷ ক্যাশিং চেকলিস্ট দেখুন।
  • নিশ্চিত করুন যে সমস্ত মিডিয়া এবং আর্টওয়ার্ক ফাইল Allow-Control-Allow-Origin: * HTTP হেডার দিয়ে পরিবেশন করা হয়েছে। এটি তৃতীয় পক্ষের ওয়েব অ্যাপ্লিকেশনগুলিকে আপনার ওয়েব সার্ভার থেকে HTTP প্রতিক্রিয়াগুলি আনতে এবং ব্যবহার করার অনুমতি দেবে৷

সেবা কর্মী ক্যাশিং কৌশল

মিডিয়া ফাইলগুলির বিষয়ে, আমি একটি সাধারণ " ক্যাশে, নেটওয়ার্কে ফিরে আসা " কৌশলটি সুপারিশ করছি যেমনটি জেক আর্চিবল্ড দ্বারা চিত্রিত হয়েছে।

যদিও আর্টওয়ার্কের জন্য, আমি একটু বেশি নির্দিষ্ট হতে চাই এবং নীচের পদ্ধতিটি বেছে নেব:

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

ব্যবহারকারীকে ক্যাশে নিয়ন্ত্রণ করতে দিন

যেহেতু ব্যবহারকারী আপনার ওয়েব অ্যাপ থেকে সামগ্রী ব্যবহার করে, মিডিয়া এবং আর্টওয়ার্ক ফাইলগুলি তাদের ডিভাইসে অনেক জায়গা নিতে পারে৷ কতটা ক্যাশে ব্যবহার করা হয়েছে তা দেখানো এবং ব্যবহারকারীদের তা সাফ করার ক্ষমতা দেওয়া আপনার দায়িত্ব ৷ আমাদের জন্য ধন্যবাদ, ক্যাশে 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 শুধুমাত্র তখনই মিডিয়া বিজ্ঞপ্তিগুলি দেখানোর জন্য "সম্পূর্ণ" অডিও ফোকাসের অনুরোধ করে যখন মিডিয়া ফাইলের সময়কাল কমপক্ষে 5 সেকেন্ড হয়৷
  • বিজ্ঞপ্তি আর্টওয়ার্ক ব্লব ইউআরএল এবং ডেটা ইউআরএল সমর্থন করে।
  • যদি কোন আর্টওয়ার্ক সংজ্ঞায়িত করা না থাকে এবং একটি পছন্দসই আকারে একটি আইকন চিত্র থাকে, মিডিয়া বিজ্ঞপ্তিগুলি এটি ব্যবহার করবে৷
  • Android এর জন্য Chrome-এ বিজ্ঞপ্তি আর্টওয়ার্কের আকার 512x512লো-এন্ড ডিভাইসের জন্য, এটি 256x256
  • audio.src = '' দিয়ে মিডিয়া বিজ্ঞপ্তি খারিজ করুন।
  • যেহেতু ওয়েব অডিও এপিআই ঐতিহাসিক কারণে অ্যান্ড্রয়েড অডিও ফোকাসের জন্য অনুরোধ করে না, তাই মিডিয়া সেশন এপিআই-এর সাথে এটি কাজ করার একমাত্র উপায় হল ওয়েব অডিও এপিআই-এ ইনপুট উত্স হিসাবে একটি <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 হল একমাত্র প্ল্যাটফর্ম যা মিডিয়া সেশন API সমর্থন করে। ব্রাউজার বাস্তবায়ন স্থিতি সম্পর্কে আরও আপ-টু-ডেট তথ্য Chrome প্ল্যাটফর্ম স্ট্যাটাসে পাওয়া যাবে।

নমুনা এবং ডেমো

ব্লেন্ডার ফাউন্ডেশন এবং জ্যান মরজেনস্টারের কাজ সমন্বিত আমাদের অফিসিয়াল ক্রোম মিডিয়া সেশনের নমুনাগুলি দেখুন৷

সম্পদ

মিডিয়া সেশন স্পেসিক: wicg.github.io/mediasession

বিশেষ সমস্যা: github.com/WICG/mediasession/issues

ক্রোম বাগ: crbug.com