我正在编写一个 Chrome 扩展程序,该扩展程序应该在访问 Youtube 观看页面时运行
youtube.com/watch?
。我 10 年前读过这个问题,那里的解决方案似乎工作不一致。
我的
manifest.json
有这个。我相信这意味着 content.js
应该在每个 Youtube 页面上运行,而不仅仅是观看页面。
"content_scripts": [
{
"js": ["scripts/content.js"],
"matches": ["https://www.youtube.com/*"]
}
]
我的
content.js
文件当前有一个事件侦听器,我从这篇文章获得了它。我发现这不会在每次加载观看页面时运行。我有时需要刷新监视页面才能运行脚本。
从功能上讲,我正在读取视频的当前时间、持续时间和播放速度,以计算剩余观看时间。
document.addEventListener("yt-navigate-start", removeRemainingTime);
document.addEventListener("yt-navigate-finish", setupRemainingTimeDisplay);
let intervalId;
function setupRemainingTimeDisplay() {
const video = document.querySelector("video");
const timeWrapper = document.querySelector(".ytp-time-wrapper");
if (timeWrapper && video) {
// Create or find the existing span for remaining time
let remainingTime = document.querySelector(".remaining-time");
if (!remainingTime) {
remainingTime = document.createElement("span");
remainingTime.className = "remaining-time";
remainingTime.style.color = "#ddd";
timeWrapper.appendChild(remainingTime);
}
// Update remaining time every second
intervalId = setInterval(() => {
updateRemainingTime(video, remainingTime);
}, 1000);
}
}
function updateRemainingTime(video, remainingTime) {
const { duration, playbackRate, currentTime } = video;
if (!duration || isNaN(playbackRate) || isNaN(currentTime)) {
remainingTime.textContent = " • Invalid time";
return;
}
const timeLeft = calculateRemainingTime(currentTime, playbackRate, duration);
remainingTime.textContent = ` • ${formatTimestamp(timeLeft)} left`;
}
function calculateRemainingTime(currentTime, playbackRate, duration) {
return Math.max((duration - currentTime) / playbackRate, 0);
}
function formatTimestamp(seconds) {
const totalSeconds = Math.floor(seconds);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const secs = totalSeconds % 60;
if (hours > 0) {
return `${hours}:${String(minutes).padStart(2, "0")}:${String(
secs
).padStart(2, "0")}`;
} else {
return `${minutes}:${String(secs).padStart(2, "0")}`;
}
}
function removeRemainingTime() {
const remainingTimeElements = document.querySelectorAll(".remaining-time");
remainingTimeElements.forEach((element) => element.remove());
clearInterval(intervalId);
}
如何确保每次访问 YouTube 观看页面时
content.js
都会运行?
此问题有多种可能的解决方案。
一种选择是使用
history.pushState
,但 YouTube 默认情况下不会触发此事件。另一种方法是使用 MutationObserver
来检测页面内容何时发生更改。
结合这两种方法可能会产生更好的结果。
最佳方法取决于 content.js 文件中的逻辑。
这里有一个示例代码,演示如何使用
MutationObserver
:
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
const video = document.querySelector('video');
if (video) {
removeRemainingTime();
setupRemainingTimeDisplay();
}
}
});
});