Cách tích hợp với các phím phương tiện phần cứng, tuỳ chỉnh thông báo về nội dung nghe nhìn và nhiều tính năng khác.
Để cho người dùng biết nội dung đang phát trong trình duyệt và kiểm soát nội dung đó mà không cần quay lại trang đã phát, chúng tôi đã ra mắt Media Session API. API này cho phép nhà phát triển web tuỳ chỉnh trải nghiệm này thông qua siêu dữ liệu trong thông báo đa phương tiện tuỳ chỉnh, các sự kiện đa phương tiện như phát, tạm dừng, tua, thay đổi bản nhạc và các sự kiện hội nghị truyền hình như tắt/bật micrô, bật/tắt máy ảnh và cúp máy. Bạn có thể tuỳ chỉnh các chế độ này trong một số ngữ cảnh, bao gồm trung tâm nội dung nghe nhìn trên máy tính, thông báo nội dung nghe nhìn trên thiết bị di động và thậm chí cả trên thiết bị đeo. Tôi sẽ mô tả các cách tuỳ chỉnh đó trong bài viết này.
Giới thiệu về Media Session API
API Phiên phát nội dung nghe nhìn mang lại một số lợi ích và chức năng:
- Hỗ trợ các phím đa phương tiện phần cứng.
- Thông báo về nội dung nghe nhìn được tuỳ chỉnh trên thiết bị di động, máy tính và thiết bị đeo được ghép nối.
- Trung tâm nội dung nghe nhìn có trên máy tính.
- Các nút điều khiển nội dung nghe nhìn trên màn hình khoá có trên ChromeOS và thiết bị di động.
- Các chế độ điều khiển cửa sổ hình trong hình hiện có thể dùng để phát âm thanh, hội nghị truyền hình và trang trình bày.
- Bạn có thể sử dụng tính năng tích hợp Trợ lý trên thiết bị di động.
Sau đây là một số ví dụ minh hoạ một số điểm này.
Ví dụ 1: Nếu người dùng nhấn phím phương tiện "bản nhạc tiếp theo" trên bàn phím, thì nhà phát triển web có thể xử lý hành động của người dùng này cho dù trình duyệt đang ở nền trước hay nền sau.
Ví dụ 2: Nếu người dùng nghe podcast trên web trong khi màn hình thiết bị bị khoá, họ vẫn có thể nhấn vào biểu tượng "tua về" từ các nút điều khiển nội dung nghe nhìn trên màn hình khoá để nhà phát triển web chuyển thời gian phát về trước vài giây.
Ví dụ 3: Nếu người dùng có các thẻ phát âm thanh, họ có thể dễ dàng dừng phát từ trung tâm nội dung nghe nhìn trên máy tính để nhà phát triển web có cơ hội xoá trạng thái của họ.
Ví dụ 4: Nếu đang gọi video, người dùng có thể nhấn vào nút điều khiển "bật/tắt micrô" trong cửa sổ Hình trong hình để ngăn trang web nhận dữ liệu micrô.
Tất cả đều được thực hiện thông qua hai giao diện khác nhau: giao diện MediaSession
và giao diện MediaMetadata
. Chế độ đầu tiên cho phép người dùng kiểm soát mọi nội dung đang phát. Lý do thứ hai là cách bạn cho MediaSession
biết cần kiểm soát những gì.
Để minh hoạ, hình ảnh bên dưới cho thấy mối quan hệ giữa các giao diện này với các chế độ điều khiển nội dung nghe nhìn cụ thể, trong trường hợp này là thông báo nội dung nghe nhìn trên thiết bị di động.
Cho người dùng biết nội dung đang phát
Khi một trang web đang phát âm thanh hoặc video, người dùng sẽ tự động nhận được thông báo về nội dung nghe nhìn trong khay thông báo trên thiết bị di động hoặc trung tâm nội dung nghe nhìn trên máy tính. Trình duyệt sẽ cố gắng hết sức để hiển thị thông tin phù hợp bằng cách sử dụng tiêu đề của tài liệu và hình ảnh biểu tượng lớn nhất mà trình duyệt có thể tìm thấy. Với API phiên nội dung đa phương tiện, bạn có thể tuỳ chỉnh thông báo về nội dung đa phương tiện bằng một số siêu dữ liệu nội dung đa phương tiện phong phú hơn, chẳng hạn như tiêu đề, tên nghệ sĩ, tên đĩa nhạc và ảnh bìa như minh hoạ dưới đây.
Chrome yêu cầu quyền phát âm thanh "đầy đủ" để chỉ hiển thị các thông báo về nội dung nghe nhìn khi thời lượng nội dung nghe nhìn là ít nhất 5 giây. Điều này đảm bảo rằng các âm thanh tình cờ như tiếng bíp không hiển thị thông báo.
// 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.
}
Khi quá trình phát kết thúc, bạn không cần phải "giải phóng" phiên phát nội dung nghe nhìn vì thông báo sẽ tự động biến mất. Tuy nhiên, hãy lưu ý rằng navigator.mediaSession.metadata
sẽ được sử dụng khi quá trình phát tiếp theo bắt đầu. Đó là lý do bạn cần cập nhật thông tin này khi nguồn phát nội dung đa phương tiện thay đổi để đảm bảo thông tin liên quan xuất hiện trong thông báo nội dung đa phương tiện.
Có một vài điều cần lưu ý về siêu dữ liệu nội dung nghe nhìn.
- Mảng hình minh hoạ thông báo hỗ trợ URL của blob và URL dữ liệu.
- Nếu không có hình minh hoạ nào được xác định và có hình ảnh biểu tượng (được chỉ định bằng
<link rel=icon>
) ở kích thước mong muốn, thì các thông báo về nội dung đa phương tiện sẽ sử dụng hình ảnh đó. - Kích thước mục tiêu của hình minh hoạ thông báo trong Chrome dành cho Android là
512x512
. Đối với các thiết bị cấp thấp, giá trị này là256x256
. - Thuộc tính
title
của phần tử HTML nội dung nghe nhìn được dùng trong tiện ích "Đang phát" trên macOS. - Nếu tài nguyên phương tiện được nhúng (ví dụ: trong một iframe), bạn phải đặt thông tin Media Session API từ ngữ cảnh được nhúng. Hãy xem đoạn mã bên dưới.
<iframe id="iframe">
<video>...</video>
</iframe>
<script>
iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
...
});
</script>
Bạn cũng có thể thêm thông tin về từng phân cảnh, chẳng hạn như tiêu đề của phân cảnh, dấu thời gian và ảnh chụp màn hình vào siêu dữ liệu nội dung nghe nhìn. Điều này cho phép người dùng di chuyển qua nội dung của nội dung nghe nhìn.
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' },
]
}]
});
Cho phép người dùng kiểm soát nội dung đang phát
Hành động trong phiên phát nội dung nghe nhìn là một hành động (ví dụ: "phát" hoặc "tạm dừng") mà trang web có thể xử lý cho người dùng khi họ tương tác với chế độ phát nội dung nghe nhìn hiện tại. Hành động tương tự và hoạt động giống như sự kiện. Giống như sự kiện, thao tác được triển khai bằng cách đặt trình xử lý trên một đối tượng thích hợp, trong trường hợp này là một thực thể của MediaSession
. Một số thao tác được kích hoạt khi người dùng nhấn vào các nút trên tai nghe, một thiết bị từ xa khác, bàn phím hoặc tương tác với thông báo đa phương tiện.
Vì một số hành động trong phiên phát nội dung đa phương tiện có thể không được hỗ trợ, nên bạn nên sử dụng khối try…catch
khi thiết lập các hành động đó.
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.`);
}
}
Việc huỷ thiết lập trình xử lý thao tác trong phiên phát nội dung nghe nhìn cũng dễ dàng như thiết lập trình xử lý đó thành 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.`);
}
Sau khi được đặt, trình xử lý hành động trong phiên phát nội dung nghe nhìn sẽ tiếp tục hoạt động trong quá trình phát nội dung nghe nhìn. Việc này tương tự như mẫu trình nghe sự kiện, ngoại trừ việc xử lý một sự kiện đồng nghĩa với việc trình duyệt ngừng thực hiện mọi hành vi mặc định và sử dụng mẫu này làm tín hiệu cho biết trang web hỗ trợ hành động đối với nội dung đa phương tiện. Do đó, các chế độ điều khiển hành động đa phương tiện sẽ không hiển thị trừ khi bạn đặt trình xử lý hành động thích hợp.
Phát / tạm dừng
Thao tác "play"
cho biết người dùng muốn tiếp tục phát nội dung nghe nhìn trong khi "pause"
cho biết họ muốn tạm dừng phát.
Biểu tượng "phát/tạm dừng" luôn xuất hiện trong thông báo về nội dung nghe nhìn và các sự kiện nội dung nghe nhìn có liên quan được trình duyệt xử lý tự động. Để ghi đè hành vi mặc định, hãy xử lý các thao tác "phát" và "tạm dừng" nội dung nghe nhìn như minh hoạ dưới đây.
Ví dụ: trình duyệt có thể coi một trang web không phát nội dung nghe nhìn khi tìm kiếm hoặc tải. Trong trường hợp này, hãy ghi đè hành vi này bằng cách đặt navigator.mediaSession.playbackState
thành "playing"
hoặc "paused"
để đảm bảo giao diện người dùng của trang web luôn đồng bộ với các chế độ điều khiển thông báo nội dung nghe nhì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';
});
Bản nhạc trước
Thao tác "previoustrack"
cho biết người dùng muốn bắt đầu quá trình phát nội dung nghe nhìn hiện tại ngay từ đầu nếu quá trình phát nội dung nghe nhìn có khái niệm là bắt đầu, hoặc chuyển sang mục trước đó trong danh sách phát nếu quá trình phát nội dung nghe nhìn có khái niệm là danh sách phát.
navigator.mediaSession.setActionHandler('previoustrack', () => {
// Play previous track.
});
Bản nhạc tiếp theo
Thao tác "nexttrack"
cho biết người dùng muốn chuyển chế độ phát nội dung nghe nhìn sang mục tiếp theo trong danh sách phát nếu trình phát nội dung nghe nhìn có khái niệm là danh sách phát.
navigator.mediaSession.setActionHandler('nexttrack', () => {
// Play next track.
});
Dừng
Thao tác "stop"
cho biết người dùng muốn dừng phát nội dung nghe nhìn và xoá trạng thái nếu thích hợp.
navigator.mediaSession.setActionHandler('stop', () => {
// Stop playback and clear state if appropriate.
});
Tua lại/tới
Thao tác "seekbackward"
cho biết người dùng muốn chuyển thời gian phát nội dung nghe nhìn lui một khoảng thời gian ngắn, trong khi "seekforward"
cho biết người dùng muốn chuyển thời gian phát nội dung nghe nhìn tới một khoảng thời gian ngắn. Trong cả hai trường hợp, khoảng thời gian ngắn có nghĩa là vài giây.
Giá trị seekOffset
được cung cấp trong trình xử lý hành động là thời gian tính bằng giây để di chuyển thời gian phát nội dung nghe nhìn. Nếu không được cung cấp (ví dụ: undefined
), bạn nên sử dụng một khoảng thời gian hợp lý (ví dụ: 10-30 giây).
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.
});
Tua đến một thời điểm cụ thể
Thao tác "seekto"
cho biết người dùng muốn chuyển thời gian phát nội dung nghe nhìn sang một thời điểm cụ thể.
Giá trị seekTime
được cung cấp trong trình xử lý hành động là thời gian tính bằng giây để chuyển thời gian phát nội dung nghe nhìn.
Giá trị boolean fastSeek
được cung cấp trong trình xử lý hành động là true nếu hành động đó được gọi nhiều lần trong một trình tự và đây không phải là lệnh gọi cuối cùng trong trình tự đó.
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.
});
Đặt vị trí phát
Việc hiển thị chính xác vị trí phát nội dung nghe nhìn trong thông báo chỉ đơn giản là đặt trạng thái vị trí tại thời điểm thích hợp như minh hoạ bên dưới. Trạng thái vị trí là sự kết hợp giữa tốc độ phát nội dung nghe nhìn, thời lượng và thời gian hiện tại.
Bạn phải cung cấp thời lượng và thời lượng phải là số dương. Vị trí phải là số dương và nhỏ hơn thời lượng. Tốc độ phát phải lớn hơn 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();
});
Bạn có thể đặt lại trạng thái vị trí dễ dàng bằng cách đặt trạng thái đó thành null
.
// Reset position state when media is reset.
navigator.mediaSession.setPositionState(null);
Thao tác trong hội nghị truyền hình
Khi người dùng chuyển cuộc gọi video vào cửa sổ Hình trong hình, trình duyệt có thể hiển thị các nút điều khiển micrô và máy ảnh cũng như nút ngắt cuộc gọi. Khi người dùng nhấp vào các nút đó, trang web sẽ xử lý các nút đó thông qua các thao tác hội nghị video bên dưới. Để biết ví dụ, hãy xem Mẫu Hội nghị truyền hình.
Bật/tắt micrô
Thao tác "togglemicrophone"
cho biết người dùng muốn tắt hoặc bật micrô. Phương thức setMicrophoneActive(isActive)
cho trình duyệt biết liệu trang web hiện có coi micrô là đang hoạt động hay không.
let isMicrophoneActive = false;
navigator.mediaSession.setActionHandler('togglemicrophone', () => {
if (isMicrophoneActive) {
// Mute the microphone.
} else {
// Unmute the microphone.
}
isMicrophoneActive = !isMicrophoneActive;
navigator.mediaSession.setMicrophoneActive(isMicrophoneActive);
});
Bật/tắt camera
Thao tác "togglecamera"
cho biết người dùng muốn bật hoặc tắt camera đang hoạt động. Phương thức setCameraActive(isActive)
cho biết liệu trình duyệt có coi trang web là đang hoạt động hay không.
let isCameraActive = false;
navigator.mediaSession.setActionHandler('togglecamera', () => {
if (isCameraActive) {
// Disable the camera.
} else {
// Enable the camera.
}
isCameraActive = !isCameraActive;
navigator.mediaSession.setCameraActive(isCameraActive);
});
Kết thúc cuộc gọi
Thao tác "hangup"
cho biết người dùng muốn kết thúc cuộc gọi.
navigator.mediaSession.setActionHandler('hangup', () => {
// End the call.
});
Hành động trình bày trang trình bày
Khi người dùng đặt bản trình bày trang trình bày vào cửa sổ Hình trong hình, trình duyệt có thể hiển thị các chế độ điều khiển để di chuyển qua các trang trình bày. Khi người dùng nhấp vào các nút đó, trang web sẽ xử lý các nút đó thông qua Media Session API. Để xem ví dụ, hãy xem Mẫu trình bày trang trình bày.
Trang trình bày trước
Thao tác "previousslide"
cho biết người dùng muốn quay lại trang trình bày trước khi trình bày các trang trình bày.
navigator.mediaSession.setActionHandler('previousslide', () => {
// Show previous slide.
});
Hỗ trợ trình duyệt
Trang trình bày tiếp theo
Thao tác "nextslide"
cho biết người dùng muốn chuyển sang trang trình bày tiếp theo khi chiếu các trang trình bày.
navigator.mediaSession.setActionHandler('nextslide', () => {
// Show next slide.
});
Hỗ trợ trình duyệt
Mẫu
Hãy xem một số mẫu Phiên phát nội dung đa phương tiện có Blender Foundation và công việc của Jan Morgenstern.
Tài nguyên
- Thông số kỹ thuật của phiên phát nội dung nghe nhìn: wicg.github.io/mediasession
- Vấn đề về thông số kỹ thuật: github.com/WICG/mediasession/issues
- Lỗi Chrome: crbug.com