WebCodecs 4K Encode Perf

Change encoderFPS to find max (where the queue can stay close to zero)

by dustinkerstein

HTML

<html>
  <head>
  </head>
  <body>
    <div>
        <h2 id="debug"></h2>
        <p id="text"></p>
    </div>
  </body>
</html>

CSS

body {
  background-color: #1f2227;
}
div {
  max-width: 80vw;
  text-align: center;
  word-break: break-all;
  color: white;
  position: absolute;
  top: 50%;
  left: 50%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

JavaScript

// Change encoderFPS to find max (where the queue can stay close to zero)
// Note that the console output is only showing 1 out of every 10 EncodedVideoChunks
//////////////////////
const encoderFPS = 30;
const width = 3840;
const height = 2160;
//////////////////////
const debug = document.getElementById('debug');
const text = document.getElementById('text');
const pixelSize = 4;
const init = {
  timestamp: 0,
  codedWidth: width,
  codedHeight: height,
  format: 'RGBA'
};
const data = new Uint8Array(init.codedWidth * init.codedHeight * pixelSize);
const config = {
  codec: "avc1.42001E",
  width: width,
  height: height,
  bitrate: 10000,
  framerate: 1,
  /* hardwareAcceleration: "prefer-software", */
  hardwareAcceleration: "prefer-hardware",
  latencyMode: "quality",
  bitrateMode: "constant"
};
var count = 0;


for (let x = 0; x < init.codedWidth; x++) {
  for (let y = 0; y < init.codedHeight; y++) {
    let offset = (y * init.codedWidth + x) * pixelSize;
    data[offset] = 0xFF; // Red
    data[offset + 1] = 0x00; // Green
    data[offset + 2] = 0x00; // Blue
    data[offset + 3] = 0x0FF; // Alpha
  }
}

const encoder = new VideoEncoder({
  output: e => {
  	if (count++ % 10 == 0 || count == 1) console.log(e);
  },
  error: e => console.log(e)
});

/* const canvas = document.createElement('canvas'); */
/* const frame = new VideoFrame(canvas, { timestamp: 0 }); */
var t0 = 0
const frame = new VideoFrame(data, init);
console.log("DUSTIN " + (performance.now() - t0));

function encodeLoop() {
  encoder.encode(frame, {
    keyFrame: false
  });
}

function debugLoop() {
  debug.innerHTML = "encodeQueueSize: " + encoder.encodeQueueSize;
}

VideoEncoder.isConfigSupported(config).then(response => {
  if (response.supported) {
  	console.log("Encoder config supported");
  	console.log(response.config);
    encoder.configure(response.config);
    setInterval(encodeLoop, 1000 / encoderFPS);
    setInterval(debugLoop, 1000 / 10);
  } else {
    debug.innerHTML =...