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 = ""; } };