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 =...