בעזרת ה-Media Session API, אפשר להתאים אישית את ההתראות של המדיה ואת פקדי ההפעלה

איך לשלב את המכשירים עם מפתחות מדיה פיזיים, להתאים אישית התראות על מדיה ועוד.

François Beaufort
François Beaufort

כדי לאפשר למשתמשים לדעת מה מופעל בדפדפן שלהם ולשלוט בו מבלי לחזור לדף שהפעיל אותו, ה-Media Session API חדשה. הוא מאפשר למפתחי אתרים להתאים אישית את החוויה מטא-נתונים בהתראות מותאמות אישית בנוגע למדיה, באירועי מדיה כמו הפעלה, השהיה דילוג, מעקב אחר אירועים ושיחות ועידה בווידאו כמו השתקה/ביטול השתקה את המיקרופון, להפעיל או לכבות את המצלמה ולנתק. התאמות אישיות כאלה זמינה בכמה הקשרים, כולל מרכזי מדיה בשולחן העבודה, התראות על מדיה במכשירים ניידים, ואפילו במכשירים לבישים. אני אתאר את ההתאמות האישיות האלה במאמר הזה.

צילומי מסך של ההקשרים של סשנים במדיה.
מרכז המדיה במחשב, התראות מדיה בנייד ומכשיר לביש.

מידע על Media Session API

ל-Media session API יש כמה יתרונות ויכולות:

תמיכה בדפדפן

  • Chrome: 73.
  • קצה: 79.
  • Firefox: 82.
  • Safari: 15.

מקור

הנה כמה דוגמאות שממחישות חלק מהנקודות האלה.

דוגמה 1: אם משתמשים לוחצים על 'הטראק הבא' מקש המדיה במקלדת, מפתחי אתרים יכולים לטפל בפעולת המשתמש הזו גם אם הדפדפן פועל בחזית או ברקע.

דוגמה 2: אם המשתמשים מאזינים לפודקאסט באינטרנט תוך כדי המכשיר כשהמסך נעול, הוא עדיין יכול ללחוץ על "דילוג אחורה" סמל מהמנעול בקרי מדיה במסך, כדי שמפתחי אתרים יזיזו את זמן ההפעלה בכמה שניות אחורה שניות.

דוגמה 3: אם למשתמשים מוצגים כרטיסיות שמפעילות אודיו, הם יכולים להפסיק את זה בקלות ממרכז המדיה במחשב, כדי שלמפתחי אתרים תהיה הזדמנות לנקות את המצב שלהם.

דוגמה 4: אם המשתמשים בשיחת וידאו, הם יכולים ללחוץ על המתג מיקרופון" לשלוט בחלון 'תמונה בתוך תמונה' כדי להפסיק את הפעלת האתר מקבל נתוני מיקרופון.

כל זה מתבצע דרך שני ממשקים שונים: הממשק של MediaSession וגם בממשק MediaMetadata. השיטה הראשונה מאפשרת למשתמשים לשלוט מתבצעת הפעלה. השיטה השנייה היא שמסבירה ל-MediaSession במה צריך לשלוט.

כדי להמחיש, התמונה הבאה מציגה את הקשרים של הממשקים האלה עם בקרי מדיה, במקרה הזה התראה על מדיה בנייד.

איור של ממשקים של סשן מדיה.
המבנה של התראה במדיה בנייד

כדאי לאפשר למשתמשים לדעת מה מושמע

כשאתר מפעיל אודיו או וידאו, המשתמשים מקבלים מדיה באופן אוטומטי במגש ההתראות בנייד או במרכז המדיה שולחן עבודה. הדפדפן עושה כמיטב יכולתו להציג את המידע המתאים באמצעות כותרת המסמך ותמונת הסמל הגדולה ביותר שהיא יכולה למצוא. עם סשן המדיה ממשק API, ניתן להתאים אישית את ההודעה במדיה עם מדיה עשירה יותר מטא-נתונים כמו השם, שם האומן, שם האלבום וגרפיקה כפי שמוצג בהמשך.

Chrome מבקש "מלא" מיקוד אודיו כדי להציג התראות מדיה רק כאשר משך המדיה הוא 5 שניות לפחות. כך ניתן לוודא שצלילים מקריים כמו צלצולים, לא יציגו התראות.

// 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.
}

כאשר ההפעלה מסתיימת, לא צריך "לשחרר" את הסרטון את סשן המדיה בתור ההתראה תיעלם באופן אוטומטי. חשוב לזכור כשההפעלה הבאה תתחיל, הסמל navigator.mediaSession.metadata יהיה בשימוש אבל. לכן חשוב לעדכן אותו כשמקור ההפעלה של המדיה כדי לוודא שמידע רלוונטי יוצג בהודעה בנוגע למדיה.

