Media Session API'si ile medya bildirimlerini ve oynatma kontrollerini özelleştirme

Donanım medya anahtarlarıyla entegrasyon, medya bildirimlerini özelleştirme ve daha fazlası.

François Beaufort
François Beaufort

Kullanıcılara tarayıcılarında o anda neyin oynatıldığını bildirmek ve onu başlatan sayfaya dönmeden kontrol etmek için Media Session API'yi kullanıma sunduk. Web geliştiricilerinin özel medya bildirimlerindeki meta veriler, oynatma, duraklatma, arama, parça değiştirme gibi medya etkinlikleri ve mikrofon sesini açma/kapatma, kamerayı açma/kapatma ve telefonu kapatma gibi video konferans etkinlikleri aracılığıyla bu deneyimi özelleştirmesine olanak tanır. Bu özelleştirmeler, masaüstü medya merkezleri, mobil cihazlardaki medya bildirimleri ve hatta giyilebilir cihazlar gibi çeşitli bağlamlarda kullanılabilir. Bu özelleştirmeleri bu makalede açıklayacağım.

Medya oturumu bağlamlarının ekran görüntüleri.
Masaüstünde medya merkezi, mobil cihazda medya bildirimi ve giyilebilir cihaz.

Media Session API hakkında

Media Session API, çeşitli avantajlar ve özellikler sunar:

  • Donanım medya anahtarları desteklenir.
  • Medya bildirimleri mobil cihazlarda, masaüstünde ve eşlenmiş giyilebilir cihazda özelleştirilmiştir.
  • Medya merkezi masaüstünde kullanılabilir.
  • Kilit ekranı medya kontrolleri ChromeOS ve mobil cihazlarda kullanılabilir.
  • Pencere içinde pencere kontrolleri, ses oynatma, video konferans ve slayt sunma için kullanılabilir.
  • Mobil cihazlarda Asistan entegrasyonu kullanılabilir.

Tarayıcı desteği

  • Chrome: 73.
  • Edge: 79.
  • Firefox: 82.
  • Safari: 15.

Kaynak

Bu noktalardan bazılarını birkaç örnekle açıklayacağız.

1. Örnek: Kullanıcılar klavyelerinin "sonraki parça" medya tuşuna basarsa web geliştiricileri, tarayıcı ön planda veya arka planda olsun bu kullanıcı işlemini işleyebilir.

2. Örnek: Kullanıcılar, cihazlarının ekranı kilitliyken web'de bir podcast dinleseler bile kilit ekranındaki medya kontrollerinde "geri sar" simgesine basabilirler. Böylece web geliştiricileri oynatma süresini birkaç saniye geri alır.

3. Örnek: Kullanıcıların ses çalan sekmeleri varsa web geliştiricilerin durumlarını temizleyebilmesi için masaüstündeki medya merkezinden oynatmayı kolayca durdurabilirler.

4. Örnek: Görüntülü görüşme yapan kullanıcılar, web sitesinin mikrofon verilerini almasını durdurmak için Pencere İçinde Pencere penceresindeki "mikrofon aç/kapat" denetimine basabilir.

Tüm bu işlemler iki farklı arayüz üzerinden yapılır: MediaSession arayüzü ve MediaMetadata arayüzü. İlki, oynatılan içeriği kontrol etmelerini sağlar. İkincisi, MediaSession adlı müşteriye neyin kontrol edilmesi gerektiğini nasıl bildireceğinizdir.

Bunu açıklamak üzere, aşağıdaki resimde bu arayüzlerin belirli medya denetimleriyle ilişkisi gösterilmektedir. Bu örnekte mobil cihazlardaki bir medya bildirimi yer almaktadır.

Medya Oturumu arayüzlerinin resmi.
Mobil cihazlarda medya bildiriminin anatomisi.

Kullanıcılara nelerin çalındığını bildirin

