Ghi lại luồng video từ bất kỳ phần tử nào

François Beaufort
François Beaufort

Với API Chụp ảnh màn hình, bạn có thể chụp toàn bộ thẻ hiện tại. API Chụp phần tử cho phép bạn chụp và ghi lại một phần tử HTML cụ thể. Việc này biến đổi việc chụp toàn bộ thẻ, thành việc chụp một cây con DOM cụ thể, chỉ chụp các thành phần con trực tiếp của phần tử mục tiêu. Nói cách khác, công cụ này sẽ cắt và xoá cả nội dung bị che khuất và nội dung bị che khuất.

Tại sao bạn nên sử dụng tính năng Chụp phần tử?

Việc xem xét các yêu cầu của ứng dụng hội nghị truyền hình có thể giúp bạn hiểu phần tử Capture hữu ích ở điểm nào. Nếu có ứng dụng hội nghị truyền hình cho phép bạn nhúng các ứng dụng của bên thứ ba vào iframe, đôi khi bạn có thể muốn ghi lại iframe đó dưới dạng video và truyền video đến những người tham gia từ xa.

Ảnh chụp màn hình cuộc gọi hội nghị truyền hình trong Chrome.
Elad dùng ứng dụng của bên thứ ba trong cuộc gọi hội nghị truyền hình với François.

Nếu gọi getDisplayMedia() và cho phép người dùng chọn thẻ hiện tại, thì toàn bộ thẻ hiện tại sẽ được truyền. Điều đó có khả năng truyền video của chính mọi người trở lại với họ. Bạn có thể cắt phần này bằng tính năng Chụp ảnh khu vực.

Tuy nhiên, điều gì sẽ xảy ra nếu người trình bày tương tác với ứng dụng hội nghị truyền hình và một số nội dung, chẳng hạn như danh sách thả xuống, tình cờ vẽ lên đầu nội dung mà họ muốn ghi lại?

Ảnh chụp màn hình một danh sách thả xuống che khuất nội dung bạn muốn chụp.
Một danh sách thả xuống sẽ xuất hiện ở đầu nội dung bạn muốn quay.

Tính năng Chụp ảnh khu vực sẽ không giúp bạn ở đó. Một phần của danh sách thả xuống có thể hiển thị với người tham gia từ xa màn hình.

Đã chụp ảnh màn hình danh sách thả xuống.
Danh sách thả xuống của Elad xuất hiện ở đầu nội dung mà François nhận được.

Trên thực tế, tính năng Chụp ảnh khu vực ghi lại các phần của các phần tử theo cách này (còn gọi là nội dung che khuất) sẽ gây ra nhiều vấn đề:

  • Nội dung bị che khuất có thể cản trở việc xem nội dung mà người dùng định chia sẻ.
  • Nội dung bị ẩn có thể là nội dung riêng tư (ví dụ: thông báo trò chuyện).
  • Nội dung bị che khuất có thể gây nhầm lẫn. (Ví dụ: bố cục lại của ứng dụng có thể đưa nhanh video của chính người tham gia từ xa lên mục tiêu bị bắt.)

Element Capture API giải quyết tất cả các vấn đề này bằng cách cho phép bạn nhắm mục tiêu phần tử mình muốn chia sẻ.

Ảnh chụp màn hình phần tử mục tiêu không có danh sách thả xuống trong chế độ xem.
François không thấy danh sách thả xuống của Elad.

Làm cách nào để sử dụng tính năng Chụp phần tử?

captureTarget là một Phần tử trên trang của bạn có chứa nội dung mà người dùng muốn ghi lại. Bạn muốn ứng dụng web hội nghị truyền hình ghi lại captureTarget và chia sẻ thiết bị đó với những người tham gia từ xa. Do đó, bạn lấy được RestrictionTarget từ captureTarget. Sau khi hạn chế bản nhạc video bằng RestrictionTarget này, khung hình trên bản nhạc video đó giờ đây chỉ bao gồm các pixel thuộc captureTarget và các thành phần con DOM trực tiếp của nó.

Nếu captureTarget thay đổi kích thước, hình dạng hoặc vị trí, thì bản video sẽ tiếp tục phát mà không đòi hỏi bất kỳ thông tin đầu vào nào khác từ ứng dụng web. Nội dung che khuất xuất hiện, biến mất hoặc di chuyển xung quanh (tương tự như vậy không cần xử lý đặc biệt).

Xem lại các bước sau:

Bắt đầu bằng cách cho phép người dùng ghi lại thẻ hiện tại.

// Ask the user for permission to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
 preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();

