WebCodecs API

Note: This feature is available in Dedicated Web Workers.

WebCodecs API cung cấp cho nhà phát triển web quyền truy cập cấp thấp vào các khung hình riêng lẻ của luồng video và các đoạn âm thanh. API này hữu ích cho các ứng dụng web cần kiểm soát hoàn toàn cách xử lý phương tiện, chẳng hạn như trình chỉnh sửa video hoặc âm thanh, và hội nghị truyền hình.

Khái niệm và cách dùng

Nhiều Web API sử dụng codec phương tiện bên trong. Ví dụ, Web Audio APIWebRTC API. Tuy nhiên các API này không cho phép nhà phát triển làm việc với các khung hình riêng lẻ của luồng video và các đoạn âm thanh hoặc video được mã hóa chưa pha trộn.

Nhà phát triển web thường dùng WebAssembly để khắc phục hạn chế này và làm việc với codec phương tiện trong trình duyệt. Tuy nhiên điều này đòi hỏi băng thông bổ sung để tải xuống các codec đã có trong trình duyệt, làm giảm hiệu suất và hiệu quả năng lượng, đồng thời tăng thêm gánh nặng phát triển.

WebCodecs API cung cấp quyền truy cập vào các codec đã có trong trình duyệt. API cho phép truy cập vào các khung hình video thô, đoạn dữ liệu âm thanh, bộ giải mã hình ảnh, bộ mã hóa và giải mã âm thanh và video.

Mô hình xử lý

WebCodecs API dùng mô hình xử lý bất đồng bộ. Mỗi phiên bản của bộ mã hóa hoặc giải mã duy trì một hàng đợi xử lý nội bộ, độc lập. Khi đưa vào hàng đợi một lượng lớn công việc, điều quan trọng là phải ghi nhớ mô hình này.

Các phương thức có tên configure(), encode(), decode(), và flush() hoạt động bất đồng bộ bằng cách thêm thông điệp điều khiển vào cuối hàng đợi, trong khi các phương thức có tên reset()close() đồng bộ hủy bỏ tất cả công việc đang chờ và xóa hàng đợi xử lý. Sau reset(), có thể đưa thêm công việc vào hàng đợi sau khi gọi configure(), nhưng close() là thao tác vĩnh viễn.

Các phương thức có tên flush() có thể được dùng để chờ hoàn thành tất cả công việc đang chờ tại thời điểm flush() được gọi. Tuy nhiên, thường chỉ nên gọi nó sau khi tất cả công việc mong muốn đã được đưa vào hàng đợi. Phương thức này không nhằm mục đích buộc tiến trình ở các khoảng thời gian đều đặn. Gọi nó không cần thiết sẽ ảnh hưởng đến chất lượng bộ mã hóa và khiến bộ giải mã yêu cầu đầu vào tiếp theo phải là khung hình chính.

Tách kênh (Demuxing)

Hiện tại không có API để tách kênh container phương tiện. Nhà phát triển làm việc với phương tiện được đóng gói sẽ cần tự triển khai hoặc dùng thư viện bên thứ ba. Ví dụ, MP4Box.js hoặc jswebm có thể được dùng để tách kênh dữ liệu âm thanh và video thành các đối tượng EncodedAudioChunkEncodedVideoChunk tương ứng.

Giao diện

AudioDecoder

Giải mã các đối tượng EncodedAudioChunk.

VideoDecoder

Giải mã các đối tượng EncodedVideoChunk.

AudioEncoder

Mã hóa các đối tượng AudioData.

VideoEncoder

Mã hóa các đối tượng VideoFrame.

EncodedAudioChunk

Đại diện cho các byte âm thanh được mã hóa theo codec cụ thể.

EncodedVideoChunk

Đại diện cho các byte video được mã hóa theo codec cụ thể.

AudioData

Đại diện cho dữ liệu âm thanh chưa mã hóa.

VideoFrame

Đại diện cho một khung hình của dữ liệu video chưa mã hóa.

VideoColorSpace

Đại diện cho không gian màu của một khung hình video.

ImageDecoder

Giải nén và giải mã dữ liệu hình ảnh, cung cấp quyền truy cập vào chuỗi khung hình trong ảnh động.

ImageTrackList

Đại diện cho danh sách các track có trong hình ảnh.

ImageTrack

Đại diện cho một track hình ảnh riêng lẻ.

Ví dụ

Trong ví dụ sau, các khung hình được trả về từ MediaStreamTrackProcessor, sau đó được mã hóa. Xem ví dụ đầy đủ và đọc thêm trong bài viết Video processing with WebCodecs.

js
let frameCounter = 0;
const track = stream.getVideoTracks()[0];
const mediaProcessor = new MediaStreamTrackProcessor(track);
const reader = mediaProcessor.readable.getReader();
while (true) {
  const result = await reader.read();
  if (result.done) break;
  let frame = result.value;
  if (encoder.encodeQueueSize > 2) {
    // Too many frames in flight, encoder is overwhelmed
    // let's drop this frame.
    frame.close();
  } else {
    frameCounter++;
    const insertKeyframe = frameCounter % 150 === 0;
    encoder.encode(frame, { keyFrame: insertKeyframe });
    frame.close();
  }
}

Xem thêm