您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shows complete video thumbnails for YouTube videos
当前为
// ==UserScript== // @name YouTube Thumbnails -- Full Video Thumbnails for YouTube // @namespace driver8.net // @description Shows complete video thumbnails for YouTube videos // @match *://*.youtube.com/watch?* // @version 0.2 // @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js // @grant GM_addStyle // @grant unsafeWindow // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // ==/UserScript== var AND_BUTTS = false; var LOAD_DELAY = 500; var TIMEOUT_DELAY = 2000; var DIV_PADDING = 10; var TD_PADDING = 2; var DISABLE_SPF = GM_getValue('ytDisableSPF', false); var LOGGING = false; var MIN_WIDTH = 4; var $thumbDiv, $thumbHeader, storyboard_spec, storyboard, best_size_idx, best_size, len_seconds, videoId, tries; function log(msg) { if (LOGGING) { console.log(msg); } } log("Hi"); setUp(); function setUp() { AND_BUTTS && $('#eow-title').text($('#eow-title').text() + " and Butts"); // See if waiting will help w/spf bullshit (it won't) tries = 0; (function trySb() { try { storyboard_spec = unsafeWindow.ytplayer.config.args.storyboard_spec; } catch (e) { log("oops " + e); try { storyboard_spec = window.ytplayer.config.args.storyboard_spec; } catch (e2) { log("oops2 " + e2); if (tries++ < 2) { window.setTimeout(trySb, TIMEOUT_DELAY); } } } })(); storyboard = parseStoryboardSpec(storyboard_spec); best_size_idx = chooseBestStoryboardSize(storyboard); best_size = storyboard.sizes[best_size_idx]; log(best_size); len_seconds = parseInt(unsafeWindow.ytplayer.config.args.length_seconds); log("len: " + len_seconds); var $titleDiv = $('#watch-header'); $thumbDiv = $('<div id="thumbDiv" class="yt-card"></div>'); $thumbDiv.css('padding', DIV_PADDING +'px'); $thumbHeader = $('<h1 width="100%">Thumbs</h1>'); $thumbHeader.css({'cursor': 'pointer'}); $thumbDiv.append($thumbHeader); $titleDiv.after($thumbDiv); $thumbHeader.click(showThumbs); log("Script done"); styleIt(); } function showThumbs() { var duration = best_size.duration / 1000; var num_thumbs = 1; if (duration > 0) { num_thumbs = Math.ceil(len_seconds / duration / best_size.cols / best_size.rows); } else { duration = len_seconds / best_size.cols / best_size.rows; } log("Thumb header clicked. Loading " + num_thumbs + " images."); var total_width = best_size.width * best_size.cols + DIV_PADDING * 2; var parent_diff = $thumbDiv.parent().innerWidth() - total_width; parent_diff < 0 && $thumbDiv.css({'left': + parent_diff + 'px'}); $thumbDiv.css({'position': 'relative', 'width': total_width + 'px'}); var badImage = false; (function loadImage(imgNum) { if (badImage === false && imgNum < num_thumbs && imgNum < 30) { // EX: https:\/\/i.ytimg.com\/sb\/2XY3AvVgDns\/storyboard3_L$L\/$N.jpg // EX: https://i.ytimg.com/sb/k4YRWT_Aldo/storyboard3_L2/M0.jpg?sigh=RVdv4fMsE-eDcsCUzIy-iCQNteI var link = storyboard.baseUrl.replace('\\', ''); link = link.replace('$L', best_size_idx); link = link.replace('$N', best_size.img_name); link = link.replace('$M', imgNum); link += '?sigh=' + best_size.sigh; log(link); // Create a table for the timestamps over the image var $newTable = $('<table>'); $newTable.addClass('imgTable'); var x = imgNum * duration * best_size.rows * best_size.cols; // the starting time for this table var innerStr = ''; for (var i = 0; i < best_size.rows; i++) { if (x <= len_seconds + 1) { // if we haven't reached the end of the video innerStr += '<tr>'; for (var j = 0; j < best_size.cols; j++) { innerStr += '<td>'; if (x <= len_seconds + 1) { innerStr += x > 3600 ? Math.floor(x / 3600) + ':' : ''; // hrs innerStr += Math.floor((x % 3600) / 60) + ':'; // mins innerStr += Math.round(x % 60) < 10 ? '0' + Math.round(x % 60) : Math.round(x % 60); // secs } innerStr += '</td>'; x += duration; } innerStr += '<tr>'; } } $newTable.html(innerStr); $newTable.error(function() { badImage = true; $(this).remove(); log("Hid bad image"); }); //$newTable.load(function() { // loadImage(imgNum + 1); //}); $newTable.css({'background-image': 'url(' + link + ')', 'width': best_size.width * best_size.cols}); $thumbDiv.append($newTable); setTimeout(loadImage, 200 + imgNum * 50, imgNum + 1); } })(0); log("Done making thumb div"); $thumbHeader.off('click'); $thumbHeader.click(hideThumbs); } function hideThumbs() { $thumbDiv.children('img').hide(); $thumbHeader.off('click'); $thumbHeader.click(showThumbsAgain); } function showThumbsAgain() { $thumbDiv.children('img').show(); $thumbHeader.off('click'); $thumbHeader.click(hideThumbs); } function parseStoryboardSpec(spec) { // EX: https:\/\/i.ytimg.com\/sb\/Pk2oW4SDDxY\/storyboard3_L$L\/$N.jpg|48#27#100#10#10#0#default#vpw4l5h3xmm2AkCT6nMZbvFIyJw|80#45#90#10#10#2000#M$M#hCWDvBSbgeV52mPYmOHjgdLFI1o|160#90#90#5#5#2000#M$M#ys1MKEnwYXA1QAcFiugAA_cZ81Q var sections = spec.split('|'); log(sections); var sb = { sizes: [], baseUrl: sections.shift() }; // EX: 80#45#90#10#10#2000#M$M#hCWDvBSbgeV52mPYmOHjgdLFI1o // EX: 160# 90# 90# 5# 5# 2000# M$M# ys1MKEnwYXA1QAcFiugAA_cZ81Q sections.forEach(function(value, idx) { var data = value.split('#'); log(data); var new_size = { width : +data[0], height : +data[1], qual : +data[2], // image quality??? cols : +data[3], rows : +data[4], duration : +data[5], // duration of each snapshot in milliseconds img_name : data[6], sigh : data[7] }; sb.sizes[idx] = new_size; }); log(sb); return sb; } function chooseBestStoryboardSize(sb) { var sizes = sb.sizes; var widest = 0; var widest_idx = -1; for (var i = 0; i < sizes.length; i++) { if (widest < sizes[i].width || (widest == sizes[i].width && sizes[widest_idx].cols < sizes[i].cols)) { if (sizes[i].cols >= MIN_WIDTH) { widest = sizes[i].width; widest_idx = i; } } } return widest_idx; } function styleIt() { var userStyles0 = "table.imgTable { border-collapse: collapse; background-repeat: no-repeat; !important } " + ".imgTable td { width: " + (best_size.width - 2 * TD_PADDING) + "px;" + " height: " + (best_size.height - 2 * TD_PADDING) + "px;" + " padding: " + TD_PADDING + "px;" + " border-width: 0px;" + " vertical-align: top;" + " color: white;" + " text-shadow:" + " -1px -1px 0 #000, " + " 1px -1px 0 #000, " + " -1px 1px 0 #000, " + " 1px 1px 0 #000; " + " !important}"; GM_addStyle(userStyles0); if (DISABLE_SPF) { $('a.spf-link').each(function () { var $link = $(this); $link.removeClass('spf-link'); $link.off(); }); } GM_registerMenuCommand( "Toggle SPF", function toggleSpf() { DISABLE_SPF = !DISABLE_SPF; GM_setValue('ytDisableSPF', DISABLE_SPF); }, 's' ); log("DONE"); } /// TRYING TO DEAL WITH YOUTUBE'S STUPID SPF SHIT WITHOUT DISABLING IT. BLAHH! /// //window.addEventListener('spfrequest', function() { log("SPF WUT? spfrequest"); }); //window.addEventListener('spfpartprocess', function() { log("SPF WUT? spfpartprocess"); }); //window.addEventListener('spfpartdone', function() { log("SPF WUT? spfpartdone"); }); //window.addEventListener('spfprocess', function() { log("SPF WUT? spfprocess"); }); //window.addEventListener('spfdone', function() { log("SPF WUT? spfdone"); }); //window.addEventListener('spferror', function() { log("SPF WUT? spferror"); }); //window.addEventListener('spfreload', function() { log("SPF WUT? spfreload"); }); //window.addEventListener('spfjsbeforeunload', function() { log("SPF WUT? spfjsbeforeunload"); }); //window.addEventListener('spfdone', spfWut); //function spfWut(a) { // log(a); // var parts = a.detail.response.parts; // var good_part = null; // parts.forEach(function(val, idx) { // good_part = good_part || (val.data && val.data.swfcfg); // }); // log(good_part); // // var storyboard_spec = a.data.swfcfg.args.storyboard_spec; // storyboard_spec = good_part.args.storyboard_spec; // log("sbSpec: " + sb_spec); // best_size_idx_idx = chooseBestStoryboardSize(storyboard); // best_size = storyboard.sizes[best_size_idx_idx]; // log(best_size); // len_seconds = parseInt(good_part.args.length_seconds); // log("len: " + len_seconds); // setUp(); // log("BOOM"); //} // //(function transitionCheck() { // $('body').on('transitionend', function(event) { // log("transitioned prog"); // if (event.target.id != 'progress') return false; // log("transitioned event"); // setUp(); // log("BOOM"); // transitionCheck(); // }); //})();