WebCodecs 4K Encode Perf

With pre-allocated array of VideoFrames. 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)
const encoderFPS = 65;
const width = 3840;
const height = 2160;
const fps = 1;
const numFrames = 200;
const pixelSize = 4;
const frameArray = [];
const encodeQueueSizeArray = [];
const debug = document.getElementById('debug');
const text = document.getElementById('text');
var encodeSetInterval;
var encoderFlushed;

const encoder = new VideoEncoder({
  output: e => console.log(e),
  error: e => console.log(e)
});

const init = {
  duration: (1000000 / fps),
  timestamp: 0,
  codedWidth: width,
  codedHeight: height,
  format: 'RGBA',
  alpha: 'discard'
};

const config = {
  codec: "avc1.42001E",
  width: width,
  height: height,
  bitrate: 10000,
  framerate: fps,
  // hardwareAcceleration: "prefer-software",
  hardwareAcceleration: "prefer-hardware",
  latencyMode: "quality",
  bitrateMode: "constant"
};

const data = new Uint8Array(init.codedWidth * init.codedHeight * pixelSize);

function captureQueue() {
  encodeQueueSizeArray.push(encoder.encodeQueueSize);
  text.innerHTML = "encodeQueueSize: " + encoder.encodeQueueSize;
}

function encodeLoop() {
  const frame = frameArray.shift()
  if (frame) {
    console.log(frame)
    encoder.encode(frame, {
      keyFrame: false
    });
    frame.close();
    captureQueue();
  } else if (!encoderFlushed) {
    encoderFlushed = true;
    clearInterval(encodeSetInterval);
    encoder.flush().then(response => {
      const last = encodeQueueSizeArray[encodeQueueSizeArray.length - 1];
      encodeQueueSizeArray.sort(function(a, b) {
        return a - b;
      });
      const min = encodeQueueSizeArray[0];
      const max = encodeQueueSizeArray[encodeQueueSizeArray.length - 1];
      const average = (encodeQueueSizeArray.reduce((sum, current) => sum + current)) / encodeQueueSizeArray.length;
      const message = "encodeQueueSize average: " + average.toFixed(0) + " min: " + min + " max: " + max + " last: " + last;
      debug.innerHTML = "Finished";
...