كيفية الدمج مع مفاتيح وسائط الأجهزة وتخصيص إشعارات الوسائط وغير ذلك
تم طرح واجهة برمجة التطبيقات Media Session API لإعلام المستخدمين بالمحتوى الذي يتم تشغيله حاليًا في المتصفّح والتحكّم فيه بدون الرجوع إلى الصفحة التي تم تشغيله منها. ويسمح هذا المعيار لمطوّري الويب بتخصيص هذه التجربة من خلال البيانات الوصفية في إشعارات الوسائط المخصّصة وأحداث الوسائط، مثل التشغيل والإيقاف المؤقت والتقديم والترجيع وتغيير المقطع الصوتي، وأحداث مؤتمرات الفيديو، مثل كتم/إلغاء كتم الميكروفون وتفعيل/إيقاف الكاميرا وإغلاق المكالمة. تتوفّر هذه التخصيصات في عدة سياقات، بما في ذلك مراكز الوسائط على أجهزة الكمبيوتر المكتبي وإشعارات الوسائط على الأجهزة الجوّالة وحتى على الأجهزة القابلة للارتداء. سأوضّح هذه التخصيصات في هذه المقالة.
لمحة عن Media Session API
توفّر واجهة برمجة التطبيقات لجلسات الوسائط العديد من المزايا والإمكانات:
- تتوفّر مفاتيح الوسائط على الجهاز.
- يتم تخصيص إشعارات الوسائط على الأجهزة الجوّالة وأجهزة الكمبيوتر المكتبي والأجهزة القابلة للارتداء المقترنة.
- يتوفّر مركز الوسائط على أجهزة الكمبيوتر المكتبي.
- تتوفّر عناصر التحكّم في الوسائط على شاشة القفل على أجهزة ChromeOS والأجهزة الجوّالة.
- تتوفّر عناصر التحكّم في نافذة "صورة في صورة" لتشغيل الصوت، اجتماعات الفيديو، وعرض الشرائح.
- وتتوفّر إمكانية الدمج مع "مساعد Google" على الأجهزة الجوّالة.
سنوضّح بعض هذه النقاط من خلال بعض الأمثلة.
المثال 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 للكائنات الثنائية الكبيرة وعناوين 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
. يتم تنفيذ بعض الإجراءات عندما يضغط المستخدمون على buttons من سماعة رأس أو جهاز تحكّم عن بُعد آخر أو لوحة مفاتيح أو يتفاعلون مع إعلام إعلامات الوسائط.
وبما أنّ بعض إجراءات جلسات الوسائط قد تكون غير متاحة، ننصح باستخدام حظر 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
المقدّمة في معالِج الإجراء هي الوقت بالثواني الذي يتم فيه تحريك وقت تشغيل الوسائط. في حال عدم توفيرها (مثل 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
المقدَّمة في معالِج الإجراءات صحيحة إذا كان يتم استدعاء الإجراء
مرارًا كجزء من تسلسل ولم يكن هذا هو الطلب الأخير
في هذا التسلسل.
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"
إلى أنّ المستخدم يريد كتم صوت الميكروفون أو إعادته.
تُعلم الطريقة 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.
});
إجراءات مشاركة العروض التقديمية
عندما يضع المستخدم عرض الشرائح في نافذة "صورة في صورة"، قد يعرض المتصفّح عناصر تحكّم للتنقّل بين الشرائح. عندما ينقر المستخدم على تلك الروابط، يعالجها الموقع الإلكتروني من خلال واجهة برمجة تطبيقات جلسة الوسائط. للحصول على مثال، يُرجى الاطّلاع على نموذج عرض العروض التقديمية.
الشريحة السابقة
يشير الإجراء "previousslide"
إلى أنّ المستخدم يريد الرجوع إلى الслайд
السابق عند عرض الشرائح.
navigator.mediaSession.setActionHandler('previousslide', () => {
// Show previous slide.
});
توافق المتصفّح
الشريحة التالية
يشير الإجراء "nextslide"
إلى أن المستخدم يريد الانتقال إلى الشريحة التالية
عند تقديم الشرائح.
navigator.mediaSession.setActionHandler('nextslide', () => {
// Show next slide.
});
دعم المتصفح
نماذج
اطّلِع على بعض عيّنات جلسات الوسائط التي تعرض Blender Foundation و أعمال Jan Morgenstern.
الموارد
- مواصفات جلسة الوسائط: wicg.github.io/mediasession
- مشاكل المواصفات: github.com/WICG/mediasession/issues
- أخطاء Chrome: crbug.com