Xác định RestrictionTarget bằng cách gọi RestrictionTarget.fromElement() với một phần tử bạn chọn làm dữ liệu đầu vào.

// Associate captureTarget with a new RestrictionTarget
const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

Sau đó, hãy gọi restrictTo() trên kênh video với RestrictionTarget làm đầu vào. Sau khi lời hứa cuối cùng được phân giải, tất cả các khung hình tiếp theo sẽ bị hạn chế.

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

// Enjoy! Transmit remotely.

Tìm hiểu chuyên sâu

Phát hiện tính năng

Để kiểm tra xem RestrictionTarget.fromElement() có được hỗ trợ hay không, hãy sử dụng:

if ("RestrictionTarget" in self && "fromElement" in RestrictionTarget) {
  // Deriving a restriction target is supported.
}

Rút ra một mục tiêu hạn chế

Tập trung vào Phần tử có tên là captureTarget. Để lấy RestrictionTarget từ đó, hãy gọi RestrictionTarget.fromElement(captureTarget). Lời hứa được trả về sẽ được giải quyết bằng đối tượng RestrictionTarget mới nếu thành công. Nếu không, thuộc tính này sẽ bị từ chối nếu bạn tạo số lượng đối tượng RestrictionTarget không hợp lý.

const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

Không giống như Phần tử, đối tượng RestrictionTarget có thể chuyển đổi tuần tự. Ví dụ: có thể truyền dữ liệu này đến một tài liệu khác bằng cách sử dụng Window.postMessage().

Hạn chế

Khi quay một thẻ, bản nhạc video sẽ hiển thị restrictTo(). Khi ghi lại thẻ hiện tại, bạn có thể gọi restrictTo() bằng null hoặc bất kỳ RestrictionTarget nào bắt nguồn từ một Phần tử trong thẻ hiện tại.

Các lệnh gọi đến restrictTo(restrictionTarget) biến đổi đoạn video thành ảnh chụp captureTarget, như thể nó được vẽ độc lập với phần còn lại của DOM. Mọi thành phần con cháu của captureTarget cũng được thu thập; đồng cấp của captureTarget sẽ bị loại khỏi quá trình chụp. Kết quả là mọi khung hình được phân phối trên kênh sẽ hiển thị như thể chúng đã bị cắt theo đường viền của captureTarget, đồng thời mọi nội dung bị che khuất và bị che khuất đều sẽ bị xoá.

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

Các lệnh gọi đến restrictTo(null) sẽ chuyển bản nhạc về trạng thái ban đầu.

// Stop restricting.
await track.restrictTo(null);

Nếu lệnh gọi đến restrictTo() thành công, Promise được trả về sẽ được phân giải khi có thể đảm bảo rằng tất cả khung hình video tiếp theo sẽ bị giới hạn ở captureTarget.

Nếu không thành công, Lời hứa sẽ bị từ chối. Lệnh gọi không thành công đến restrictTo() sẽ do một trong các lý do sau đây:

  • Nếu restrictionTarget được tạo trong một thẻ không phải trong thẻ đang được ghi. (Xin lưu ý rằng khi sử dụng nút "chia sẻ thẻ này", người dùng có thể thay đổi thẻ được ghi lại vào một thời điểm nhất định.)
  • Nếu restrictionTarget được bắt nguồn từ một Phần tử không còn tồn tại.
  • Nếu bản nhạc đó có bản sao. (Xem vấn đề 1509418.)
  • Nếu bản nhạc hiện tại không phải là bản nhạc video tự chụp.
  • Nếu Phần tử tạo ra restrictionTarget không đủ điều kiện để áp dụng quy định hạn chế.

Những điều cần cân nhắc khi tự chụp ảnh

Khi một ứng dụng gọi getDisplayMedia() và người dùng chọn chụp thẻ của riêng ứng dụng đó, chúng ta gọi đó là "tự chụp".

Phương thức restrictTo() hiển thị trên mọi bản video được chụp bằng thẻ, chứ không chỉ để tự quay. Tuy nhiên, tính năng Chụp phần tử hiện chỉ được bật để tự chụp. Do đó, nên kiểm tra xem người dùng có chọn thẻ hiện tại hay không trước khi cố gắng hạn chế kênh. Bạn có thể thực hiện việc này bằng cách sử dụng Tên người dùng để ghi lại. Bạn cũng có thể yêu cầu trình duyệt nhắc người dùng tự chụp ảnh bằng preferCurrentTab.

Sự minh bạch

