Skip to content

Instantly share code, notes, and snippets.

@rubyu
Created December 15, 2018 13:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rubyu/bebedb90f8a5c707914f177b8c714e44 to your computer and use it in GitHub Desktop.
Save rubyu/bebedb90f8a5c707914f177b8c714e44 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name HIDIVE Screenshot
// @version 1.0
// @description Tested on Chrome 64 and Firefox 61 with Tampermonkey 4.7.
// @include /^https?://www\.hidive\.com/stream/.*$/
// @require http://html2canvas.hertzen.com/dist/html2canvas.js
// @grant GM_notification
// ==/UserScript==
(function() {
'use strict';
// The trigger key to capture screenshot.
const invocationKey = "F9";
// Modifier keys required when the trigger key to be activated. (acceptable values: "alt", "ctrl", "shift", "meta")
const invocationKeyModifiers = [];
// Mime type of output image file. (acceptable values: "image/png", "image/jpeg", "image/webp")
const outputMimeType = "image/png";
// Quality argument indicates the quality of output image file. (range: 0.0 to 1.0; 1.0 is best and 0.0 is worst)
// Note: png encoder won't be effected by this parameter because it is a lossless format.
const outputQuality = 0.9;
// Add episode title to the filename if true.
const outputEpisodeTitle = true;
// Set to true if you need to pause the video to capture it precisely.
const pausePlaybackBeforeCapturing = false;
// Set to true if you need to focus the player element to control by keys assigned to it.
const focusPlayerOnLoad = true;
// Set to true if you need to focus the player element after capturing.
const focusPlayerAfterCapturing = true;
// Settings for notification feature.
const notificationEnabled = true;
const notificationTimeout = 2000;
const appName = "HIDIVE Screenshot";
function saveCavnasAsImageFile(canvas, filename) {
canvas.toBlob(function (blob) {
const link = document.createElement("a");
link.download = filename;
link.href = window.URL.createObjectURL(blob);
dispatchClickEvent(link);
}, outputMimeType, outputQuality);
}
function dispatchClickEvent(target) {
const evnt = document.createEvent("MouseEvents");
evnt.initMouseEvent("click", {
view: window,
bubbles: true,
cancelable: true
});
target.dispatchEvent(evnt);
}
function parseSeconds(seconds) {
const sec = Math.floor(seconds);
const msec = Math.floor((seconds - sec) * 1000);
const minute = Math.floor(sec / 60);
const hour = Math.floor(minute / 60);
return {
msec: msec,
sec: sec % 60,
minute: minute % 60,
hour: hour
};
}
function lzerofill(obj, minLength) {
const str = obj.toString();
return ("0".repeat(minLength) + str).slice(-Math.max(minLength, str.length));
}
function secondsToCurrentTimeString(seconds) {
const ct = parseSeconds(seconds);
return lzerofill(ct.hour, 2) + "_" + lzerofill(ct.minute, 2) + "_" + lzerofill(ct.sec, 2) + "." + lzerofill(ct.msec, 3);
}
function getPrefferedExtension() {
if (outputMimeType == "image/png") return "png";
else if (outputMimeType == "image/jpeg") return "jpg";
else if (outputMimeType == "image/webp") return "webp";
else return outputMimeType.split("/")[1];
}
function removeQuotes(str) {
return str.replace("“", "").replace("”", "");
}
function getPrefferedFileName(currentTime) {
const title = document.querySelector(".bottom-gutter-15 h1 a").textContent;
const descriptions = document.querySelectorAll("#StreamTitleDescription h2");
const seasonAndEpisode = descriptions[0].textContent.replace(/^ /, "").replace(/ \|.+/, "");
const episodeTitle = descriptions[1].textContent;
const ct = secondsToCurrentTimeString(currentTime);
const ext = getPrefferedExtension();
return title + " [" + seasonAndEpisode + "] " + episodeTitle + " [" + ct + "]." + ext;
}
if (focusPlayerOnLoad) {
window.addEventListener("load", function(evnt) {
const player = document.getElementById("rmpPlayer");
player.focus();
});
}
document.addEventListener("keydown", function(evnt) {
if (evnt.key != invocationKey ||
invocationKeyModifiers.indexOf("alt") >= 0 && !evnt.altKey ||
invocationKeyModifiers.indexOf("ctrl") >= 0 && !evnt.ctrlKey ||
invocationKeyModifiers.indexOf("shift") >= 0 && !evnt.shiftKey ||
invocationKeyModifiers.indexOf("meta") >= 0 && !evnt.metaKey) {
return;
}
try {
console.log(appName + " was invoked");
const player = document.getElementById("rmpPlayer");
const action = player;
const vs = player.getElementsByClassName("rmp-video")[0];
const sub = player.getElementsByClassName("rmp-cc-area")[0];
if (pausePlaybackBeforeCapturing) {
dispatchClickEvent(action);
}
const w = vs.clientWidth;
const h = vs.clientHeight;
console.log("width: " + w);
console.log("height: " + h);
const canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
ctx.drawImage(vs, 0, 0, w, h);
html2canvas(sub, {backgroundColor: null}).then(function(sub_canvas) {
if (sub_canvas.width > 0 && sub_canvas.height > 0) {
//ctx.drawImage(sub_canvas, 0, sub.offsetTop, w, h);
ctx.drawImage(sub_canvas, 0, 0, w, h);
}
const filename = getPrefferedFileName(vs.currentTime);
saveCavnasAsImageFile(canvas, filename);
const successMessage = "Screenshot was saved to \"" + filename + "\"";
console.log(successMessage);
if (notificationEnabled) {
GM_notification({
image: "http://d10xkldqejj5hr.cloudfront.net/misc/HD_Logo_PR.png",
text: successMessage,
timeout: notificationTimeout
});
}
if (focusPlayerAfterCapturing) {
player.focus();
}
});
} catch (ex) {
const errorMessage = "An error has occurred: " + ex.toString();
console.log(errorMessage);
if (notificationEnabled) {
GM_notification({
image: "http://d10xkldqejj5hr.cloudfront.net/misc/HD_Logo_PR.png",
title: "Oops!",
text: errorMessage,
timeout: 10000
});
}
}
// Cancel the key down event.
return false;
});
document.addEventListener("keyup", function(evnt) {
if (evnt.key != invocationKey ||
invocationKeyModifiers.indexOf("alt") >= 0 && !evnt.altKey ||
invocationKeyModifiers.indexOf("ctrl") >= 0 && !evnt.ctrlKey ||
invocationKeyModifiers.indexOf("shift") >= 0 && !evnt.shiftKey ||
invocationKeyModifiers.indexOf("meta") >= 0 && !evnt.metaKey) {
return;
}
// Cancel the key up event.
return false;
});
console.log(appName + " was loaded");
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment