You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Renders a "YouTube Stats for Nerds" overlay on top of an image.
* This simulates the YouTube audio volume normalization statistics for various codecs.
*
* @param {HTMLImageElement} originalImg - The source image to draw the overlay on (e.g. video screenshot).
* @param {string} audioFormat - The format to simulate ("Opus", "Mp2", "Mp3", "Ac3").
* @param {number} volumePercent - The player volume percentage (e.g. 100).
* @param {number} contentLoudnessDb - The original content loudness relative to reference (e.g. 2.5).
* @returns {HTMLCanvasElement} - Canvas element containing the processed image.
*/
function processImage(originalImg, audioFormat = "Opus", volumePercent = 100, contentLoudnessDb = 2.5) {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// Maintain original image dimensions
canvas.width = originalImg.width;
canvas.height = originalImg.height;
// Draw the underlying video screenshot (image)
ctx.drawImage(originalImg, 0, 0);
// Auto-scale the "Stats for Nerds" UI based on the image width
// Assuming standard 1280px width for a scaling factor of 1.0
const scale = Math.max(0.5, canvas.width / 1280);
const fontSize = Math.round(13 * scale);
const padding = Math.round(16 * scale);
const gap = Math.round(30 * scale);
const lineHeight = Math.round(22 * scale);
// Determine exact audio formatting string based on the tool's specifications
let audioStatStr = audioFormat;
const lowerFmt = audioFormat.toLowerCase();
if (lowerFmt === "opus") {
audioStatStr = "Opus (-26.0dB/-14.0dB)";
} else if (lowerFmt === "mp2") {
audioStatStr = "Mp2 (-19.0dB/-14.0dB)";
} else if (lowerFmt === "mp3") {
audioStatStr = "Mp3 (-19.0dB/-14.0dB)";
} else if (lowerFmt === "ac3") {
audioStatStr = "Ac3";
}
// Mathematically resolve how YouTube calculates the "Normalized" volume level
const loudness = parseFloat(contentLoudnessDb) || 0;
const volume = parseFloat(volumePercent) || 100;
// If content loudness is > 0, YouTube applies a negative gain to normalize volume
// Gain mapping using inverse log 10 formulation: multiplier = 10^(-dB/20)
let normalizedVol = volume;
if (loudness > 0) {
let gainMultiplier = Math.pow(10, -loudness / 20);
normalizedVol = Math.round(volume * gainMultiplier);
}
const loudnessStr = loudness > 0 ? `+${loudness}` : `${loudness}`;
// Assemble the mock stats array representing the "Stats for nerds" pane
const stats = [
["Video ID / sCPN", "xYz123aBcDe / ABCD-EFGH-IJKL"],
["Viewport / Frames", `${canvas.width}x${canvas.height} / 0 dropped of 1245`],
["Current / Optimal Res", `${canvas.width}x${canvas.height}@60 / ${canvas.width}x${canvas.height}@60`],
["Volume / Normalized", `${volume}% / ${normalizedVol}% (content loudness ${loudnessStr}dB)`],
["Codecs", `vp09.00.51.08.01.27.x / ${lowerFmt}`],
["Audio Format Info", audioStatStr],
["Host", "r1---sn-axq7sn7e.googlevideo.com"],
["Connection Speed", "45234 Kbps"],
["Network Activity", "0 KB"],
["Buffer Health", "14.53 s"]
];
ctx.font = `${fontSize}px "Roboto", "Segoe UI", Arial, sans-serif`;
// Calculate dynamic box width based on measured text sizes
let maxLeftWidth = 0;
let maxRightWidth = 0;
stats.forEach(line => {
maxLeftWidth = Math.max(maxLeftWidth, ctx.measureText(line[0]).width);
maxRightWidth = Math.max(maxRightWidth, ctx.measureText(line[1]).width);
});
const closeBtnWidth = ctx.measureText(" x ").width;
const boxWidth = padding * 2 + maxLeftWidth + gap + maxRightWidth + closeBtnWidth;
const boxHeight = padding * 2 + stats.length * lineHeight;
// Position of the overlay box
const boxX = padding;
const boxY = padding;
// Draw semi-transparent dark grey background
ctx.fillStyle = "rgba(0, 0, 0, 0.70)";
if (typeof ctx.roundRect === "function") {
ctx.beginPath();
ctx.roundRect(boxX, boxY, boxWidth, boxHeight, 4 * scale);
ctx.fill();
} else {
ctx.fillRect(boxX, boxY, boxWidth, boxHeight);
}
// Draw Stats Text
ctx.textBaseline = "middle";
stats.forEach((line, i) => {
const textY = boxY + padding + (i * lineHeight) + (lineHeight / 2);
// Characteristic left-side gray labels
ctx.fillStyle = "rgba(255, 255, 255, 0.65)";
ctx.textAlign = "left";
ctx.fillText(line[0], boxX + padding, textY);
// Right-side solid white values
ctx.fillStyle = "rgba(255, 255, 255, 1.0)";
ctx.fillText(line[1], boxX + padding + maxLeftWidth + gap, textY);
});
// Draw "X" Close Button on top right of the box
ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
ctx.textAlign = "right";
ctx.fillText("x", boxX + boxWidth - padding, boxY + padding + (lineHeight / 2));
return canvas;
}
Apply Changes