Bir web sitesinde ses veya video oynatıldığında kullanıcılar mobil cihazlardaki bildirim tepsisine ya da masaüstündeki medya merkezine otomatik olarak medya bildirimleri alır. Tarayıcı, belgenin başlığını ve bulabileceği en büyük simge resmini kullanarak uygun bilgileri göstermek için elinden geleni yapar. Media Session API ile medya bildirimini, aşağıda gösterildiği gibi başlık, sanatçı adı, albüm adı ve poster gibi daha zengin medya meta verileriyle özelleştirebilirsiniz.

Chrome, medya bildirimlerini yalnızca medya süresi en az 5 saniye olduğunda göstermek için "tam" ses odağı ister. Bu sayede, zil sesleri gibi arızi sesler bildirim olarak gösterilmez.

// After media (video or audio) starts playing
await document.querySelector("video").play();

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://via.placeholder.com/96',   sizes: '96x96',   type: 'image/png' },
      { src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
      { src: 'https://via.placeholder.com/192', sizes: '192x192', type: 'image/png' },
      { src: 'https://via.placeholder.com/256', sizes: '256x256', type: 'image/png' },
      { src: 'https://via.placeholder.com/384', sizes: '384x384', type: 'image/png' },
      { src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
    ]
  });

  // TODO: Update playback state.
}

Oynatma sona erdiğinde bildirim otomatik olarak kaybolacağı için medya oturumunu "bırakmanıza" gerek yoktur. Ancak bir sonraki oynatma işlemi başladığında navigator.mediaSession.metadata değerinin kullanılacağını unutmayın. Bu nedenle, medya oynatma kaynağı değiştiğinde medya bildiriminde alakalı bilgilerin gösterilmesini sağlamak için bunu güncellemek önemlidir.

Medya meta verileriyle ilgili dikkat edilmesi gereken birkaç nokta vardır.

  • Bildirim posteri dizisi, blob URL'lerini ve veri URL'lerini destekler.
  • Poster tanımlanmamışsa ve istenilen boyutta bir simge resmi (<link rel=icon> kullanılarak belirtilmiş) varsa medya bildirimleri bu resmi kullanır.
  • Android için Chrome'da bildirim posterlerinin hedef boyutu: 512x512. Düşük özellikli cihazlarda bu değer 256x256'tür.
  • Medya HTML öğesinin title özelliği, "Şimdi oynatılıyor" macOS widget'ında kullanılır.
  • Medya kaynağı yerleştirilmişse (örneğin, bir iframe'e) Media Session API bilgileri, yerleştirilmiş bağlamda ayarlanmalıdır. Aşağıdaki snippet'i inceleyin.
<iframe id="iframe">
  <video>...</video>
</iframe>
<script>
  iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
    title: 'Never Gonna Give You Up',
    ...
  });
</script>

Medya meta verilerine bölüm bilgileri (ör. bölümün başlığı, zaman damgası ve ekran görüntüsü) de ekleyebilirsiniz. Bu sayede kullanıcılar medya içeriğinde gezinebilir.

