Hulu.jp Subtitle Downloader

Download subtitle guides from Hulu.jp in VTT format

目前為 2025-01-09 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Hulu.jp Subtitle Downloader
// @namespace    https://hulu.jp
// @version      1.0.0
// @description  Download subtitle guides from Hulu.jp in VTT format
// @author       Ronny
// @match        https://*.hulu.jp/watch/*
// @copyright
// @license MIT
// ==/UserScript==

(function () {
  ("use strict");

  var settingButton = document.getElementsByClassName("watch-info-title")[0];
  var button = document.createElement("button");
  var fileName = "subtitle.vtt";
  var subSrc = "";
  button.innerHTML = "字幕ガイドをダウンロード";
  button.style.border = "none";
  button.style.borderRadius = "4px";
  button.style.backgroundColor = "#889188";
  button.style.color = "#fefffe";
  button.style.padding = "1em 1.5em";
  button.style.lineHeight = "1";
  button.style.fontSize = "0.8em";
  button.addEventListener("mouseover", function () {
    button.style.opacity = "0.8";
  });
  button.addEventListener("mouseout", function () {
    button.style.opacity = "1";
  });

  settingButton.appendChild(button);

  const downloadSubtitle = () => {
    if (!subSrc) {
      console.error("No subtitle track found.");
      return;
    }

    fetch(subSrc)
      .then((response) => response.text())
      .then((data) => {
        const blob = new Blob([data], { type: "text/vtt" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = fileName;
        a.click();
        URL.revokeObjectURL(url);
      })
      .catch((error) => {
        console.error("Failed to download subtitle:", error);
      });
  };

  button.onclick = downloadSubtitle;

  const originalXhrOpen = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function (method, url, ...rest) {
    this.addEventListener("load", function () {
      // 在这里可以检查 URL 和响应内容
      if (url.startsWith("https://playback.prod.hjholdings.tv/session/open")) {
        try {
          // 生成片名
          const pageTitle = document.title;
          fileName = pageTitle.split(" | ")[0].trim() + ".vtt";
          // 遍历 tracks 数组,找出含有 label: "字幕ガイド" 的项目
          const targetTrack = this.response.tracks.find(
            (track) => track.label === "字幕ガイド"
          );

          if (targetTrack) {
            const src = targetTrack.src;
            console.log("Found subtitle track, src:", src);
            subSrc = src;
          } else {
            console.log("No subtitle track found.");
          }
        } catch (e) {
          console.error("Failed to parse JSON response:", e);
        }
      }
    });
    originalXhrOpen.apply(this, [method, url, ...rest]);
  };
})();