Bạn có thể chia sẻ các thẻ, cửa sổ và màn hình trên nền tảng web bằng Screen Capture API. Khi một ứng dụng web gọi getDisplayMedia()
, Chrome sẽ nhắc người dùng chia sẻ một thẻ, cửa sổ hoặc màn hình với ứng dụng web dưới dạng video MediaStreamTrack
.
Nhiều ứng dụng web dùng getDisplayMedia()
sẽ cho người dùng xem trước video của giao diện đã chụp. Ví dụ: các ứng dụng hội nghị truyền hình thường sẽ truyền trực tuyến video này đến người dùng từ xa, đồng thời hiển thị video đó cho một HTMLVideoElement
cục bộ để người dùng cục bộ liên tục xem bản xem trước nội dung họ đang chia sẻ.
Tài liệu này giới thiệu Captured Surface Control API (API Điều khiển bề mặt đã chụp) trong Chrome. API này cho phép ứng dụng web của bạn cuộn một thẻ đã chụp, cũng như đọc và ghi mức thu phóng của thẻ đã chụp.
Tại sao bạn nên sử dụng tính năng Kiểm soát bề mặt được chụp?
Tất cả ứng dụng hội nghị truyền hình đều gặp phải cùng một hạn chế: nếu người dùng muốn tương tác với một thẻ hoặc cửa sổ đã chụp, thì người dùng phải chuyển sang nền tảng đó, rời khỏi ứng dụng hội nghị truyền hình. Điều này gây ra một số thách thức:
- Người dùng không thể xem ứng dụng đã chụp và video của người dùng từ xa cùng một lúc, trừ phi họ sử dụng chế độ Hình trong hình hoặc các cửa sổ cạnh nhau riêng biệt cho thẻ hội nghị video và thẻ được chia sẻ. Trên một màn hình nhỏ hơn, điều này có thể khó khăn.
- Người dùng phải chuyển đổi giữa ứng dụng hội nghị truyền hình và giao diện được chụp.
- Người dùng mất quyền truy cập vào các chế độ điều khiển mà ứng dụng hội nghị truyền hình hiển thị khi họ rời khỏi ứng dụng đó; ví dụ: ứng dụng trò chuyện được nhúng, biểu tượng cảm xúc, thông báo về người dùng yêu cầu tham gia cuộc gọi, chế độ điều khiển bố cục và nội dung đa phương tiện, cũng như các tính năng hội nghị truyền hình hữu ích khác.
- Người trình bày không thể uỷ quyền quyền kiểm soát cho người tham gia từ xa. Điều này dẫn đến một tình huống quá quen thuộc, trong đó người dùng từ xa yêu cầu người trình bày thay đổi trang trình bày, cuộn lên và xuống một chút hoặc điều chỉnh mức thu phóng.
API Điều khiển giao diện đã chụp giải quyết những vấn đề này.
Làm cách nào để sử dụng Kiểm soát bề mặt được chụp?
Để sử dụng thành công tính năng Kiểm soát giao diện đã chụp, bạn cần thực hiện một vài bước, chẳng hạn như chụp rõ ràng một thẻ trình duyệt và nhận quyền của người dùng trước khi có thể cuộn và thu phóng thẻ đã chụp.
Ghi lại thẻ trình duyệt
Bắt đầu bằng cách nhắc người dùng chọn một nền tảng để chia sẻ bằng getDisplayMedia()
và trong quá trình này, hãy liên kết đối tượng CaptureController
với phiên chụp. Chúng ta sẽ sớm sử dụng đối tượng đó để kiểm soát bề mặt đã chụp.
const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });
Tiếp theo, hãy tạo bản xem trước cục bộ của bề mặt được chụp ở dạng phần tử <video>
:
const previewTile = document.querySelector('video');
previewTile.srcObject = stream;
Nếu người dùng chọn chia sẻ một cửa sổ hoặc màn hình, thì hiện nằm ngoài phạm vi của yêu cầu đó — nhưng nếu họ đã chọn chia sẻ một thẻ, thì chúng tôi có thể tiếp tục.
const [track] = stream.getVideoTracks();
if (track.getSettings().displaySurface !== 'browser') {
// Bail out early if the user didn't pick a tab.
return;
}
Lời nhắc cấp quyền
Lệnh gọi đầu tiên của sendWheel()
hoặc setZoomLevel()
trên một đối tượng CaptureController
nhất định sẽ tạo ra lời nhắc cấp quyền. Nếu người dùng cấp quyền, thì các lệnh gọi tiếp theo của các phương thức này trên đối tượng CaptureController
đó sẽ được cho phép. Nếu người dùng từ chối cấp quyền, thì lời hứa được trả về sẽ bị từ chối.
Lưu ý rằng các đối tượng CaptureController
được liên kết duy nhất với một phiên chụp cụ thể, không thể liên kết với một phiên chụp khác và không tồn tại trong phần điều hướng của trang mà chúng được xác định. Tuy nhiên, các phiên chụp vẫn tồn tại sau khi điều hướng của trang được thu thập.
Bạn phải có một cử chỉ của người dùng để hiển thị lời nhắc cấp quyền cho người dùng. Chỉ các lệnh gọi sendWheel()
và setZoomLevel()
mới yêu cầu cử chỉ của người dùng và chỉ khi cần hiển thị lời nhắc. Nếu người dùng nhấp vào nút phóng to hoặc thu nhỏ trong ứng dụng web, thì cử chỉ người dùng đó sẽ được tính cho họ; nhưng nếu ứng dụng muốn cung cấp tính năng kiểm soát cuộn trước tiên, nhà phát triển cần lưu ý rằng thao tác cuộn không tạo thành một cử chỉ của người dùng. Một khả năng là trước tiên, hãy cung cấp cho người dùng nút "bắt đầu cuộn", như trong ví dụ sau:
const startScrollingButton = document.querySelector('button');
startScrollingButton.addEventListener('click', async () => {
try {
const noOpWheelAction = {};
await controller.sendWheel(noOpWheelAction);
// The user approved the permission prompt.
// You can now scroll and zoom the captured tab as shown later in the article.
} catch (error) {
return; // Permission denied. Bail.
}
});
Cuộn
Bằng cách sử dụng sendWheel()
, một ứng dụng chụp ảnh có thể cung cấp các sự kiện bánh xe có cường độ đã chọn trên các toạ độ mà ứng dụng đó chọn trong khung nhìn của một thẻ. Ứng dụng đã ghi lại không thể phân biệt sự kiện này với lượt tương tác trực tiếp của người dùng.
Giả sử ứng dụng chụp sử dụng phần tử <video>
có tên là "previewTile"
, mã sau đây cho biết cách chuyển tiếp các sự kiện gửi con lăn đến thẻ đã chụp:
const previewTile = document.querySelector('video');
previewTile.addEventListener('wheel', async (event) => {
// Translate the offsets into coordinates which sendWheel() can understand.
// The implementation of this translation is explained further below.
const [x, y] = translateCoordinates(event.offsetX, event.offsetY);
const [wheelDeltaX, wheelDeltaY] = [-event.deltaX, -event.deltaY];
try {
// Relay the user's action to the captured tab.
await controller.sendWheel({ x, y, wheelDeltaX, wheelDeltaY });
} catch (error) {
// Inspect the error.
// ...
}
});
Phương thức sendWheel()
lấy một từ điển có hai bộ giá trị:
x
vày
: toạ độ nơi phân phối sự kiện con lăn.wheelDeltaX
vàwheelDeltaY
: độ lớn của thao tác cuộn (tính bằng pixel) tương ứng với thao tác cuộn ngang và dọc. Xin lưu ý rằng các giá trị này được đảo ngược so với sự kiện con lăn ban đầu.
Bạn có thể triển khai translateCoordinates()
như sau:
function translateCoordinates(offsetX, offsetY) {
const previewDimensions = previewTile.getBoundingClientRect();
const trackSettings = previewTile.srcObject.getVideoTracks()[0].getSettings();
const x = trackSettings.width * offsetX / previewDimensions.width;
const y = trackSettings.height * offsetY / previewDimensions.height;
return [Math.floor(x), Math.floor(y)];
}
Xin lưu ý rằng có 3 kích thước khác nhau trong mã trước đó:
- Kích thước của phần tử
<video>
. - Kích thước của các khung hình được chụp (được biểu thị ở đây là
trackSettings.width
vàtrackSettings.height
). - Kích thước của thẻ.
Kích thước của phần tử <video>
nằm hoàn toàn trong phạm vi của ứng dụng chụp và trình duyệt không biết. Kích thước của thẻ nằm hoàn toàn trong miền của trình duyệt và ứng dụng web không xác định được.
Ứng dụng web sử dụng translateCoordinates()
để chuyển đổi độ lệch tương ứng của phần tử <video>
thành các toạ độ trong không gian toạ độ riêng của bản nhạc video. Trình duyệt cũng sẽ dịch giữa kích thước của các khung hình đã chụp và kích thước của thẻ, đồng thời phân phối sự kiện cuộn ở một độ dời tương ứng với kỳ vọng của ứng dụng web.
Lời hứa do sendWheel()
trả về có thể bị từ chối trong các trường hợp sau:
- Nếu phiên chụp chưa bắt đầu hoặc đã dừng, bao gồm cả việc dừng không đồng bộ trong khi trình duyệt xử lý thao tác
sendWheel()
. - Nếu người dùng không cấp quyền cho ứng dụng sử dụng
sendWheel()
. - Nếu ứng dụng chụp cố gắng phân phối một sự kiện cuộn ở các toạ độ nằm ngoài
[trackSettings.width, trackSettings.height]
. Lưu ý rằng các giá trị này có thể thay đổi không đồng bộ, vì vậy, bạn nên phát hiện và bỏ qua lỗi. (Lưu ý rằng0, 0
thường không nằm ngoài giới hạn, vì vậy, bạn có thể an toàn sử dụng các quyền này để nhắc người dùng cấp quyền.)
Zoom (thu phóng)
Hoạt động tương tác với mức thu phóng của thẻ đã chụp được thực hiện thông qua các vùng hiển thị CaptureController
sau:
getSupportedZoomLevels()
trả về danh sách các mức thu phóng mà trình duyệt hỗ trợ, được biểu thị dưới dạng phần trăm của "mức thu phóng mặc định", được xác định là 100%. Danh sách này tăng đơn điệu và chứa giá trị 100.getZoomLevel()
trả về mức thu phóng hiện tại của thẻ.setZoomLevel()
đặt mức thu phóng của thẻ thành bất kỳ giá trị số nguyên nào có tronggetSupportedZoomLevels()
và trả về một lời hứa khi thành công. Lưu ý rằng mức thu phóng không được đặt lại vào cuối phiên chụp.oncapturedzoomlevelchange
cho phép bạn theo dõi các thay đổi về mức thu phóng của thẻ đã chụp vì người dùng có thể thay đổi mức thu phóng thông qua ứng dụng chụp hoặc thông qua hoạt động tương tác trực tiếp với thẻ đã chụp.
Các lệnh gọi đến setZoomLevel()
được kiểm soát theo quyền; các lệnh gọi đến các phương thức thu phóng chỉ đọc khác là "miễn phí", cũng như các lệnh gọi sự kiện.
Ví dụ sau đây minh hoạ cách tăng mức thu phóng của một thẻ được chụp trong phiên chụp ảnh hiện có:
const zoomIncreaseButton = document.getElementById('zoomInButton');
zoomIncreaseButton.addEventListener('click', async (event) => {
const levels = CaptureController.getSupportedZoomLevels();
const index = levels.indexOf(controller.getZoomLevel());
const newZoomLevel = levels[Math.min(index + 1, levels.length - 1)];
try {
await controller.setZoomLevel(newZoomLevel);
} catch (error) {
// Inspect the error.
// ...
}
});
Ví dụ sau đây cho bạn biết cách phản ứng với các thay đổi về mức thu phóng của một thẻ đã chụp:
controller.addEventListener('capturedzoomlevelchange', (event) => {
const zoomLevel = controller.getZoomLevel();
document.querySelector('#zoomLevelLabel').textContent = `${zoomLevel}%`;
});
Phát hiện tính năng
Để kiểm tra xem tính năng gửi sự kiện con lăn có được hỗ trợ hay không, hãy sử dụng:
if (!!window.CaptureController?.prototype.sendWheel) {
// CaptureController sendWheel() is supported.
}
Để kiểm tra xem tính năng điều khiển thu phóng có được hỗ trợ hay không, hãy sử dụng:
if (!!window.CaptureController?.prototype.setZoomLevel) {
// CaptureController setZoomLevel() is supported.
}
Bật tính năng Điều khiển giao diện đã chụp
Captured Surface Control API có trong Chrome trên máy tính sau cờ Captured Surface Control (Kiểm soát bề mặt được thu thập) và có thể được bật tại chrome://flags/#captured-surface-control
.
Tính năng này cũng đang bước vào giai đoạn thử nghiệm theo nguồn gốc bắt đầu từ Chrome 122 trên máy tính. Tính năng này cho phép nhà phát triển bật tính năng này cho khách truy cập trang web của họ để thu thập dữ liệu từ người dùng thực. Hãy xem bài viết Bắt đầu sử dụng thử nghiệm theo nguồn gốc để biết thêm thông tin về thử nghiệm theo nguồn gốc và cách hoạt động của thử nghiệm này.
Bảo mật và quyền riêng tư
Chính sách quyền "captured-surface-control"
cho phép bạn quản lý cách ứng dụng chụp của bạn và iframe được nhúng của bên thứ ba có quyền truy cập vào tính năng Kiểm soát nền tảng được ghi lại. Để tìm hiểu các yếu tố đánh đổi về mặt bảo mật, hãy xem phần Các điểm cần cân nhắc về quyền riêng tư và bảo mật trong tài liệu giải thích về Chế độ kiểm soát bề mặt được chụp lại.
Bản minh hoạ
Bạn có thể chơi với Captured Surface Control bằng cách chạy bản minh hoạ trên Glitch. Hãy nhớ xem mã nguồn.
Thay đổi so với các phiên bản Chrome trước
Dưới đây là một số điểm khác biệt chính về hành vi liên quan đến chế độ Kiểm soát bề mặt được thu thập mà bạn cần lưu ý:
- Trong Chrome 124 trở xuống:
- Quyền (nếu được cấp) sẽ thuộc phạm vi phiên chụp được liên kết với
CaptureController
đó, chứ không phải thuộc phạm vi nguồn gốc chụp.
- Quyền (nếu được cấp) sẽ thuộc phạm vi phiên chụp được liên kết với
- Trong Chrome 122:
getZoomLevel()
trả về một lời hứa với mức thu phóng hiện tại của thẻ.sendWheel()
trả về lời hứa bị từ chối kèm theo thông báo lỗi"No permission."
nếu người dùng không cấp quyền sử dụng cho ứng dụng. Loại lỗi này là"NotAllowedError"
trong Chrome 123 trở lên.- Không dùng được
oncapturedzoomlevelchange
. Bạn có thể polyfill tính năng này bằngsetInterval()
.
Phản hồi
Nhóm Chrome và cộng đồng tiêu chuẩn web muốn biết trải nghiệm của bạn với tính năng Điều khiển giao diện được chụp.
Hãy cho chúng tôi biết về thiết kế
Có điều gì về tính năng Quay video màn hình không hoạt động như mong đợi không? Hay có phương thức hay thuộc tính nào bị thiếu để triển khai ý tưởng của bạn không? Bạn có câu hỏi hoặc nhận xét về mô hình bảo mật này? Gửi vấn đề về thông số kỹ thuật trên kho lưu trữ GitHub hoặc thêm ý kiến của bạn vào một vấn đề hiện có.
Bạn gặp vấn đề trong quá trình triển khai?
Bạn có phát hiện lỗi khi triển khai Chrome không? Hay cách triển khai có khác với thông số kỹ thuật không? Gửi lỗi tại https://new.crbug.com. Hãy nhớ cung cấp càng nhiều thông tin chi tiết càng tốt, cũng như hướng dẫn cách tái hiện lỗi. Glitch rất hữu ích để chia sẻ các lỗi có thể tái hiện.