YouTube Annotation Markers

Marks where annotations are on the progress bar of the HTML5 YouTube player.

目前为 2017-10-29 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Annotation Markers
  3. // @namespace https://github.com/HatScripts/YouTubeAnnotationMarkers
  4. // @version 1.2.2
  5. // @description Marks where annotations are on the progress bar of the HTML5 YouTube player.
  6. // @author HatScripts
  7. // @include http*://*.youtube.com/*
  8. // ==/UserScript==
  9.  
  10. (function () {
  11. function parseTime(timeStr) {
  12. var parts = timeStr.split(":");
  13. var duration = 0;
  14. for (var multiplier = 1; parts.length > 0; multiplier *= 60) {
  15. duration += multiplier * parseFloat(parts.pop());
  16. }
  17. return duration;
  18. }
  19.  
  20. function getVideoAnnotationXml(videoId, success) {
  21. var request = new XMLHttpRequest();
  22. request.open("GET", "annotations_invideo?video_id=" + videoId, true);
  23. request.onload = function () {
  24. if (request.status >= 200 && request.status < 400) {
  25. var xmlString = request.responseText;
  26. var domParser = new DOMParser();
  27. success(domParser.parseFromString(xmlString, "text/xml"));
  28. }
  29. };
  30. request.send();
  31. }
  32.  
  33. function annotationToMarker(annotation) {
  34. var rectRegions = Array.from(annotation.querySelectorAll("movingRegion *:not([t=never])"));
  35. if (rectRegions.length === 0) {
  36. return false;
  37. }
  38. var start = rectRegions[0].getAttribute("t");
  39. var end = rectRegions[rectRegions.length - 1].getAttribute("t");
  40. var startTime = parseTime(start);
  41. var duration = parseTime(end) - startTime;
  42. var appearance = annotation.querySelector("appearance");
  43. var c = parseInt(appearance.getAttribute("bgColor"), 10);
  44. var rgb = [(c & 0xff0000) >> 16, (c & 0x00ff00) >> 8, (c & 0x0000ff)];
  45. var marker = document.createElement("div");
  46. marker.classList.add("ytp-play-progress");
  47. marker.style.position = "absolute";
  48. marker.style.left = ((startTime / videoDuration) * 100) + "%";
  49. marker.style.bottom = "100%";
  50. marker.style.transform = "scaleX(" + (duration / videoDuration) + ")";
  51. marker.style.background = "rgb(" + rgb + ")";
  52. marker.style.opacity = 0.5;
  53. marker.style.zIndex = Math.round(startTime * 10);
  54. return marker;
  55. }
  56.  
  57. function parseVideoAnnotationXml(xml) {
  58. Array.from(xml.querySelectorAll("annotation")).map(function (annotation) {
  59. return annotationToMarker(annotation);
  60. }).filter(function (annotation) {
  61. return annotation;
  62. }).sort(function (a1, a2) {
  63. return parseInt(a1.style.zIndex) - parseInt(a2.style.zIndex);
  64. }).forEach(function (annotation) {
  65. progressList.appendChild(annotation);
  66. });
  67. }
  68.  
  69. function getVideoId() {
  70. var url = new URL(location.href);
  71. return url.searchParams.get("v") || url.pathname.split("/").pop()
  72. || document.querySelector("#page-manage ytd-watch").getAttribute("video-id");
  73. }
  74.  
  75. var videoId = getVideoId();
  76. var player = document.querySelector("#player");
  77. var progressBar = player.querySelector(".ytp-progress-bar");
  78. var progressList = progressBar.querySelector(".ytp-progress-list");
  79. var videoDuration = parseTime(player.querySelector(".ytp-time-duration").innerText);
  80. getVideoAnnotationXml(videoId, parseVideoAnnotationXml);
  81. })();