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

Donanım medya tuşlarıyla entegrasyon, medya bildirimlerini özelleştirme ve daha pek çok konuda daha fazla yöntem.

François Beaufort
François Beaufort

Kullanıcıların tarayıcılarında o anda neyin oynatıldığını bilmelerini sağlamak ve tarayıcıyı başlatan sayfaya dönmeden kontrol etmelerini sağlamak için Media Session API'si kullanıma sunuldu. Web geliştiricilerinin bu deneyimi; özel medya bildirimlerindeki meta veriler, oynatma, duraklatma, arama, değiştirme gibi medya etkinlikleri ve mikrofonun sesini kapatma/açma, kamerayı açma/kapatma ve telefonu kapatma gibi video konferans etkinlikleri aracılığıyla özelleştirmelerine olanak tanır. Bu özelleştirmeler; masaüstü medya merkezleri, mobil cihazlardaki ve hatta giyilebilir cihazlardaki medya bildirimleri dahil olmak üzere çeşitli bağlamlarda kullanılabilir. Söz konusu özelleştirmeleri bu makalede açıklayacağım.

Medya Oturumu bağlamlarının ekran görüntüleri.
Masaüstünde Medya Merkezi, mobilde medya bildirimi ve giyilebilir bir cihaz.

Media Session API'si hakkında

Medya oturumu API'sı çeşitli avantajlar ve olanaklar sunar:

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

Tarayıcı Desteği

  • 73
  • 79
  • 82
  • 15

Kaynak

Bu noktaların bazıları birkaç örnekle gösterilmiştir.

1. Örnek: Kullanıcılar klavyelerinin "sonraki parça" medya tuşuna basarsa web geliştiricileri, tarayıcının ön planda veya arka planda olmasına bakılmaksızın bu kullanıcı işlemini gerçekleştirebilir.

2. Örnek: Kullanıcılar cihaz ekranları kilitliyken web'de bir podcast dinlerlerse de kilit ekranı medya denetimlerindeki "geriye git" simgesine basarak web geliştiricilerinin oynatma süresini birkaç saniye geriye taşıyabilirler.

3. Örnek: Kullanıcıların ses çalan sekmeleri varsa masaüstündeki medya merkezinden oynatmayı kolayca durdurabilirler. Böylece web geliştiricilerinin durumlarını temizleme şansı olur.

4. Örnek: Kullanıcılar bir video görüşmesindeyse, web sitesinin mikrofon verilerini almasını durdurmak için Pencere İçinde Pencere penceresinde "mikrofonu aç/kapat" denetimine basabilir.

Bu işlemlerin tümü iki farklı arayüz üzerinden yapılır: MediaSession arayüzü ve MediaMetadata arayüzü. Birincisi, kullanıcıların oynatılan içeriği kontrol etmelerine olanak tanır. İkincisi, MediaSession hizmetine nelerin kontrol edilmesi gerektiğini nasıl bildirdiğinizdir.

Örnek olarak, aşağıdaki resimde bu arayüzlerin belirli medya kontrolleriyle (bu örnekte, mobil ortamdaki bir medya bildirimi) ilişkisi gösterilmektedir.

Medya Oturumu arayüzlerinin resmi.
Mobil cihazda bir medya bildiriminin anatomisi.

Kullanıcılara oynatılan içeriği bildirin

Bir web sitesinde ses veya video oynatıldığında, kullanıcılar mobil cihazlardaki bildirim tepsisinde veya masaüstünde medya merkezinde otomatik olarak medya bildirimleri alır. Tarayıcı, dokümanın başlığını ve bulunabileceği en büyük simge resmini kullanarak uygun bilgileri göstermek için elinden geleni yapar. Medya Oturumu API'sı ile medya bildirimini aşağıda gösterildiği gibi başlık, sanatçı adı, albüm adı ve poster gibi bazı zengin medya meta verileriyle özelleştirebilirsiniz.

Chrome, yalnızca medya süresi en az 5 saniye olduğunda medya bildirimlerini göstermek için "tam" ses odağını ister. Bu sayede, çınlama gibi arızi seslerin bildirimlerin gösterilmemesi sağlanır.

// 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. Yine de bir sonraki oynatma başladığında navigator.mediaSession.metadata öğesinin kullanılacağını unutmayın. Bu nedenle, medya bildiriminde alakalı bilgilerin gösterildiğinden emin olmak için medya oynatma kaynağı değiştiğinde bu ayarı güncellemek önemlidir.

