mirror of
https://github.com/SoPat712/videospeed.git
synced 2025-08-22 02:18:45 -04:00
Merge upstream
# Conflicts: # inject.js # manifest.json
This commit is contained in:
@@ -24,7 +24,7 @@ Once the extension is installed simply navigate to any page that offers HTML5 vi
|
|||||||
* **X** - advance video by 10 seconds.
|
* **X** - advance video by 10 seconds.
|
||||||
* **V** - show/hide the controller.
|
* **V** - show/hide the controller.
|
||||||
|
|
||||||
_Note: you can customize these shortcut keys in the extension settings page._
|
_Note: you can customize these shortcut keys in the extension settings page and even make the extension remember your current playback speed._
|
||||||
|
|
||||||
### FAQ
|
### FAQ
|
||||||
|
|
||||||
|
76
inject.js
76
inject.js
@@ -167,12 +167,12 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
var shadow = wrapper
|
var shadow = wrapper
|
||||||
|
|
||||||
shadow.querySelector('.draggable').addEventListener('mousedown', (e) => {
|
shadow.querySelector('.draggable').addEventListener('mousedown', (e) => {
|
||||||
runAction(e.target.dataset['action'], document);
|
runAction(e.target.dataset['action'], document, false, e);
|
||||||
});
|
});
|
||||||
|
|
||||||
forEach.call(shadow.querySelectorAll('button'), function(button) {
|
forEach.call(shadow.querySelectorAll('button'), function(button) {
|
||||||
button.onclick = (e) => {
|
button.onclick = (e) => {
|
||||||
runAction(e.target.dataset['action'], document);
|
runAction(e.target.dataset['action'], document, false, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -223,10 +223,10 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
window.addEventListener('load', function () {
|
window.addEventListener('load', function () {
|
||||||
initializeNow(document);
|
initializeNow(window.document);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
if (document) {
|
if (document && document.doctype && document.doctype.name == "html") {
|
||||||
if (document.readyState === "complete") {
|
if (document.readyState === "complete") {
|
||||||
initializeNow(document);
|
initializeNow(document);
|
||||||
} else {
|
} else {
|
||||||
@@ -314,25 +314,28 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
}
|
}
|
||||||
} else if (node.children != undefined) {
|
} else if (node.children != undefined) {
|
||||||
for (var i = 0; i < node.children.length; i++) {
|
for (var i = 0; i < node.children.length; i++) {
|
||||||
checkForVideo(node.children[i],
|
const child = node.children[i];
|
||||||
node.children[i].parentNode || parent,
|
checkForVideo(child, child.parentNode || parent, added);
|
||||||
added);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var observer = new MutationObserver(function(mutations) {
|
var observer = new MutationObserver(function(mutations) {
|
||||||
mutations.forEach(function(mutation) {
|
// Process the DOM nodes lazily
|
||||||
forEach.call(mutation.addedNodes, function(node) {
|
requestIdleCallback(_ => {
|
||||||
if (typeof node === "function")
|
mutations.forEach(function(mutation) {
|
||||||
return;
|
forEach.call(mutation.addedNodes, function(node) {
|
||||||
checkForVideo(node, node.parentNode || mutation.target, true);
|
if (typeof node === "function")
|
||||||
})
|
return;
|
||||||
forEach.call(mutation.removedNodes, function(node) {
|
checkForVideo(node, node.parentNode || mutation.target, true);
|
||||||
if (typeof node === "function")
|
});
|
||||||
return;
|
forEach.call(mutation.removedNodes, function(node) {
|
||||||
checkForVideo(node, node.parentNode || mutation.target, false);
|
if (typeof node === "function")
|
||||||
})
|
return;
|
||||||
});
|
checkForVideo(node, node.parentNode || mutation.target, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, {timeout: 1000});
|
||||||
});
|
});
|
||||||
observer.observe(document, { childList: true, subtree: true });
|
observer.observe(document, { childList: true, subtree: true });
|
||||||
|
|
||||||
@@ -349,7 +352,7 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function runAction(action, document, keyboard) {
|
function runAction(action, document, keyboard, e) {
|
||||||
var videoTags = document.getElementsByTagName('video');
|
var videoTags = document.getElementsByTagName('video');
|
||||||
videoTags.forEach = Array.prototype.forEach;
|
videoTags.forEach = Array.prototype.forEach;
|
||||||
|
|
||||||
@@ -366,14 +369,12 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
v.currentTime += tc.settings.advanceTime;
|
v.currentTime += tc.settings.advanceTime;
|
||||||
} else if (action === 'faster') {
|
} else if (action === 'faster') {
|
||||||
// Maximum playback speed in Chrome is set to 16:
|
// Maximum playback speed in Chrome is set to 16:
|
||||||
// https://cs.chromium.org/chromium/src/media/blink/webmediaplayer_impl.cc?l=103
|
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=168
|
||||||
var s = Math.min( (v.playbackRate < 0.1 ? 0.0 : v.playbackRate) + tc.settings.speedStep, 16);
|
var s = Math.min( (v.playbackRate < 0.1 ? 0.0 : v.playbackRate) + tc.settings.speedStep, 16);
|
||||||
v.playbackRate = Number(s.toFixed(2));
|
v.playbackRate = Number(s.toFixed(2));
|
||||||
} else if (action === 'slower') {
|
} else if (action === 'slower') {
|
||||||
// Audio playback is cut at 0.05:
|
|
||||||
// https://cs.chromium.org/chromium/src/media/filters/audio_renderer_algorithm.cc?l=49
|
|
||||||
// Video min rate is 0.0625:
|
// Video min rate is 0.0625:
|
||||||
// https://cs.chromium.org/chromium/src/media/blink/webmediaplayer_impl.cc?l=102
|
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=167
|
||||||
var s = Math.max(v.playbackRate - tc.settings.speedStep, 0.0625);
|
var s = Math.max(v.playbackRate - tc.settings.speedStep, 0.0625);
|
||||||
v.playbackRate = Number(s.toFixed(2));
|
v.playbackRate = Number(s.toFixed(2));
|
||||||
} else if (action === 'reset') {
|
} else if (action === 'reset') {
|
||||||
@@ -382,7 +383,7 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
controller.classList.add('vsc-manual');
|
controller.classList.add('vsc-manual');
|
||||||
controller.classList.toggle('vsc-hidden');
|
controller.classList.toggle('vsc-hidden');
|
||||||
} else if (action === 'drag') {
|
} else if (action === 'drag') {
|
||||||
handleDrag(v, controller);
|
handleDrag(v, controller, e);
|
||||||
} else if (action === 'fast') {
|
} else if (action === 'fast') {
|
||||||
resetSpeed(v, tc.settings.fastSpeed);
|
resetSpeed(v, tc.settings.fastSpeed);
|
||||||
}
|
}
|
||||||
@@ -400,17 +401,32 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDrag(video, controller) {
|
function handleDrag(video, controller, e) {
|
||||||
const parentElement = controller.parentElement,
|
const shadowController = controller.querySelector('#controller');
|
||||||
shadowController = controller.querySelector('#controller');
|
|
||||||
|
// Find nearest parent of same size as video parent.
|
||||||
|
var parentElement = controller.parentElement;
|
||||||
|
while (parentElement.parentNode &&
|
||||||
|
parentElement.parentNode.offsetHeight === parentElement.offsetHeight &&
|
||||||
|
parentElement.parentNode.offsetWidth === parentElement.offsetWidth) {
|
||||||
|
parentElement = parentElement.parentNode;
|
||||||
|
}
|
||||||
|
|
||||||
video.classList.add('vcs-dragging');
|
video.classList.add('vcs-dragging');
|
||||||
shadowController.classList.add('dragging');
|
shadowController.classList.add('dragging');
|
||||||
|
|
||||||
|
const initialMouseXY = [e.clientX, e.clientY];
|
||||||
|
const initialControllerXY = [
|
||||||
|
parseInt(shadowController.style.left),
|
||||||
|
parseInt(shadowController.style.top)
|
||||||
|
];
|
||||||
|
|
||||||
const startDragging = (e) => {
|
const startDragging = (e) => {
|
||||||
let style = shadowController.style;
|
let style = shadowController.style;
|
||||||
style.left = parseInt(style.left) + e.movementX + 'px';
|
let dx = e.clientX - initialMouseXY[0];
|
||||||
style.top = parseInt(style.top) + e.movementY + 'px';
|
let dy = e.clientY -initialMouseXY[1];
|
||||||
|
style.left = (initialControllerXY[0] + dx) + 'px';
|
||||||
|
style.top = (initialControllerXY[1] + dy) + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
const stopDragging = () => {
|
const stopDragging = () => {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Video Speed Controller",
|
"name": "Video Speed Controller",
|
||||||
"short_name": "videospeed",
|
"short_name": "videospeed",
|
||||||
"version": "0.4.9.4",
|
"version": "0.5.0",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "Speed up, slow down, advance and rewind any HTML5 video with quick shortcuts.",
|
"description": "Speed up, slow down, advance and rewind any HTML5 video with quick shortcuts.",
|
||||||
"homepage_url": "https://github.com/codebicycle/videospeed",
|
"homepage_url": "https://github.com/codebicycle/videospeed",
|
||||||
|
Reference in New Issue
Block a user