Skip to content

Instantly share code, notes, and snippets.

@panzi
Last active June 30, 2023 14:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panzi/92db274c1b73e27807c779d84a9983e4 to your computer and use it in GitHub Desktop.
Save panzi/92db274c1b73e27807c779d84a9983e4 to your computer and use it in GitHub Desktop.

Create a new bookmark and use this as the link:

javascript:%28function%28%29%20%7B%20%22use%20strict%22%3B%20function%20padd%28x%29%20%7B%20var%20x%20%3D%20String%28x%29%3B%20return%20x.length%20%3C%202%20%3F%20%270%27%20%2B%20x%20%3A%20x%3B%20%7D%20var%20duration%20%3D%20%2Bdocument.querySelector%28%22video%22%29.duration%3B%20var%20playerData%20%3D%20document.querySelector%28%22ytd-watch-flexy%22%29.__data.playerData%3B%20var%20storyboard_spec%20%3D%20playerData.storyboards.playerStoryboardSpecRenderer.spec.split%28%27%7C%27%29%3B%20var%20url_template%20%3D%20storyboard_spec%5B0%5D%3B%20var%20sheets%20%3D%20storyboard_spec.slice%281%29.map%28function%28spec%2C%20quality%29%20%7B%20var%20spec%20%3D%20spec.split%28%27%23%27%29%3B%20var%20sheet%20%3D%20%7B%20url_template%3A%20url_template%2C%20url%3A%20url_template.replace%28%27%24L%27%2C%20quality%29.replace%28%27%24N%27%2C%20spec%5B6%5D%29%2C%20quality%3A%20quality%2C%20width%3A%20%2Bspec%5B0%5D%2C%20height%3A%20%2Bspec%5B1%5D%2C%20count%3A%20%2Bspec%5B2%5D%2C%20cols%3A%20%2Bspec%5B3%5D%2C%20rows%3A%20%2Bspec%5B4%5D%2C%20sigh%3A%20spec%5B7%5D%20%7D%3B%20sheet.sheetSize%20%3D%20sheet.cols%20%2A%20sheet.rows%3B%20sheet.sheetCount%20%3D%20%28%28sheet.count%20/%20sheet.sheetSize%29%20%7C%200%29%20%2B%201%3B%20sheet.countOnLastSheet%20%3D%20%28%28sheet.count%20-%201%29%20%25%20sheet.sheetSize%29%20%2B%201%3B%20return%20sheet%3B%20%7D%29%3B%20var%20sheet%20%3D%20sheets%5Bsheets.length%20-%201%5D%3B%20var%20thumbs%20%3D%20%5B%5D%3B%20var%20hash_prefix%20%3D%20%27/watch%3Fv%3D%27%20%2B%20playerData.videoDetails.videoId%3B%20window.x_duration%20%3D%20duration%3B%20window.x_url_tempalte%20%3D%20url_template%3B%20window.x_sheets%20%3D%20sheets%3B%20window.x_thumbs%20%3D%20thumbs%3B%20for%20%28var%20i%20%3D%200%3B%20i%20%3C%20sheet.sheetCount%3B%20%2B%2Bi%29%20%7B%20var%20thumb_count%20%3D%20i%20%3D%3D%3D%20sheet.sheetCount%20-%201%20%3F%20sheet.countOnLastSheet%20%3A%20sheet.sheetSize%3B%20var%20thumb_url%20%3D%20sheet.url.replace%28%27%24M%27%2C%20i%29%20%2B%20%27%26sigh%3D%27%20%2B%20sheet.sigh%3B%20for%20%28var%20t%20%3D%200%3B%20t%20%3C%20thumb_count%3B%20%2B%2Bt%29%20%7B%20var%20row%20%3D%20%28t%20/%20sheet.cols%29%20%7C%200%3B%20var%20col%20%3D%20t%20-%20%28row%20%2A%20sheet.cols%29%3B%20var%20thumb%20%3D%20%7B%20row%3A%20row%2C%20col%3A%20col%2C%20x%3A%20col%20%2A%20sheet.width%2C%20y%3A%20row%20%2A%20sheet.height%2C%20url%3A%20thumb_url%20%7D%3B%20thumbs.push%28thumb%29%3B%20%7D%20%7D%20var%20thumb_duration%20%3D%20duration%20/%20thumbs.length%3B%20var%20links%20%3D%20document.createElement%28%27div%27%29%3B%20links.style.display%20%3D%20%27block%27%3B%20links.style.width%20%3D%20%27100%25%27%3B%20for%20%28var%20i%20%3D%200%3B%20i%20%3C%20thumbs.length%3B%20%2B%2Bi%29%20%7B%20var%20thumb%20%3D%20thumbs%5Bi%5D%3B%20var%20link%20%3D%20document.createElement%28%27a%27%29%3B%20var%20time%20%3D%20thumb_duration%20%2A%20i%3B%20var%20secs%20%3D%20%28time%20%25%2060%29%20%7C%200%3B%20var%20rem%20%3D%20%28%28time%20-%20secs%29%20/%2060%29%20%7C%200%3B%20var%20mins%20%3D%20%28rem%20%25%2060%29%20%7C%200%3B%20var%20hours%20%3D%20%28%28rem%20-%20mins%29%20/%2060%29%20%7C%200%3B%20var%20text%3B%20var%20hash%20%3D%20hash_prefix%3B%20if%20%28hours%20%3E%200%29%20%7B%20text%20%3D%20hours%20%2B%20%27%3A%27%20%2B%20padd%28mins%29%20%2B%20%27%3A%27%20%2B%20padd%28secs%29%3B%20hash%20%2B%3D%20%27%26t%3D%27%20%2B%20hours%20%2B%20%27h%27%20%2B%20mins%20%2B%20%27m%27%20%2B%20secs%20%2B%20%27s%27%3B%20%7D%20else%20%7B%20text%20%3D%20mins%20%2B%20%27%3A%27%20%2B%20padd%28secs%29%3B%20hash%20%2B%3D%20%27%26t%3D%27%20%2B%20mins%20%2B%20%27m%27%20%2B%20secs%20%2B%20%27s%27%3B%20%7D%20link.href%20%3D%20hash%3B%20link.style.display%20%3D%20%27inline-block%27%3B%20link.style.overflow%20%3D%20%27hidden%27%3B%20link.style.width%20%3D%20sheet.width%20%2B%20%27px%27%3B%20link.style.height%20%3D%20sheet.height%20%2B%20%27px%27%3B%20link.style.backgroundImage%20%3D%20%27url%28%27%20%2B%20thumb.url%20%2B%20%27%29%27%3B%20link.style.backgroundRepeat%20%3D%20%27no-repeat%27%3B%20link.style.backgroundPosition%20%3D%20%28-thumb.x%29%20%2B%20%27px%20%27%20%2B%20%28-thumb.y%29%20%2B%20%27px%27%3B%20link.style.color%20%3D%20%27white%27%3B%20link.style.textShadow%20%3D%20%270%200%205px%20rgba%280%2C0%2C0%2C0.6%29%27%3B%20link.textContent%20%3D%20text%3B%20link.setAttribute%28%27data-time%27%2C%20time%29%3B%20link.onclick%20%3D%20function%20%28event%29%20%7B%20document.querySelector%28%22video%22%29.currentTime%20%3D%20%2Bthis.getAttribute%28%27data-time%27%29%3B%20window.scrollTo%280%2C%200%29%3B%20event.preventDefault%28%29%3B%20%7D%3B%20links.appendChild%28link%29%3B%20%7D%20var%20columns%20%3D%20document.getElementById%28%22columns%22%29%3B%20columns.parentNode.insertBefore%28links%2C%20columns%29%3B%20%7D%29%28%29%3B%20void%280%29