יש כמה נקודות חשובות לגבי המטא-נתונים של המדיה.

  • מערך הגרפיקה של ההתראות תומך בכתובות URL של blob ובכתובות URL של נתונים.
  • אם לא הוגדרה גרפיקה ומוצגת תמונת סמל (שצוין באמצעות <link rel=icon>) בגודל רצוי, התראות על מדיה ישתמשו בה.
  • גודל היעד של הגרפיקה של ההתראות ב-Chrome ל-Android הוא 512x512. עבור במכשירים פשוטים, זה 256x256.
  • המאפיין title של רכיב ה-HTML של המדיה נמצא בשימוש בפעולה "הפעלה עכשיו" הווידג'ט של macOS.
  • אם משאב המדיה מוטמע (למשל ב-iframe), Media Session API צריך להגדיר את המידע מההקשר המוטמע. מידע נוסף מופיע בקטע הקוד שבהמשך.
<iframe id="iframe">
  <video>...</video>
</iframe>
<script>
  iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
    title: 'Never Gonna Give You Up',
    ...
  });
</script>

אתם יכולים להוסיף גם פרטים על כל פרק, כמו שם הקטע, חותמת הזמן שלו וצילום מסך למטא-נתונים של המדיה. כך המשתמשים יכולים לנווט בתוכן של המדיה.

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.
התראה על מדיה שכוללת פרקים ב-ChromeOS.

המשתמשים יכולים לשלוט בתוכן המושמע

פעולה במדיה היא פעולה (למשל, 'הפעלה' או 'השהיה') שהאתר יכול נקודת אחיזה למשתמשים כאשר הם מקיימים אינטראקציה עם הפעלת המדיה הנוכחית. הפעולות הן מקבילים לאירועים ועובדים בדיוק כמו אירועים. בדומה לאירועים, הפעולות הן שמוטמעת באמצעות הגדרת handlers לאובייקט מתאים, מופע של MediaSession, במקרה הזה. חלק מהפעולות מופעלות כשמשתמשים לוחצים על מאוזניות, ממכשיר מרוחק אחר או ממקלדת, או לבצע אינטראקציה התראה במדיה.

צילום מסך של הודעה במדיה ב-Windows 10.
התראות מדיה מותאמות אישית ב-Windows 10

מאחר שיכול להיות שלא תהיה תמיכה בפעולות מסוימות של סשן מדיה, מומלץ: להשתמש בבלוק try…catch כשמגדירים אותם.

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.`);
  }
}

כדי לבטל את ההגדרה של handler של פעולות בסשן מדיה אפשר פשוט להגדיר אותו לערך null.

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.`);
}

לאחר ההגדרה, רכיבי ה-handler של פעולות בסשן מדיה יישמרו בהפעלות מדיה. הוא דומה לדפוס של האזנה לאירועים, מלבד הטיפול באירוע כלומר הדפדפן מפסיק לבצע פעולות ברירת מחדל ומשתמש בה לסמן שהאתר תומך בפעולת המדיה. כלומר, אמצעי הבקרה לפעולות במדיה לא תוצג אלא אם יוגדר ה-handler המתאים של הפעולות.

צילום מסך של הווידג&#39;ט &#39;מה שומעים עכשיו?&#39; ב-macOS Big Sur.
הווידג'ט 'מה שומעים עכשיו?' של 'מה שומעים עכשיו?' ב-macOS Big Sur.

הפעלה / השהיה

הפעולה "play" מציינת שהמשתמש רוצה להמשיך את הפעלת המדיה ואילו "pause" מציין רצון להפסיק באופן זמני.

האפשרות 'הפעלה/השהיה' מוצג תמיד בהתראה של מדיה, אירועי מדיה מנוהלים באופן אוטומטי על ידי הדפדפן. כדי לשנות את ברירת המחדל התנהגות, טיפול ב-"play" ו-"pause" [השהיה] פעולות במדיה כפי שמוצג בהמשך.

הדפדפן עשוי לחשוב שאתר לא מפעיל מדיה בעת ביצוע חיפוש או טעינה, למשל. במקרה כזה, משנים את ההתנהגות באמצעות הגדרת navigator.mediaSession.playbackState אל "playing" או "paused" כדי לוודא ממשק המשתמש של האתר מסונכרן עם פקדי ההתראות של המדיה.

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

הטראק הקודם

הפעולה "previoustrack" מציינת שהמשתמש רוצה להפעיל את של הפעלת מדיה נוכחית מההתחלה, אם הפעלת המדיה התחלה, או מעבר לפריט הקודם בפלייליסט, אם הפעלת מדיה מוגדר כפלייליסט.

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

הטראק הבא

הפעולה "nexttrack" מציינת שהמשתמש רוצה להעביר את הפעלת המדיה אל את הפריט הבא בפלייליסט, אם הפעלת המדיה מתייחסת לפלייליסט.

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

