您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shows complete video thumbnails for YouTube videos. You can click a thumbnail image to jump to that point in the video.
当前为
// ==UserScript== // @name YouTube Thumbnails - Full Video Thumbnails for YouTube // @namespace driver8.net // @description Shows complete video thumbnails for YouTube videos. You can click a thumbnail image to jump to that point in the video. // @match *://*.youtube.com/* // @version 0.3.5 // @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 = GM_getValue('ytAndButts', false); var LOAD_DELAY_START = 200; var LOAD_DELAY_FACTOR = 50; var LOAD_DELAY_MAX = 500; var TIMEOUT_DELAY = 2000; var DIV_PADDING = 10; var TD_PADDING = 2; var DISABLE_SPF = GM_getValue('ytDisableSPF', false); var MIN_WIDTH = 4; var MAX_IMAGES = 30; var LOGGING = false; var $thumbDiv, $thumbHeader, storyboard_spec, storyboard, best_size_idx, best_size, len_seconds, videoId, tries; function log(msg) { 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++ < 0) { window.setTimeout(trySb, TIMEOUT_DELAY); } } } })(); var $titleDiv = $('#watch-header'); if ($titleDiv.prop('nodeName') !== 'DIV') { log("no title div"); return; } if (storyboard_spec) { 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); $thumbDiv = $('<div id="thumbDiv" class="yt-card"></div>'); $thumbHeader = $('<h1 width="100%">Thumbnails</h1>'); $thumbDiv.append($thumbHeader); $thumbDiv.click(showThumbs); } else if (unsafeWindow.ytplayer) { $thumbDiv = $('<div id="thumbDiv" class="yt-card no-thumbs"></div>'); $thumbHeader = $('<h1 width="100%">No Thumbnails Available</h1>'); $thumbDiv.append($thumbHeader); } else { log("Reload for thumbs"); $thumbDiv = $('<div id="thumbDiv" class="yt-card no-thumbs"></div>'); $thumbHeader = $('<h1 width="100%">Reload for Thumbnails</h1>'); $thumbDiv.append($thumbHeader); } $titleDiv.after($thumbDiv); log($titleDiv); log("Script done"); styleIt(); } function showThumbs(event) { 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'}); // Grab the youtube sessionlink ID for time links var sessionlink = $('#logo-container').data("sessionlink"); var badImage = false; (function loadImage(imgNum) { if (badImage === false && imgNum < num_thumbs && imgNum < MAX_IMAGES) { // 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 = ''; var doclocation = document.location.href.replace(/\#.*/, ''); 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><a class="yt-uix-sessionlink" href="' + doclocation + '#t=' + x + '">'; if (x <= len_seconds + 1) { var hrs = Math.floor(x / 3600); var mins = Math.floor((x % 3600) / 60); var secs = Math.round(x % 60); innerStr += hrs > 0 ? hrs + ':' : ''; // hrs innerStr += ( hrs > 0 && mins < 10 ? "0" + mins : mins ) + ':'; // mins innerStr += secs < 10 ? "0" + secs : secs; // secs } innerStr += '</a></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, Math.min(LOAD_DELAY_START + imgNum * LOAD_DELAY_FACTOR, LOAD_DELAY_MAX), imgNum + 1); } })(0); log("Done making thumb div"); $thumbDiv.off('click'); $thumbDiv.click(hideThumbs); } function hideThumbs(event) { if ($(event.target).is('#thumbDiv, #thumbDiv h1')) { $thumbDiv.children('table').hide(); $thumbDiv.off('click'); $thumbDiv.click(showThumbsAgain); } else { $('html, body').scrollTop(0); } } function showThumbsAgain(event) { if ($(event.target).is('#thumbDiv, #thumbDiv h1')) { $thumbDiv.children('table').show(); $thumbDiv.off('click'); $thumbDiv.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() { log("styling"); var td_width = best_size ? best_size.width - 2 * TD_PADDING : 10; var td_height = best_size ? best_size.height - 2 * TD_PADDING : 10; var userStyles0 = "table.imgTable { border-collapse: collapse; background-repeat: no-repeat; cursor: auto; } " + ".imgTable td { width: " + td_width + "px;" + " height: " + td_height + "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}" + ".imgTable a { text-decoration: none; color: white; display: block; width: 100%; height: 100%; } " + "#thumbDiv { padding: " + DIV_PADDING + "px; cursor: pointer; } " + ".no-thumbs { color: grey; cursor: default !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' ); GM_registerMenuCommand( "and Butts", function toggleButts() { AND_BUTTS = !AND_BUTTS; GM_setValue('ytAndButts', AND_BUTTS); }, 'b' ); log("DONE"); } //// CODE STOLEN FROM YoutubeCenter AND YouTubePlaylistAutoplayDisable TO DEAL WITH STUPID SPF. // Runs the function when the page is loading and has finished loading //window.addEventListener('readystatechange',username,true); // Runs the function when the page changes via SPF method: https://github.com/youtube/spfjs/ window.addEventListener('spfdone', setUp);