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";
...