วิธีผสานรวมกับคีย์สื่อแบบฮาร์ดแวร์ ปรับแต่งการแจ้งเตือนสื่อ และอื่นๆ
เราจึงเปิดตัว Media Session API เพื่อช่วยให้ผู้ใช้ทราบว่ากำลังเล่นอะไรอยู่ในเบราว์เซอร์ และควบคุมได้โดยไม่ต้องกลับไปยังหน้าที่เปิดแอป ซึ่งช่วยให้นักพัฒนาเว็บปรับแต่งการใช้งานนี้ได้ผ่านข้อมูลเมตาในการแจ้งเตือนสื่อที่กำหนดเอง เหตุการณ์เกี่ยวกับสื่อ เช่น การเล่น หยุดชั่วคราว กรอวิดีโอ การติดตามการเปลี่ยนแปลง และกิจกรรมการประชุมทางวิดีโออย่างปิด/เปิดเสียงไมโครโฟน เปิด/ปิดกล้อง และวางสาย การปรับแต่งเหล่านี้พร้อมใช้งานในหลายๆ บริบท เช่น ฮับสื่อบนเดสก์ท็อป การแจ้งเตือนสื่อบนอุปกรณ์เคลื่อนที่ หรือแม้แต่ในอุปกรณ์ที่สวมใส่ได้ ฉันจะอธิบายเกี่ยวกับการกำหนดค่าเหล่านี้ ในบทความนี้
เกี่ยวกับ Media Session API
API เซสชันสื่อมีประโยชน์และความสามารถหลายอย่าง:
- รองรับคีย์สื่อของฮาร์ดแวร์
- การแจ้งเตือนสื่อมีการปรับแต่งบนอุปกรณ์เคลื่อนที่ เดสก์ท็อป และอุปกรณ์ที่สวมใส่ได้ซึ่งจับคู่กัน
- ฮับสื่อมีให้บริการบนเดสก์ท็อป
- การควบคุมสื่อในหน้าจอล็อกใช้งานได้ใน ChromeOS และอุปกรณ์เคลื่อนที่
- การควบคุมหน้าต่างการแสดงภาพซ้อนภาพใช้ได้กับการเล่นเสียง การประชุมทางวิดีโอ และสไลด์การนำเสนอ
- การผสานรวมกับ Assistant ในอุปกรณ์เคลื่อนที่พร้อมใช้งาน
ตัวอย่าง 2-3 รายการจะช่วยอธิบายถึงประเด็นเหล่านี้
ตัวอย่างที่ 1: หากผู้ใช้กดแป้นสื่อ "แทร็กถัดไป" ของแป้นพิมพ์ นักพัฒนาเว็บจะจัดการการดำเนินการของผู้ใช้นี้ได้ไม่ว่าเบราว์เซอร์จะอยู่ที่เบื้องหน้าหรือเบื้องหลัง
ตัวอย่างที่ 2: หากผู้ใช้ฟังพอดแคสต์บนเว็บในขณะที่หน้าจออุปกรณ์ล็อกอยู่ ผู้ใช้จะยังคงกดไอคอน "กรอย้อนกลับ" จากตัวควบคุมสื่อในหน้าจอล็อกได้ เพื่อให้นักพัฒนาเว็บเลื่อนเวลาเล่นไปข้างหลัง 2-3 วินาทีได้
ตัวอย่างที่ 3: หากผู้ใช้มีแท็บที่เล่นเสียง ผู้ใช้สามารถหยุดการเล่นจากฮับสื่อบนเดสก์ท็อปได้อย่างง่ายดายเพื่อให้นักพัฒนาเว็บล้างสถานะของตนได้
ตัวอย่างที่ 4: หากผู้ใช้อยู่ในวิดีโอคอล ผู้ใช้จะกดตัวควบคุม "สลับไมโครโฟน" ในหน้าต่างการแสดงภาพซ้อนภาพเพื่อไม่ให้เว็บไซต์รับข้อมูลไมโครโฟนได้
โดยทำผ่านอินเทอร์เฟซ 2 รายการที่แตกต่างกัน ได้แก่ อินเทอร์เฟซ MediaSession
และอินเทอร์เฟซ MediaMetadata
ตัวเลือกแรกจะให้ผู้ใช้ควบคุมสิ่งที่
เล่นอยู่ได้ อย่างที่ 2 คือวิธีบอกให้ 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
เมื่อการเล่นครั้งถัดไปเริ่มเล่น คุณจึงควรอัปเดตข้อมูลนี้เมื่อมีการเปลี่ยนแปลงแหล่งที่มาของการเล่นสื่อเพื่อให้แน่ใจว่าข้อมูลที่เกี่ยวข้องจะแสดงในการแจ้งเตือนสื่อ
สิ่งที่ควรทราบเกี่ยวกับข้อมูลเมตาของสื่อมีดังนี้
- อาร์เรย์อาร์ตเวิร์กการแจ้งเตือนรองรับ BLOB 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
เช่นเดียวกับเหตุการณ์ การดำเนินการบางอย่างจะทริกเกอร์เมื่อผู้ใช้กดปุ่มจากชุดหูฟัง อุปกรณ์ระยะไกลเครื่องอื่น แป้นพิมพ์ หรือโต้ตอบกับการแจ้งเตือนสื่อ
เนื่องจากระบบอาจไม่รองรับการดำเนินการของเซสชันสื่อบางอย่าง เราจึงขอแนะนำให้ใช้การบล็อก 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.`);
}
เมื่อตั้งค่าแล้ว ตัวแฮนเดิลการทำงานเซสชันสื่อจะยังคงอยู่ผ่านการเล่นสื่อ สิ่งนี้คล้ายกับรูปแบบ Listener เหตุการณ์ เว้นแต่ว่าการจัดการเหตุการณ์หมายความว่าเบราว์เซอร์จะหยุดการทำงานที่เป็นค่าเริ่มต้นและใช้สิ่งนี้เป็นสัญญาณว่าเว็บไซต์รองรับการทำงานของสื่อ ดังนั้น การควบคุมการใช้สื่อจะไม่แสดง จนกว่าจะมีการตั้งค่าเครื่องจัดการการดำเนินการที่เหมาะสม
เล่น / หยุดชั่วคราว
การดำเนินการ "play"
บ่งบอกว่าผู้ใช้ต้องการเล่นสื่อต่อขณะที่ "pause"
บ่งบอกว่าผู้ใช้ต้องการหยุดเล่นสื่อชั่วคราว
ไอคอน "เล่น/หยุดชั่วคราว" จะแสดงในการแจ้งเตือนสื่อเสมอ และเบราว์เซอร์จะจัดการเหตุการณ์สื่อที่เกี่ยวข้องโดยอัตโนมัติ หากต้องการลบล้างลักษณะการทำงานเริ่มต้น ให้จัดการการดำเนินการกับสื่อแบบ "เล่น" และ "หยุดชั่วคราว" ดังที่แสดงด้านล่าง
เบราว์เซอร์อาจถือว่าเว็บไซต์ไม่เล่นสื่อเมื่อกรอหรือโหลด เป็นต้น ในกรณีนี้ ให้ลบล้างลักษณะการทำงานนี้โดยการตั้งค่า navigator.mediaSession.playbackState
เป็น "playing"
หรือ "paused"
เพื่อให้ UI ของเว็บไซต์ซิงค์กับตัวควบคุมการแจ้งเตือนสื่ออยู่เสมอ
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"
บ่งบอกความต้องการที่จะย้ายเวลาการเล่นสื่อไปข้างหน้าเป็นระยะเวลาสั้นๆ ในทั้ง 2 กรณี ระยะเวลาสั้นๆ
หมายถึงไม่กี่วินาที
ค่า 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.
});
การดำเนินการในการนำเสนอสไลด์
เมื่อผู้ใช้นำเสนอสไลด์ในหน้าต่างการแสดงภาพซ้อนภาพ เบราว์เซอร์อาจแสดงตัวควบคุมสำหรับไปยังส่วนต่างๆ ของสไลด์ เมื่อผู้ใช้คลิกรายการเหล่านั้น เว็บไซต์จะจัดการกับข้อความเหล่านั้นผ่าน Media Session API โปรดดูตัวอย่างจากตัวอย่างการนำเสนอสไลด์
สไลด์ก่อนหน้า
การดำเนินการ "previousslide"
บ่งบอกว่าผู้ใช้ต้องการกลับไปที่สไลด์ก่อนหน้าเมื่อนำเสนอสไลด์
navigator.mediaSession.setActionHandler('previousslide', () => {
// Show previous slide.
});
การสนับสนุนเบราว์เซอร์
- 111
- 111
- x
- x
สไลด์ถัดไป
เมื่อนำเสนอสไลด์ การดำเนินการ "nextslide"
จะระบุว่าผู้ใช้ต้องการไปที่สไลด์ถัดไป
navigator.mediaSession.setActionHandler('nextslide', () => {
// Show next slide.
});
การสนับสนุนเบราว์เซอร์
- 111
- 111
- x
- x
ตัวอย่างผลิตภัณฑ์
ลองดูตัวอย่างเซสชันสื่อบางส่วนที่ประกอบด้วย Blender Foundation และผลงานของ Jan Morgenstern
แหล่งข้อมูล
- ข้อมูลจำเพาะของเซสชันสื่อ: wicg.github.io/mediasession
- ปัญหาเกี่ยวกับข้อมูลจำเพาะ: github.com/WICG/mediasession/issues
- ข้อบกพร่องของ Chrome: crbug.com