navigator.mediaSession.metadata = new MediaMetadata({
  // title, artist, album, artwork, ...
  chapterInfo: [{
    title: 'Chapter 1',
    startTime: 0,
    artwork: [
      { src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
      { src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
    ]
  }, {
    title: 'Chapter 2',
    startTime: 42,
    artwork: [
      { src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
      { src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
    ]
  }]
});
ChromeOS medya bildirimlerinde gösterilen bölüm bilgileri.
ChromeOS'teki bölümleri içeren medya bildirimi.

Kullanıcıların oynatılan içeriği kontrol etmesine izin verme

Medya oturumu işlemi, kullanıcılar mevcut medya oynatma işlemiyle etkileşime geçtiğinde web sitesinin kullanıcılar için işleyebileceği bir işlemdir (ör. "oynat" veya "duraklat"). Eylemler etkinliklere benzer ve onlarla hemen hemen aynı şekilde işler. Etkinlikler gibi işlemler de uygun bir nesneye (bu örnekte MediaSession örneği) işleyiciler ayarlanarak uygulanır. Bazı işlemler, kullanıcılar bir mikrofonlu kulaklıktaki, başka bir uzak cihazdaki veya klavyedeki düğmelere bastığında ya da bir medya bildirimiyle etkileşimde bulunduğunda tetiklenir.

Windows 10&#39;daki bir medya bildiriminin ekran görüntüsü.
Windows 10'da özelleştirilmiş medya bildirimi.

Bazı medya oturumu işlemleri desteklenmediğinden, bunları ayarlarken try…catch bloğu kullanmanız önerilir.

const actionHandlers = [
  ['play',          () => { /* ... */ }],
  ['pause',         () => { /* ... */ }],
  ['previoustrack', () => { /* ... */ }],
  ['nexttrack',     () => { /* ... */ }],
  ['stop',          () => { /* ... */ }],
  ['seekbackward',  (details) => { /* ... */ }],
  ['seekforward',   (details) => { /* ... */ }],
  ['seekto',        (details) => { /* ... */ }],
  /* Video conferencing actions */
  ['togglemicrophone', () => { /* ... */ }],
  ['togglecamera',     () => { /* ... */ }],
  ['hangup',           () => { /* ... */ }],
  /* Presenting slides actions */
  ['previousslide', () => { /* ... */ }],
  ['nextslide',     () => { /* ... */ }],
];

for (const [action, handler] of actionHandlers) {
  try {
    navigator.mediaSession.setActionHandler(action, handler);
  } catch (error) {
    console.log(`The media session action "${action}" is not supported yet.`);
  }
}

Bir medya oturumu işlem işleyicisinin ayarını kaldırmak, null olarak ayarlamak kadar kolaydır.

try {
  // Unset the "nexttrack" action handler at the end of a playlist.
  navigator.mediaSession.setActionHandler('nexttrack', null);
} catch (error) {
  console.log(`The media session action "nexttrack" is not supported yet.`);
}

Medya oturumu işlem işleyicileri, ayarlandıktan sonra medya oynatmaları boyunca kullanılabilir olmaya devam eder. Bu, etkinlik dinleyici kalıbına benzer. Bununla birlikte, bir etkinliğin işlenmesi, tarayıcının varsayılan davranışı durdurması anlamına gelir ve bunu web sitesinin medya işlemini desteklediğinin bir sinyali olarak kullanır. Bu nedenle, uygun işlem işleyici ayarlanmazsa medya işlemi kontrolleri gösterilmez.

macOS Big Sur&#39;da Ne Çalıyor? widget&#39;ının ekran görüntüsü.
macOS Big Sur'daki Şimdi Çalan widget'ı.

Oynat/duraklat

"play" işlemi, kullanıcının medya oynatmayı devam ettirmek istediğini, "pause" işlemi ise geçici olarak durdurmak istediğini belirtir.

Medya bildiriminde "oynat/duraklat" simgesi her zaman gösterilir ve ilgili medya etkinlikleri tarayıcı tarafından otomatik olarak işlenir. Varsayılan davranışlarını geçersiz kılmak için "oynatma" ve "duraklatma" medya işlemlerini aşağıda gösterildiği gibi kullanın.

Tarayıcı, örneğin bir web sitesinin, aranırken veya yüklenirken medya oynatmadığını düşünebilir. Bu durumda, web sitesi kullanıcı arayüzünün medya bildirimi kontrolleriyle senkronize kalmasını sağlamak için navigator.mediaSession.playbackState değerini "playing" veya "paused" olarak ayarlayarak bu davranışı geçersiz kılın.

const video = document.querySelector('video');

navigator.mediaSession.setActionHandler('play', async () => {
  // Resume playback
  await video.play();
});

navigator.mediaSession.setActionHandler('pause', () => {
  // Pause active playback
  video.pause();
});

video.addEventListener('play', () => {
  navigator.mediaSession.playbackState = 'playing';
});

video.addEventListener('pause', () => {
  navigator.mediaSession.playbackState = 'paused';
});

Önceki parça

"previoustrack" işlemi, medya oynatmanın başlangıcı varsa kullanıcının geçerli medya oynatmayı baştan başlatmak istediğini veya medya oynatmada bir oynatma listesi kavramı varsa oynatma listesindeki bir önceki öğeye geçmek istediğini belirtir.

navigator.mediaSession.setActionHandler('previoustrack', () => {
  // Play previous track.
});

Sonraki parça

"nexttrack" işlemi, medya oynatmada oynatma listesi kavramı varsa kullanıcının medya oynatmayı oynatma listesindeki bir sonraki öğeye taşımak istediğini belirtir.

navigator.mediaSession.setActionHandler('nexttrack', () => {
  // Play next track.
});

Durdur

"stop" işlemi, kullanıcının medya oynatmayı durdurmak ve uygunsa durumu temizlemek istediğini gösterir.

navigator.mediaSession.setActionHandler('stop', () => {
  // Stop playback and clear state if appropriate.
});

Geri/ileri sar

"seekbackward" işlemi, kullanıcının medya oynatma süresini kısa bir süre geri almak istediğini, "seekforward" ise medya oynatma süresini kısa bir süre ileri almak istediğini gösterir. Her iki durumda da kısa süre birkaç saniye anlamına gelir.

İşlem işleyicisinde sağlanan seekOffset değeri, medya oynatma süresinin saniye cinsinden ne kadar ileri taşınacağını belirtir. Bu değer sağlanmazsa (örneğin, undefined) makul bir süre (örneğin, 10-30 saniye) kullanmanız gerekir.

const video = document.querySelector('video');
const defaultSkipTime = 10; /* Time to skip in seconds by default */

navigator.mediaSession.setActionHandler('seekbackward', (details) => {
  const skipTime = details.seekOffset || defaultSkipTime;
  video.currentTime = Math.max(video.currentTime - skipTime, 0);
  // TODO: Update playback state.
});

navigator.mediaSession.setActionHandler('seekforward', (details) => {
  const skipTime = details.seekOffset || defaultSkipTime;
  video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
  // TODO: Update playback state.
});

Belirli bir zamana gitme

"seekto" işlemi, kullanıcının medya oynatma süresini belirli bir zamana taşımak istediğini belirtir.

İşlem işleyicisinde sağlanan seekTime değeri, medya oynatma süresinin taşınacağı saniye cinsinden süredir.

İşlem, bir sıranın parçası olarak birden çok kez çağrılıyorsa ve bu, söz konusu sıradaki son çağrı değilse işlem işleyicisinde sağlanan fastSeek boole değeri doğru olur.

const video = document.querySelector('video');

navigator.mediaSession.setActionHandler('seekto', (details) => {
  if (details.fastSeek && 'fastSeek' in video) {
    // Only use fast seek if supported.
    video.fastSeek(details.seekTime);
    return;
  }
  video.currentTime = details.seekTime;
  // TODO: Update playback state.
});

Oynatma konumunu ayarlama

Bir bildirimde medya oynatma konumunu doğru şekilde görüntülemek, aşağıda gösterildiği gibi uygun bir zamanda konum durumunu ayarlamak kadar basittir. Konum durumu; medya oynatma hızı, süre ve geçerli zamanın bir birleşimidir.

ChromeOS&#39;teki kilit ekranı medya denetimlerinin ekran görüntüsü.
ChromeOS'te kilit ekranı medya kontrolleri.

Süre belirtilmeli ve pozitif olmalıdır. Konum pozitif ve süreden küçük olmalıdır. Oynatma hızı 0'dan büyük olmalıdır.

const video = document.querySelector('video');

function updatePositionState() {
  if ('setPositionState' in navigator.mediaSession) {
    navigator.mediaSession.setPositionState({
      duration: video.duration,
      playbackRate: video.playbackRate,
      position: video.currentTime,
    });
  }
}

// When video starts playing, update duration.
await video.play();
updatePositionState();

// When user wants to seek backward, update position.
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
  /* ... */
  updatePositionState();
});

// When user wants to seek forward, update position.
navigator.mediaSession.setActionHandler('seekforward', (details) => {
  /* ... */
  updatePositionState();
});

// When user wants to seek to a specific time, update position.
navigator.mediaSession.setActionHandler('seekto', (details) => {
  /* ... */
  updatePositionState();
});

// When video playback rate changes, update position state.
video.addEventListener('ratechange', (event) => {
  updatePositionState();
});

Konum durumunu sıfırlamak, null olarak ayarlamak kadar kolaydır.

// Reset position state when media is reset.
navigator.mediaSession.setPositionState(null);

Video konferans işlemleri

Kullanıcı görüntülü görüşmesini Pencere İçinde Pencere penceresine yerleştirdiğinde tarayıcıda mikrofon, kamera ve görüşmeyi sonlandırma kontrolleri gösterilebilir. Kullanıcı bunları tıkladığında web sitesi bunları aşağıdaki video konferans işlemleri aracılığıyla işler. Örnek için Video Konferansı örneğine bakın.

Pencere içinde pencere penceresindeki video konferans denetimlerinin ekran görüntüsü.
Pencere içinde pencere penceresindeki video konferans kontrolleri.

Mikrofonu aç/kapat

"togglemicrophone" işlemi, kullanıcının mikrofonun sesini kapatmak veya açmak istediğini belirtir. setMicrophoneActive(isActive) yöntemi, web sitesinin şu anda mikrofonu etkin olarak görüp görmediğini tarayıcıya bildirir.

let isMicrophoneActive = false;

navigator.mediaSession.setActionHandler('togglemicrophone', () => {
  if (isMicrophoneActive) {
    // Mute the microphone.
  } else {
    // Unmute the microphone.
  }
  isMicrophoneActive = !isMicrophoneActive;
  navigator.mediaSession.setMicrophoneActive(isMicrophoneActive);
});

Kamerayı değiştir

"togglecamera" işlemi, kullanıcının etkin kamerayı açmak veya kapatmak istediğini gösterir. setCameraActive(isActive) yöntemi, tarayıcının web sitesini etkin olarak görüp görmediğini belirtir.

let isCameraActive = false;

navigator.mediaSession.setActionHandler('togglecamera', () => {
  if (isCameraActive) {
    // Disable the camera.
  } else {
    // Enable the camera.
  }
  isCameraActive = !isCameraActive;
  navigator.mediaSession.setCameraActive(isCameraActive);
});

Kapatın.

"hangup" işlemi, kullanıcının bir görüşmeyi sonlandırmak istediğini gösterir.

navigator.mediaSession.setActionHandler('hangup', () => {
  // End the call.
});

Slayt gösterme işlemleri

Kullanıcı, slayt sunumunu bir Pencere İçinde Pencere penceresine yerleştirdiğinde tarayıcı, slaytlar arasında gezinmeyle ilgili kontrolleri gösterebilir. Kullanıcı bu bağlantıları tıkladığında web sitesi, Media Session API üzerinden bu bağlantıları işler. Örnek için Slaytlar'ı sunma örneğini inceleyin.

Önceki slayt

"previousslide" işlemi, kullanıcının slaytları sunarken önceki slayta geri dönmek istediğini gösterir.

navigator.mediaSession.setActionHandler('previousslide', () => {
  // Show previous slide.
});

Tarayıcı Desteği

  • Chrome: 111.
  • Edge: 111.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

Sonraki slayt

"nextslide" işlemi, kullanıcının slaytları sunarken bir sonraki slayta gitmek istediğini gösterir.

navigator.mediaSession.setActionHandler('nextslide', () => {
  // Show next slide.
});

Tarayıcı desteği

  • Chrome: 111.
  • Edge: 111.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

Örnekler

Blender Foundation ve Jan Morgenstern'ın çalışmalarının yer aldığı bazı medya oturumu örneklerine göz atın.

Media Session API'yi gösteren bir ekran kaydı.

Kaynaklar