返回首頁 

Greasy Fork is available in English.

Tumblr HD Video Download Buttons

Automatically redirect Tumblr video links to raw HD versions, and display a download button below videos


安装此脚本?
作者推荐脚本

您可能也喜欢Tumblr Images to HD Redirector


安装此脚本
// ==UserScript==// @name         Tumblr HD Video Download Buttons// @namespace    TumblrVideoReszr// @description  Automatically redirect Tumblr video links to raw HD versions, and display a download button below videos// @version      3.1// @author       Kai Krause <[email protected]>// @match        http://*.tumblr.com/*// @match        https://*.tumblr.com/*// @run-at       document-start// @grant        GM_xmlhttpRequest// @connect      tumblr.com// ==/UserScript==// Typical Video URL Patterns:// https://vt.media.tumblr.com/tumblr_ID_NUM.mp4// https://vtt.tumblr.com/tumblr_ID_NUM.mp4// https://vt.tumblr.com/tumblr_ID_NUM.mp4// https://ve.tumblr.com/tumblr_ID_NUM.mp4var loc = location.toString();// ----------------------------------------// DIRECT MP4 URLS// ----------------------------------------function redirectToHD() {// Check that the URL is a ~.mp4if (!loc.endsWith('.mp4')) return;var lowQuality = /[$_]\d*.mp4$/;// Do not redirect if already HDif (!loc.match(lowQuality)) return;// Change to HDloc = loc.replace(lowQuality, '.mp4');// If the URL is HTTP, change it to HTTPSif (!loc.startsWith('https://')) {loc = loc.replace(/^http/, 'https');}// Redirect to the HD videolocation.replace(loc);}redirectToHD();// ----------------------------------------// DOWNLOAD BUTTON STYLE// ----------------------------------------// Create the button stylevar downloadButtonStyle = document.createElement("style");downloadButtonStyle.innerText = ".videoDownloadButtonStyle_kk{display:table !important; width:100% !important; padding:6px !important; border:2px solid #979EA8 !important; background-color:#2F3D51 !important; color: #979EA8 !important; line-height: 100% !important; font-family:'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif; font-weight: 600 !important; text-align: center !important; font-style: normal !important; text-decoration: none !important} .videoDownloadButtonStyle_kk:hover{color:#F5F5F5 !important;}";document.head.appendChild(downloadButtonStyle);// ----------------------------------------// HELPER FUNCTIONS// ----------------------------------------// Dynamic function wrapperfunction dynamicScroll (f) {window.addEventListener("scroll", (function(){f();}), false);}function fixVideoUrl(videoURL) {videoURL = videoURL.replace(/\d+(?=\.media)/, 'vt');videoURL = videoURL.replace(/[^_]*$/, '');videoURL = videoURL.replace(/_$/, '.mp4');return videoURL;}function createBtn(videoURL) {// Create the buttonvar downloadButton = document.createElement('a');downloadButton.innerText = 'Download This Video (HD)';// Set and style the download buttondownloadButton.setAttribute('class', 'videoDownloadButtonStyle_kk');downloadButton.setAttribute('href', videoURL);downloadButton.setAttribute('target', '_blank');downloadButton.setAttribute('download', videoURL);return downloadButton;}// ----------------------------------------// DASHBOARD BUTTONS// ----------------------------------------function dashboardDownloadButtons() {// Tumblr uses two class names that only differ by "-" and "_". The former used for blogs, and the latter for the dashboard.var posts = document.getElementsByClassName('post-wrapper');if (!posts[0]) posts = document.getElementsByClassName('post_wrapper');if (!posts[0]) posts = document.getElementsByClassName('text-post'); // blogs...for (var i = 0; i < posts.length; ++i) {var videos = posts[i].getElementsByTagName('video');if (videos[0]) {for (var a = 0; a < videos.length; ++a) {// if the button already exists, ignore this postvar btnCheck = posts[i].getElementsByClassName('videoDownloadButtonStyle_kk');if (btnCheck[0]) continue;// Generate the video URLvar videoURL;// Check whether the video is a livePhotovar livePhoto = videos[a].getAttribute("class");if (livePhoto && livePhoto == "live-photo-video") {videoURL = videos[a].src;}// Otherwise, use the video preview image urlelse if (videos[a].poster) {videoURL = videos[a].poster;videoURL = fixVideoUrl(videoURL);} else {continue;}var downloadBtn = createBtn(videoURL);var belowVideo = "";// reblogged videosif (!belowVideo) belowVideo = posts[i].getElementsByClassName('reblog-content')[0];// normal videosif (!belowVideo) belowVideo = posts[i].getElementsByClassName('post_media')[0];if (!belowVideo) belowVideo = posts[i].getElementsByClassName('tmblr-full')[0];if (!belowVideo) belowVideo = posts[i].getElementsByTagName('figure')[0];/*// This will a) not load-in because tumblr's JS overwrites it, and b) displays underneath the video player control bar somehow...if (!belowVideo) {var crtVideo = posts[i].getElementsByClassName('post_body')[0].getElementsByTagName("div")[0];if (crtVideo.hasAttribute("data-crt-video")) belowVideo = crtVideo;}*/if (!belowVideo) belowVideo = posts[i].getElementsByClassName('post_body')[0];belowVideo.appendChild(downloadBtn);// consider displaying the button above videos, due to tumblr changes and the problem of displaying it below videos//belowVideo.insertBefore(downloadButton, belowVideo.childNodes[0]);}}}}if (location.hostname.includes("tumblr.com")) {if (loc.endsWith('.com/') || loc.includes('tumblr.com/dashboard') || loc.includes('tumblr.com/post') || loc.includes('tumblr.com/like')|| loc.includes('tumblr.com/search/') || loc.includes('tumblr.com/tagged')) {window.addEventListener("DOMContentLoaded", function load() {window.removeEventListener("DOMContentLoaded", load, false);// For initial page loaddashboardDownloadButtons();// For endless scrolling usersdynamicScroll(dashboardDownloadButtons);}, false);}}// ----------------------------------------// BLOG BUTTONS// ----------------------------------------var eDisplay = false;function req (videoNum, video) {GM_xmlhttpRequest({url: video,headers: {":Authority": "www.tumblr.com","Referer": location.href},method: 'GET',onload: function(response) {if (response.status == '200' && response.responseText) {try {var text = response.responseText;var a = text.match("previews.+tumblr_.+filmstrip\.") || text.match("\/tumblr_.+frame1\.");a[0] = a[0].replace("previews\/", "");a[0] = a[0].replace("_r1_filmstrip", "");a[0] = a[0].replace("_filmstrip", "");a[0] = a[0].replace("_frame1", "");var videoUrl = "https://vt.tumblr.com/" + a[0].toString() + "mp4";embedBlogDownloadButtons(videoNum, videoUrl);}catch (e) {if (!eDisplay) {window.alert("There was a problem embedding video download buttons. Please report this at the below site. (動画のダウンロードボタンの埋め込みに問題が発生しました。下のサイトまで報告してください。)\n\nhttps://greasyfork.org/en/scripts/32038-tumblr-hd-video-download-buttons\n\n" + "The problem is (発生した問題は):\n" + e);eDisplay = true;}console.error(e);}}}});}var videoCache = [];function blogDownloadButtons() {// Get the iframe of this post, which has the video URLvar frames = document.getElementsByTagName("iframe");for (var i = 0; i < frames.length; i++) {var frame = frames[i];// Check whether this is a videoif (!frame.src.includes("/video/")) continue;// if the button already exists, ignore this postvar frameParent = frame.parentNode;var btnCheck = frameParent.getElementsByClassName('videoDownloadButtonStyle_kk');if (videoCache.indexOf(frame.src) > -1 || btnCheck[0]) continue;// Cache the current post IDvideoCache.push(frame.src);// Get the video url via a crossDomain request from the iframevar videoNum = i;req(videoNum, frame.src);}}function embedBlogDownloadButtons (videoNum, videoURL) {var frames = document.getElementsByTagName("iframe");var frame = frames[videoNum];var frameParent = frame.parentNode;var downloadBtn = createBtn(videoURL);frameParent.appendChild(downloadBtn);}if (location.hostname.includes('tumblr.com') && location.hostname != 'tumblr.com') {window.addEventListener("DOMContentLoaded", function load() {window.removeEventListener("DOMContentLoaded", load, false);// For initial page loadblogDownloadButtons();dashboardDownloadButtons();// For endless scrolling usersdynamicScroll(blogDownloadButtons);dynamicScroll(dashboardDownloadButtons);}, false);}