177 lines
4.9 KiB
JavaScript
177 lines
4.9 KiB
JavaScript
var errors = {
|
|
"mediainfo" : "Couldn't parse mediainfo. Check that it is a valid video mediainfo which contains zones.",
|
|
"frames" : "Please check that the frame count you entered is correct, and the mediainfo is valid.",
|
|
"high" : "One of the frames you inputted was either too high or too low.",
|
|
"check" : "Please enter a valid, comma-separated list of frames to check, without spaces.",
|
|
"crash" : "Stupidly large frame numbers can crash your browser.",
|
|
"unknown" : "An unknown error occured.",
|
|
};
|
|
|
|
function getBaseRate(settings) {
|
|
for (var i = 0; i < settings.length; i++) {
|
|
var setting = settings[i];
|
|
if (/^crf=/.test(setting)) {
|
|
return ["crf", setting.replace(/^crf=/, "")];
|
|
} else if (/^bitrate=/.test(setting)) {
|
|
return ["bitrate", setting.replace(/^bitrate=/, "")];
|
|
}
|
|
}
|
|
};
|
|
|
|
function parseZones(zones, base, numframes) {
|
|
numframes = parseInt(numframes);
|
|
var frames = new Array(numframes);
|
|
for (var i = 0; i < zones.length; i++) {
|
|
var zone = zones[i].split(",");
|
|
if (parseInt(zone[1]) > numframes) {
|
|
return null;
|
|
}
|
|
|
|
// loop over each part of the zone
|
|
for (var j = 2; j < zone.length; j++) {
|
|
if (/^crf=/.test(zone[j])) {
|
|
var crf = zone[j].replace(/^crf=/, "");
|
|
frames.fill(["crf", crf], parseInt(zone[0]), parseInt(zone[1])+1);
|
|
} else if (/^b=/.test(zone[j])) {
|
|
var b = zone[j].replace(/^b=/, "");
|
|
frames.fill(["b", b], parseInt(zone[0]), parseInt(zone[1])+1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// fill in all the unfilled frames
|
|
for (var i = 0; i < frames.length; i++) {
|
|
if (!frames[i]) {
|
|
frames[i] = base;
|
|
}
|
|
}
|
|
|
|
return frames;
|
|
};
|
|
|
|
function checkZones(mediainfo, numframes, check) {
|
|
// Check number of frames
|
|
if (numframes > 1000000) {
|
|
return errors["crash"];
|
|
}
|
|
|
|
// Extract encode settings
|
|
var lines = mediainfo.split('\n');
|
|
var settings;
|
|
for (var i = 0; i < lines.length; i++) {
|
|
if (/^Encoding\ settings\ :\ /.test(lines[i])) {
|
|
// This is the line we want
|
|
settings = lines[i].replace(/^Encoding\ settings\ :\ /, "").split(" / ");
|
|
}
|
|
}
|
|
if (!settings) {
|
|
return errors["mediainfo"];
|
|
}
|
|
|
|
// Find base CRF or bitrate
|
|
var base = getBaseRate(settings);
|
|
if (!base) {
|
|
return errors["mediainfo"];
|
|
}
|
|
|
|
var frames;
|
|
for (var i = 0; i < settings.length; i++) {
|
|
var setting = settings[i];
|
|
if (/^zones=/.test(setting)) {
|
|
frames = parseZones(setting.replace(/^zones=/, "").split("/"), base, numframes);
|
|
}
|
|
}
|
|
if (!frames) {
|
|
return errors["frames"];
|
|
}
|
|
|
|
// Check input
|
|
var to_check = check.split(",");
|
|
for (var i = 0; i < to_check.length; i++) {
|
|
if (/^[0-9]+$/.test(to_check[i])) {
|
|
to_check[i] = parseInt(to_check[i]);
|
|
} else {
|
|
return errors["check"];
|
|
}
|
|
}
|
|
|
|
// Check each frame
|
|
var results = {
|
|
frames : {},
|
|
zones : {},
|
|
};
|
|
for (var i = 0; i < to_check.length; i++) {
|
|
var frame = to_check[i];
|
|
if (!frames[frame]) {
|
|
return errors["high"];
|
|
}
|
|
results["frames"][frame] = frames[frame][0] + "=" + frames[frame][1];
|
|
}
|
|
|
|
// Calculate percentages
|
|
var frequencies = new Object;
|
|
for (var i = 0; i < frames.length; i++) {
|
|
var frame = frames[i];
|
|
if (frame[0] != base[0] || frame[1] != base[1]) {
|
|
// does the frequencies object already have an entry for this rate?
|
|
if (frequencies[frame[0] + "=" + frame[1]]) {
|
|
// yes
|
|
frequencies[frame[0] + "=" + frame[1]]++;
|
|
} else {
|
|
// no
|
|
frequencies[frame[0] + "=" + frame[1]] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (var rate in frequencies) {
|
|
if (!frequencies.hasOwnProperty(rate)) continue;
|
|
results["zones"][rate] = parseInt(frequencies[rate]) / parseInt(numframes) * 100;
|
|
}
|
|
|
|
// sorting
|
|
var rates = new Array;
|
|
for (var rate in results["zones"]) {
|
|
if (!results["zones"].hasOwnProperty(rate)) continue;
|
|
rates.push(rate);
|
|
}
|
|
rates.sort(
|
|
function(a, b) {
|
|
c = [a, b].map(
|
|
function(x) {
|
|
return parseFloat(x.replace(/^(crf|b)=/, ""));
|
|
}
|
|
);
|
|
return c[0] - c[1];
|
|
}
|
|
);
|
|
|
|
// Build report
|
|
var output = "Base " + base[0] + ": " + base[1] + "\n\n";
|
|
|
|
for (var frame in results["frames"]) {
|
|
if (!results["frames"].hasOwnProperty(frame)) continue;
|
|
output += "Frame " + frame + ": " + results["frames"][frame] + "\n";
|
|
}
|
|
output += "\n";
|
|
|
|
for (var zone in results["zones"]) {
|
|
if (!results["zones"].hasOwnProperty(zone)) continue;
|
|
output += zone + ": " + parseFloat(results["zones"][zone]).toFixed(3) + "% (" + frequencies[zone] + " frames)\n";
|
|
}
|
|
|
|
return output;
|
|
};
|
|
|
|
function update() {
|
|
var mediainfo = document.getElementById("mediainfo").value;
|
|
var frames = document.getElementById("frames").value;
|
|
var check = document.getElementById("check").value;
|
|
|
|
if (mediainfo && frames && check) {
|
|
document.getElementById("results").value = checkZones(mediainfo, frames, check);
|
|
} else {
|
|
document.getElementById("results").value = "";
|
|
}
|
|
};
|