Bilibili 分P时长计算器

计算 Bilibili 视频分 P 的总时长

// ==UserScript==

// @name     Bilibili 分P时长计算器

// @namespace  http://tampermonkey.net/

// @version   1.9.1

// @description 计算 Bilibili 视频分 P 的总时长

// @author    NightRaid

// @match    https://www.bilibili.com/video/*

// @grant    none

// @license All Rights Reserved

// ==/UserScript==

(function() {
  'use strict';

  // 等待页面加载
  setTimeout(function() {
    //获取当前P数及最大P数
    function getPart(){
       var separateText = document.querySelector('.amt').innerText.trim();
       var startP = 1;
       var endP = 1;
       // 使用正则表达式提取括号中的数字
       try{
           var match = separateText.split("/");
           startP = parseInt(match[0].split("(")[1]);
           endP = parseInt(match[1].split(")")[0]);
           startInput.value = startP; // 设置默认值
           endInput.value = endP; //设置默认值
           console.log("?");
       }catch(e){
           console.log("未能匹配到当前分P及最大分P,请自行输入!"+e.message);
       }
    }

    // 创建侧边栏
    var sidebar = document.createElement('div');
    sidebar.style.position = 'fixed';
    sidebar.style.bottom = '70%'; // 靠近页面70%高度的位置
    sidebar.style.right = '10px';
    sidebar.style.width = '60px'; // 缩小默认宽度
    sidebar.style.height = '35px';
    sidebar.style.backgroundColor = '#007bff'; // 美化背景颜色
    sidebar.style.color = 'white';
    sidebar.style.borderRadius = '20px 0 0 20px'; // 类似半圆
    sidebar.style.zIndex = '1000';
    sidebar.style.textAlign = 'center';
    sidebar.style.lineHeight = '35px';
    sidebar.style.boxShadow = '0 2px 5px rgba(0,0,0,0.3)';
    sidebar.style.cursor = 'pointer'; // 小手标识
    sidebar.style.userSelect = 'none';
    sidebar.title = '点击展开/收起';
    sidebar.style.transition = 'width 0.3s'; // 添加宽度平滑过渡

    // 创建展示文字
    var sidebarText = document.createElement('span');
    sidebarText.innerText = '统计';
    sidebarText.style.fontSize = '14px';
    sidebarText.style.transition = 'all 0.3s'; // 流畅变化
    sidebar.appendChild(sidebarText);

    // 创建水印
    var watermark = document.createElement('div');
    watermark.innerText = 'NightRaid';
    watermark.style.fontSize = '12px';
    watermark.style.color = 'rgba(0, 0, 0, 0.5)';
    watermark.style.textAlign = 'center';
    watermark.style.marginTop = '5px';
    watermark.style.opacity = '0'; // 初始隐藏
    watermark.style.transition = 'opacity 0.3s'; // 添加透明度平滑过渡
    sidebar.appendChild(watermark);

    // 创建展示栏
    var form = document.createElement('div');
    form.style.display = 'none'; // 初始时隐藏
    form.style.position = 'fixed';
    form.style.bottom = '40%'; // 与侧边栏对齐
    form.style.right = '10px'; // 紧挨侧边栏底部
    form.style.width = '300px';
    form.style.height = 'auto'; // 自适应高度
    form.style.padding = '15px';
    form.style.backgroundColor = '#f9f9f9';
    form.style.border = '1px solid #ddd';
    form.style.borderRadius = '10px';
    form.style.boxShadow = '0 2px 5px rgba(0,0,0,0.3)';
    form.style.zIndex = '1000';
    form.style.transition = 'all 0.3s'; // 平滑过渡
    form.style.overflow = 'auto'; // 内容溢出时显示滚动条
    form.style.cursor = 'default'; // 保持小手标识

    // 创建起始分 P 的输入框
    var startLabel = document.createElement('label');
    startLabel.innerText = '起始分 P: ';
    startLabel.style.display = 'block';
    var startInput = document.createElement('input');
    startInput.type = 'number';
    startInput.min = '1';
    startInput.value = 1; // 设置默认值
    startInput.style.marginBottom = '10px';
    startInput.style.width = '100%';
    startLabel.appendChild(startInput);

    // 创建终止分 P 的输入框
    var endLabel = document.createElement('label');
    endLabel.style.display = 'block';
    endLabel.style.marginTop = '10px';
    endLabel.innerText = '终止分 P: ';
    var endInput = document.createElement('input');
    endInput.type = 'number';
    endInput.min = '1';
    endInput.value = 1; //设置默认值
    endInput.style.marginBottom = '10px';
    endInput.style.width = '100%';
    endLabel.appendChild(endInput);

    // 创建倍速输入框
    var speedLabel = document.createElement('label');
    speedLabel.innerText = '倍速: ';
    speedLabel.style.display = 'block';
    var speedInput = document.createElement('input');
    speedInput.type = 'number';
    speedInput.min = '0.1';
    speedInput.step = '0.1';
    speedInput.value = '1';
    speedInput.style.marginBottom = '10px';
    speedInput.style.width = '100%';
    speedLabel.appendChild(speedInput);

    // 创建计算时长按钮
    var submitButton = document.createElement('button');
    submitButton.type = 'button';
    submitButton.innerText = '计算时长';
    submitButton.style.padding = '8px 16px';
    submitButton.style.backgroundColor = '#4CAF50';
    submitButton.style.color = 'white';
    submitButton.style.border = 'none';
    submitButton.style.borderRadius = '5px';
    submitButton.style.cursor = 'pointer';
    submitButton.style.width = '100%';

    // 创建结果容器
    var resultContainer = document.createElement('div');
    resultContainer.style.padding = '10px';
    resultContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
    resultContainer.style.color = 'white';
    resultContainer.style.borderRadius = '5px';
    resultContainer.style.display = 'none'; // 初始时隐藏
    resultContainer.style.boxShadow = '0 2px 5px rgba(0,0,0,0.3)';
    resultContainer.style.transition = 'opacity 0.3s'; // 平滑过渡
    resultContainer.style.marginTop = '10px'; // 间隔
    resultContainer.style.opacity = '0'; // 初始隐藏

    // 创建关闭按钮
    var closeButton = document.createElement('span');
    closeButton.innerText = '×';
    closeButton.style.fontSize = '20px';
    closeButton.style.cursor = 'pointer';
    closeButton.style.position = 'absolute';
    closeButton.style.top = '10px';
    closeButton.style.right = '10px';
    closeButton.title = '关闭';
    closeButton.addEventListener('click', function() {
      form.style.display = 'none'; // 关闭时隐藏展示栏
      sidebar.style.width = '60px'; // 恢复侧边栏默认宽度
      sidebarText.innerText = '统计'; // 恢复展示文字
      watermark.style.opacity = '0'; // 隐藏水印
      resultContainer.style.opacity = '0'; // 隐藏结果
    });

    resultContainer.appendChild(closeButton);
    form.appendChild(startLabel);
    form.appendChild(endLabel);
    form.appendChild(speedLabel); // 添加倍速输入框
    form.appendChild(submitButton);
    form.appendChild(resultContainer); // 将结果输出栏放进展示栏

    document.body.appendChild(form);
    document.body.appendChild(sidebar);

    // 按钮点击事件处理函数:计算时长
    submitButton.addEventListener('click', function() {
      var startPart = parseInt(startInput.value);
      var endPart = parseInt(endInput.value);
      var speed = parseFloat(speedInput.value);
      var result = "";
      var h = 0;
      var m = 0;
      var s = 0;

      try {
    // 获取视频的所有视频分P项
    var content = document.querySelectorAll('.video-pod__list .video-pod__item');

    // 自动设置 endPart 为 content 的总长度,如果未设置用户输入
    if (isNaN(endPart) || endPart > content.length) {
        endPart = content.length;
        endInput.value = endPart;
    }

    // 遍历每个视频分P,从 startPart 到 endPart
    for (var i = startPart - 1; i <= endPart - 1; i++) {
        var temp = content[i].querySelector('.title-txt').innerText;  // 获取标题
        var durationText = content[i].querySelector('.stat-item.duration').innerText;  // 获取时长
        var time = durationText.split(":");  // 按照 ':' 分割时分秒
        var hour, minute, second;

        if (time.length === 2) {
            hour = 0;  // 如果没有小时部分,默认是0
            minute = parseInt(time[0]);
            second = parseInt(time[1]);
        } else if (time.length === 3) {
            hour = parseInt(time[0]);
            minute = parseInt(time[1]);
            second = parseInt(time[2]);
        }

        // 累加时间
        h += hour;
        s += second;
        if (s >= 60) {
            s -= 60;
            m += 1;
        }

        m += minute;
        if (m >= 60) {
            m -= 60;
            h += 1;
        }
    }

    // 计算总时长(秒)
    var totalSeconds = h * 3600 + m * 60 + s;

    // 应用倍速
    var speedTime = totalSeconds / speed;

    // 将秒数转换为小时、分钟、秒
    var speedH = Math.floor(speedTime / 3600);
    speedTime -= speedH * 3600;
    var speedM = Math.floor(speedTime / 60);
    var speedS = Math.floor(speedTime % 60);

    // 格式化结果
    result = "从 " + startPart + "P 到 " + endPart + "P\n"
        + "总计时长: " + h + "小时 " + m + "分钟 " + s + "秒\n"
        + "当前倍速: " + speed + "倍\n"
        + "使用倍速观看时需时长: " + speedH + "小时 " + speedM + "分钟 " + speedS + "秒\n"
        + "作者:NightRaid\n"
        + "QQ:1454272310";

} catch (e) {
    console.error("计算时发生错误", e);
    result = "计算失败,请检查输入是否正确";
}


      resultContainer.innerText = '总时长: ' + result;
      resultContainer.style.opacity = '1'; // 显示结果
      resultContainer.style.display = 'block'; // 确保显示
    });

    // 鼠标移动事件处理函数
    sidebar.addEventListener('mouseenter', function() {
      getPart();
      sidebar.style.width = '200px'; // 鼠标移入时宽度变宽
      sidebarText.innerText = '分P时长统计'; // 改变展示文字
      watermark.style.opacity = '1'; // 显示水印
      adjustFormPosition(); // 调整展示栏位置
    });

    // 鼠标移出事件处理函数
    sidebar.addEventListener('mouseleave', function() {
      sidebar.style.width = '60px'; // 恢复宽度
      sidebarText.innerText = '统计'; // 恢复展示文字
      watermark.style.opacity = '0'; // 隐藏水印
    });

    // 调整展示栏的位置
    function adjustFormPosition() {
      form.style.right = (parseInt(sidebar.style.right) + parseInt(sidebar.style.width)) + 'px';
      form.style.bottom = (parseInt(sidebar.style.bottom) - parseInt(form.style.height) + parseInt(sidebar.style.height)) + 'px';
    }

    // 页面加载完成后调整位置
    adjustFormPosition();

    // 窗口调整大小时重新调整展示栏的位置
    window.addEventListener('resize', adjustFormPosition);

    // 点击侧边栏时展开/收起展示栏
    sidebar.addEventListener('click', function() {
      if (form.style.display === 'none') {
        form.style.display = 'block';
        resultContainer.style.display = 'none'; // 展示栏打开时隐藏结果输出栏
        resultContainer.style.opacity = '0'; // 确保结果容器初始时隐藏
      } else {
        form.style.display = 'none';
        resultContainer.style.opacity = '0'; // 隐藏结果容器
      }
    });

  }, 1000); // 等待1秒以确保页面加载完成
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址