Khung video mà ứng dụng nhận được đến getDisplayMedia() không bao gồm kênh alpha. Nếu ứng dụng đặt mục tiêu chụp trong suốt một phần, việc loại bỏ kênh alpha có thể dẫn đến một số hậu quả sau:

  • Màu sắc có thể thay đổi. Các phần tử mục tiêu trong suốt một phần được vẽ trên nền sáng có thể trông tối hơn khi kênh alpha bị xoá và những phần tử được vẽ trên nền tối có thể trông sáng hơn.
  • Các màu không hiển thị hoặc không nhìn thấy được đối với người dùng khi kênh alpha được đặt thành mức tối đa, sẽ xuất hiện sau khi kênh alpha bị xoá. Ví dụ: điều này có thể dẫn đến các vùng màu đen không mong muốn trong các khung đã chụp, nếu các phần trong suốt có mã RGBA rgba(0, 0, 0, 0).
Ảnh chụp màn hình kết quả mục tiêu chụp trong suốt không phải là hình chữ nhật.
Luồng video đích chụp trong suốt không phải hình chữ nhật (bên phải) là một hình chữ nhật nền đen có chứa một vòng tròn màu xanh dương mờ.

Mục tiêu chụp không đủ điều kiện

Bạn luôn có thể bắt đầu giới hạn kênh ở bất kỳ mục tiêu thu thập hợp lệ nào. Tuy nhiên, khung hình sẽ không được tạo trong một số điều kiện nhất định, chẳng hạn như nếu phần tử hoặc đối tượng cấp trên là display:none. Lý do chung là hạn chế chỉ áp dụng cho một phần tử bao gồm một vùng hình chữ nhật, nhất quán, hai chiều, có pixel có thể được xác định một cách hợp lý để tách biệt với mọi phần tử mẹ hoặc đồng cấp.

Một lưu ý quan trọng cần cân nhắc để đảm bảo phần tử đủ điều kiện bị hạn chế là phần tử đó phải tạo ngữ cảnh xếp chồng riêng. Để đảm bảo điều này, bạn có thể chỉ định thuộc tính CSS cách ly bằng cách đặt thuộc tính này thành isolate.

<div id="captureTarget" style="isolation: isolate;"></iframe>

Xin lưu ý rằng phần tử đích có thể chuyển đổi giữa trạng thái đủ điều kiện và không đủ điều kiện bị hạn chế tại bất kỳ thời điểm nào tuỳ ý, chẳng hạn như khi ứng dụng thay đổi các thuộc tính CSS. Ứng dụng phải sử dụng các mục tiêu thu thập hợp lý và tránh thay đổi thuộc tính của các mục tiêu đó một cách đột ngột. Nếu phần tử đích không đủ điều kiện, thì các khung hình mới sẽ không được phát trên kênh cho đến khi phần tử mục tiêu đó trở lại đủ điều kiện để hạn chế.

Bật tính năng Chụp phần tử

API Chụp phần tử có trong Chrome trên máy tính sau cờ Thu thập phần tử và có thể được bật tại chrome://flags/#element-capture.

Tính năng này cũng sẽ bắt đầu chạy bản dùng thử theo nguyên gốc của Chrome 121 trên máy tính. Theo đó, nhà phát triển có thể bật tính năng này cho khách truy cập vào 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 Làm quen với bản dùng thử theo nguyên gốc để biết thêm thông tin về bản dùng thử theo nguyên gốc.

Bảo mật và quyền riêng tư

Để tìm hiểu các yếu tố đánh đổi về bảo mật, hãy xem phần Các cân nhắc về quyền riêng tư và bảo mật trong phần thông số kỹ thuật của tính năng Thu thập phần tử.

Trình duyệt Chrome vẽ một đường viền màu xanh dương xung quanh cạnh của các thẻ được chụp.

Bản minh hoạ

Bạn có thể chơi với Element Capture bằng cách chạy bản minh hoạ trên Glitch. Hãy chắc chắn kiểm tra mã nguồn.

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 Thu thập phần tử.

Hãy cho chúng tôi biết về thiết kế

Có điều gì đó về tính năng Chụp ảnh khu vực không hoạt động như bạn 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?

  • Báo cáo 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ề 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 trong quá trình 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?

  • Báo cáo lỗi tại https://new.crbug.com. Hãy nhớ cung cấp nhiều thông tin chi tiết nhất có thể và hướng dẫn đơn giản để tái tạo. Glitch rất hữu ích khi chia sẻ các bản dựng lại nhanh chóng và dễ dàng.

Thư cảm ơn

Ảnh của Paul Skorupskas trên Unsplash