Medya meta verileri ile ilgili göz önünde bulundurulması gereken birkaç nokta vardır.

  • Bildirim posteri dizisi, blob URL'lerini ve veri URL'lerini destekler.
  • Hiç poster tanımlanmamışsa ve istediğiniz boyutta bir simge resmi (<link rel=icon> ile belirtilir) varsa medya bildirimleri bunu kullanır.
  • Android için Chrome'da bildirim çiziminin hedef boyutu: 512x512. Düşük teknolojili cihazlar için bu fiyat 256x256.
  • Media HTML öğesinin title özelliği, macOS "Şimdi oynatılıyor" widget'ında kullanılır.
  • Medya kaynağı yerleştirilmişse (örneğin bir iframe içine) Media Session API bilgileri yerleştirilmiş bağlamdan 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ün başlığı, zaman damgası ve ekran görüntüsü resmi gibi bölüm bilgilerini tek tek ekleyebilirsiniz. Bu, kullanıcıların medya içeriğinde gezinmesine olanak tanır.

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 bildiriminde gösterilen bölüm bilgileri.
ChromeOS'te bölümler içeren medya bildirimi.

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

Medya oturumu işlemi, bir web sitesinin mevcut medya oynatmayla etkileşimde bulunduğunda kullanıcılar için gerçekleştirebileceği bir işlemdir (örneğin "oynat" veya "duraklat"). Eylemler olaylara benzer ve onlarla hemen hemen aynı şekilde işler. Etkinliklerde olduğu gibi, işlemler de uygun bir nesne (bu örnekte MediaSession örneği) üzerinde işleyiciler ayarlanarak uygulanır. Kullanıcılar mikrofonlu kulaklık, başka bir uzak cihaz veya klavyedeki düğmelere bastığında ya da bir medya bildirimiyle etkileşimde bulunduğunda bazı işlemler 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 bir try…catch engellemesi 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.`);
  }
}

Medya oturumu işlem işleyicisini 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.`);
}

Ayarlandıktan sonra medya oturumu işlem işleyicileri, medya oynatmaları boyunca devam eder. Bu, etkinlik işleyici kalıbına benzerdir. Tek fark, bir etkinliğin işlenmesinin, tarayıcının herhangi bir varsayılan davranışı yapmayı bırakması ve bunu, web sitesinin medya işlemini desteklediğine dair bir sinyal olarak kullanması anlamına gelir. Bu nedenle, uygun işlem işleyici ayarlanmadığı sürece medya işlemi kontrolleri gösterilmez.

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

Oynatma / duraklatma

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

"Oynat/duraklat" simgesi her zaman medya bildiriminde 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 "oynat" ve "duraklat" medya işlemlerini aşağıda gösterildiği gibi gerçekleştirin.

Örneğin, tarayıcı, arama yaparken veya yüklerken bir web sitesinin 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ıç kavramı varsa kullanıcının geçerli medya oynatmayı baştan başlatmak veya medya oynatmada oynatma listesi fikri 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 bir oynatma listesi fikri 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 belirtir.

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üreliğine geriye taşımak istediğini gösterir. "seekforward" ise medya oynatma süresini kısa bir süre ileriye taşımak istediğini gösterir. Kısa dönem her iki durumda da birkaç saniye anlamına gelir.

İşlem işleyicide sağlanan seekOffset değeri, medya oynatma süresinin saniye cinsinden aktarılacağı süredir. Belirtilmemişse (örneğin, undefined) makul bir süre kullanmalısınız (örneğin 10-30 saniye).

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 git

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

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

İşlem, bir dizinin 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şleyicide sağlanan fastSeek boole'si doğrudur.

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 ayarla

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

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

Süre sağlanmalı 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ı, video görüşmesini Pencere İçinde Pencere penceresine yerleştirdiğinde tarayıcı, mikrofon, kamera ve görüşmeyi sonlandırma denetimlerini görüntüleyebilir. Kullanıcı bu tıklamaları tıkladığında web sitesi bunları aşağıdaki video konferans işlemleri aracılığıyla işler. Örnek için Video Konferans örneğini inceleyin.

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

Mikrofonu aç/kapat

"togglemicrophone" işlemi, kullanıcının mikrofonun sesini kapatmak veya açmak istediğini gösterir. setMicrophoneActive(isActive) yöntemi, tarayıcıya, web sitesinin mikrofonun etkin olduğunu düşünüp algılamadığını bildirir.

let isMicrophoneActive = false;

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

Kameralar arasında geçiş yap

"togglecamera" işlemi, kullanıcının etkin kamerayı açmak veya kapatmak istediğini belirtir. setCameraActive(isActive) yöntemi, tarayıcının web sitesini etkin olarak kabul edip etmediğini belirtir.

let isCameraActive = false;

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

Görüşmeyi bitir

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

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

Slaytlarla sunulan işlemler

Kullanıcı, slayt sunularını Pencere İçinde Pencere penceresine yerleştirdiğinde, tarayıcı, slaytlar arasında gezinmeye ilişkin denetimleri görüntüleyebilir. Kullanıcılar bu tıklamaları tıkladığında web sitesi bunları Media Session API üzerinden işler. Örnek için Slaytlar'ı gösterme örneğini inceleyin.

Önceki slayt

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

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

Tarayıcı Desteği

  • 111
  • 111
  • x
  • x

Sonraki slayt

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

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

Tarayıcı Desteği

  • 111
  • 111
  • x
  • x

Numuneler

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 ekran video kaydı.

Kaynaklar