עצירה

הפעולה "stop" מציינת שהמשתמש רוצה להפסיק את הפעלת המדיה ו מנקים את המצב, אם יש בכך צורך.

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

הרצה אחורה / קדימה

הפעולה "seekbackward" מציינת שהמשתמש רוצה להעביר את המדיה זמן ההפעלה אחורה לפרק זמן קצר, ו-"seekforward" מציין רצון כדי להזיז את זמן ההפעלה של המדיה קדימה בפרק זמן קצר. בשני המקרים, משך זמן קצר הוא מספר שניות.

הערך seekOffset שצוין ב-handler של הפעולות הוא הזמן בשניות עד להזיז את זמן ההפעלה של המדיה לפי. אם הוא לא צוין (לדוגמה undefined), צריך להשתמש בפרק זמן סביר (למשל, 10 עד 30 שניות).

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

דילוג למועד ספציפי

הפעולה "seekto" מציינת שהמשתמש רוצה להזיז את הפעלת המדיה בזמן מסוים.

הערך seekTime שצוין ב-handler של הפעולות הוא הזמן בשניות עד מזיזים את זמן ההפעלה של המדיה.

הערך הבוליאני fastSeek שצוין ב-handler של הפעולה מתקיים אם הפעולה מופעלת מספר פעמים כחלק מרצף, וזו לא הקריאה האחרונה ברצף הזה.

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

בחירת מיקום להפעלה

הצגה מדויקת של מיקום ההפעלה של המדיה בהתראה כהגדרת מצב המיקום בזמן המתאים, כפי שמוצג בהמשך. מצב המיקום הוא שילוב של קצב ההפעלה של המדיה, משך ההפעלה השעה הנוכחית.

צילום מסך של פקדי המדיה במסך הנעילה ב-ChromeOS.
פקדי מדיה במסך הנעילה ב-ChromeOS.

יש לציין משך זמן חיובי. המיקום חייב להיות חיובי פחות ממשך הזמן. קצב ההפעלה חייב להיות גדול מ-0.

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

האיפוס של מצב המיקום מתבצע בקלות וניתן להגדיר אותו ל-null.

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

פעולות בשיחות ועידה בווידאו

כשהמשתמש מכניס את שיחת הווידאו שלו לחלון עם תמונה בתוך תמונה, הדפדפן עשוי להציג פקדים למיקרופון, למצלמה ולניתוק. כשהמשתמש לוחץ על המודעות, האתר מטפל בהן דרך הסרטון. הפעולות שמפורטות בהמשך בשיחת ועידה. לדוגמה, ראו דוגמה של שיחת ועידה בווידאו.

צילום מסך של הפקדים לשיחות ועידה בווידאו בחלון &#39;תמונה בתוך תמונה&#39;.
הפקדים של שיחות ועידה בווידאו בחלון 'תמונה בתוך תמונה'

החלפת המצב של המיקרופון

הפעולה "togglemicrophone" מציינת שהמשתמש רוצה להשתיק או לבטל את ההשתקה את המיקרופון. השיטה setMicrophoneActive(isActive) מנחה את הדפדפן אם האתר מתייחס כרגע למיקרופון כפעיל.

let isMicrophoneActive = false;

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

שנה מצב מצלמה

הפעולה "togglecamera" מציינת שהמשתמש רוצה להפעיל את להפעיל או לכבות את המצלמה. השיטה setCameraActive(isActive) מציינת אם מתייחס לאתר כפעיל.

let isCameraActive = false;

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

ניתוק

הפעולה "hangup" מציינת שהמשתמש רוצה לסיים שיחה.

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

הצגת פעולות בשקפים

כשהמשתמשים מעבירים את מצגת השקפים לחלון עם 'תמונה בתוך תמונה', הדפדפן עשוי להציג פקדים לניווט בין שקפים. כשהמשתמש לוחץ עליהן, האתר מטפל בהם דרך ממשק ה-API של סשן במדיה. עבור ראו הצגת דוגמה ל-Slides.

השקף הקודם

הפעולה "previousslide" מציינת שהמשתמש רוצה לחזור אל לשקף הקודם כשמציגים שקפים.

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

תמיכה בדפדפן

  • Chrome: 111.
  • קצה: 111.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

השקף הבא

הפעולה "nextslide" מציינת שהמשתמש רוצה לעבור לשקף הבא כשמציגים שקפים.

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

תמיכה בדפדפן

  • Chrome: 111.
  • קצה: 111.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

דוגמאות

צפו בכמה דוגמאות לסשן מדיה עם Blender Foundation וגם היצירה של יאן מורגנסטרן.

הקלטת מסך שממחישה את Media Session API.

משאבים