When you click it on a YouTube watch page it adds a table where you can see all the seeking thumbnails at once.

(function() {
"use strict";
function padd(x) {
var x = String(x);
return x.length < 2 ? '0' + x : x;
}
var duration = +document.querySelector("video").duration;
var playerData = document.querySelector("ytd-watch-flexy").__data.playerData;
var storyboard_spec = playerData.storyboards.playerStoryboardSpecRenderer.spec.split('|');
var url_template = storyboard_spec[0];
var sheets = storyboard_spec.slice(1).map(function(spec, quality) {
var spec = spec.split('#');
var sheet = {
url_template: url_template,
url: url_template.replace('$L', quality).replace('$N', spec[6]),
quality: quality,
width: +spec[0],
height: +spec[1],
count: +spec[2],
cols: +spec[3],
rows: +spec[4],
sigh: spec[7]
};
sheet.sheetSize = sheet.cols * sheet.rows;
sheet.sheetCount = ((sheet.count / sheet.sheetSize) | 0) + 1;
sheet.countOnLastSheet = ((sheet.count - 1) % sheet.sheetSize) + 1;
return sheet;
});
var sheet = sheets[sheets.length - 1];
var thumbs = [];
var hash_prefix = '/watch?v=' + playerData.videoDetails.videoId;
window.x_duration = duration;
window.x_url_tempalte = url_template;
window.x_sheets = sheets;
window.x_thumbs = thumbs;
for (var i = 0; i < sheet.sheetCount; ++i) {
var thumb_count = i === sheet.sheetCount - 1 ? sheet.countOnLastSheet : sheet.sheetSize;
var thumb_url = sheet.url.replace('$M', i) + '&sigh=' + sheet.sigh;
for (var t = 0; t < thumb_count; ++t) {
var row = (t / sheet.cols) | 0;
var col = t - (row * sheet.cols);
var thumb = {
row: row,
col: col,
x: col * sheet.width,
y: row * sheet.height,
url: thumb_url
};
thumbs.push(thumb);
}
}
var thumb_duration = duration / thumbs.length;
var links = document.createElement('div');
links.style.display = 'block';
links.style.width = '100%';
for (var i = 0; i < thumbs.length; ++i) {
var thumb = thumbs[i];
var link = document.createElement('a');
var time = thumb_duration * i;
var secs = (time % 60) | 0;
var rem = ((time - secs) / 60) | 0;
var mins = (rem % 60) | 0;
var hours = ((rem - mins) / 60) | 0;
var text;
var hash = hash_prefix;
if (hours > 0) {
text = hours + ':' + padd(mins) + ':' + padd(secs);
hash += '&t=' + hours + 'h' + mins + 'm' + secs + 's';
} else {
text = mins + ':' + padd(secs);
hash += '&t=' + mins + 'm' + secs + 's';
}
link.href = hash;
link.style.display = 'inline-block';
link.style.overflow = 'hidden';
link.style.width = sheet.width + 'px';
link.style.height = sheet.height + 'px';
link.style.backgroundImage = 'url(' + thumb.url + ')';
link.style.backgroundRepeat = 'no-repeat';
link.style.backgroundPosition = (-thumb.x) + 'px ' + (-thumb.y) + 'px';
link.style.color = 'white';
link.style.textShadow = '0 0 5px rgba(0,0,0,0.6)';
link.textContent = text;
link.setAttribute('data-time', time);
link.onclick = function (event) {
document.querySelector("video").currentTime = +this.getAttribute('data-time');
window.scrollTo(0, 0);
event.preventDefault();
};
links.appendChild(link);
}
var columns = document.getElementById("columns");
columns.parentNode.insertBefore(links, columns);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment