איך משתלבים עם מפתחות מדיה בחומרה, מתאימים אישית התראות מדיה ועוד.
כדי לאפשר למשתמשים לדעת מה מופעל כרגע בדפדפן שלהם ולשלוט בו בלי לחזור לדף שבו הוא הופעל, הוספנו את Media Session API. הוא מאפשר למפתחי אתרים להתאים אישית את החוויה הזו באמצעות מטא-נתונים בהתראות מותאמות אישית לגבי מדיה, אירועי מדיה כמו הפעלה, השהיה, דילוג, שינוי טראק ואירועים של כנסים בווידאו כמו השבתה/הפעלה של המיקרופון, הפעלה/כיבוי של המצלמה וסיום השיחה. ההתאמות האישיות האלה זמינות בכמה הקשרים, כולל מרכזי מדיה במחשב, התראות על מדיה בנייד ואפילו במכשירים לבישים. במאמר הזה אסביר על ההתאמות האישיות האלה.
מידע על Media Session API
ל-Media session API יש כמה יתרונות ויכולות:
- יש תמיכה במפתחות מדיה לחומרה.
- אפשר להתאים אישית את ההתראות על מדיה בנייד, במחשב ובמכשיר נייד משולב.
- מרכז המדיה זמין במחשב.
- אמצעי הבקרה למדיה במסך הנעילה זמינים ב-ChromeOS ובנייד.
- פקדי החלון של 'תמונה בתוך תמונה' זמינים להפעלת אודיו, לשיחות ועידה בווידאו ולהצגת שקפים.
- השילוב עם Assistant זמין בנייד.
ריכזנו כאן כמה דוגמאות שיעזרו להמחיש את הנקודות האלה.
דוגמה 1: אם משתמשים לוחצים על מקש המדיה 'טראק הבא' במקלדת, מפתחי האתר יכולים לטפל בפעולה הזו של המשתמש גם אם הדפדפן נמצא בחזית וגם אם הוא ברקע.
דוגמה 2: אם משתמשים מקשיבים לפודקאסט באינטרנט בזמן שמסך המכשיר נעול, הם עדיין יכולים ללחוץ על הסמל 'דילוג לאחור' באמצעי הבקרה של המדיה במסך הנעילה, כדי שמפתחי האתרים יוכלו להזיז את זמן ההפעלה לאחור בכמה שניות.
דוגמה 3: אם למשתמשים יש כרטיסיות עם אודיו שפועל, הם יכולים להפסיק בקלות את ההפעלה ממרכז המדיה במחשב, כדי שמפתחי האתרים יוכלו לנקות את המצב שלהם.
דוגמה 4: אם משתמשים נמצאים בשיחת וידאו, הם יכולים ללחוץ על לחצן החלפת המצב של המיקרופון בחלון התצוגה בחלון כדי למנוע מהאתר לקבל נתוני מיקרופון.
אפשר לעשות את זה דרך שני ממשקים שונים: הממשק MediaSession
והממשק MediaMetadata
. האפשרות הראשונה מאפשרת למשתמשים לשלוט במה שמופעל. השני הוא איך אומרים ל-MediaSession
מה צריך לשלוט בו.
כדי להמחיש, בתמונה הבאה אפשר לראות איך הממשקים האלה קשורים לפקדי מדיה ספציפיים, במקרה הזה התראה על מדיה בנייד.
מודיע למשתמשים מה מושמע
כשבאתר מסוים מופעל אודיו או וידאו, המשתמשים מקבלים התראות מדיה באופן אוטומטי בחלונית ההתראות בנייד או במרכז המדיה במחשב. הדפדפן עושה כמיטב יכולתו כדי להציג מידע מתאים, באמצעות שם המסמך ותמונת הסמל הגדולה ביותר שהוא יכול למצוא. באמצעות Media Session 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' },
]
}]
});
המשתמשים יכולים לשלוט בתוכן המושמע
פעולה של סשן מדיה היא פעולה (למשל, 'הפעלה' או 'השהיה') שהאתר יכול לטפל בה אצל משתמשים כשהם מקיימים אינטראקציה עם הפעלת המדיה הנוכחית. פעולות דומות לאירועים ופועלות באופן דומה. בדומה לאירועים, כדי להטמיע פעולות צריך להגדיר גורמים מטפלים באובייקט מתאים, במקרה הזה מופע של MediaSession
. חלק מהפעולות מופעלות כשמשתמשים לוחצים על לחצנים באוזניות, במכשיר מרוחק אחר, במקלדת או מבצעים אינטראקציה עם התראה על מדיה.
יכול להיות שחלק מהפעולות בסשן המדיה לא נתמכות, לכן מומלץ להשתמש בבלוק 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.`);
}
}
כדי לבטל את ההגדרה של בורר הפעולות של סשן המדיה, פשוט מגדירים אותו כ-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.`);
}
אחרי ההגדרה, בוררי הפעולות של סשן המדיה ימשיכו לפעול במהלך הפעלות המדיה. זה דומה לדפוס של מאזין האירועים, אלא שבטיפול באירוע הדפדפן מפסיק לבצע את התנהגות ברירת המחדל שלו ומשתמש בכך כאות לכך שהאתר תומך בפעולה של המדיה. לכן, פקדי הפעולה של המדיה לא יוצגו אלא אם הוגדר טיפול הפעולה המתאים.
הפעלה / השהיה
הפעולה "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
שסופק בטיפול הפעולה הוא הזמן בשניות שאליו צריך להעביר את זמן ההפעלה של המדיה.
הערך הבוליאני fastSeek
שסופק בטיפול הפעולה הוא true אם הפעולה נקראת כמה פעמים כחלק מרצף, והקריאה הזו היא לא הקריאה האחרונה ברצף.
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.
});
הגדרת מיקום ההפעלה
כדי להציג בצורה מדויקת את מיקום ההפעלה של המדיה בהתראה, פשוט מגדירים את מצב המיקום בזמן המתאים, כפי שמתואר בהמשך. מצב המיקום הוא שילוב של קצב ההפעלה של המדיה, משך הזמן והשעה הנוכחית.
משך הזמן חייב להיות חיובי. המיקום חייב להיות חיובי וקטן מהמשך הזמן. קצב ההפעלה חייב להיות גדול מ-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);
פעולות בשיחות ועידה בווידאו
כשהמשתמש מעביר את שיחת הווידאו לחלון של תמונה בתוך תמונה, יכול להיות שבדפדפן יוצגו לחצני בקרה למיקרופון ולמצלמה ולניתוק השיחה. כשהמשתמש לוחץ על המודעות, האתר מטפל בהן באמצעות הפעולות שמפורטות בהמשך לגבי שיחת ועידה בווידאו. דוגמה לכך מופיעה בדוגמה לשיחת ועידה בווידאו.
החלפת מצב מיקרופון
הפעולה "togglemicrophone"
מציינת שהמשתמש רוצה להשתיק או לבטל את ההשתקה של המיקרופון. ה-method 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.
});
פעולות של הצגת שקפים
כשהמשתמש מעביר את מצגת השקפים לחלון 'תמונה בתוך תמונה', יכול להיות שבדפדפן יוצגו אמצעי בקרה לניווט בין השקפים. כשהמשתמש לוחץ עליהם, האתר מטפל בהם דרך Media Session API. לדוגמה, ראו את הדוגמה להצגת שקפים.
השקף הקודם
הפעולה "previousslide"
מציינת שהמשתמש רוצה לחזור לשקף הקודם במהלך הצגת שקפים.
navigator.mediaSession.setActionHandler('previousslide', () => {
// Show previous slide.
});
תמיכה בדפדפנים
השקף הבא
הפעולה "nextslide"
מציינת שהמשתמש רוצה לעבור לשקף הבא במהלך הצגת שקפים.
navigator.mediaSession.setActionHandler('nextslide', () => {
// Show next slide.
});
תמיכה בדפדפנים
דוגמאות
כדאי לעיין בדוגמאות ל-Media Session שכוללות את Blender Foundation והעבודה של Jan Morgenstern.
משאבים
- מפרט Media Session: wicg.github.io/mediasession
- בעיות במפרט: github.com/WICG/mediasession/issues
- באגים ב-Chrome: crbug.com