-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
179 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,55 @@ | ||
# chrome-media-controller | ||
# chrome-media-controller | ||
|
||
|
||
A Chrome or Edge extension to use keyboard to control webpage media (video and audio). | ||
|
||
## 1. Installation | ||
|
||
(To be published onto the Chrome Web Store...) | ||
|
||
|
||
## 2. How to use | ||
|
||
| Key | Function | | ||
|-----|----------| | ||
| `k` | Play/pause | | ||
| `j` | Seek backward 10 seconds | | ||
| `l` | Seek forward 10 seconds | | ||
| `m` | Mute/unmute sound | | ||
| `w` | Increase volume | | ||
| `s` | Decrease volume | | ||
| `<` (Shift+`,`) | Slow down media playback speed | | ||
| `>` (Shift+`.`) | Speed up media playback speed | | ||
|
||
## 3. Which websites does this extension work on | ||
|
||
I have tested this extension on the following websites. Websites outside of this list may still work. | ||
|
||
### Fully compatible: | ||
|
||
* YouTube | ||
* HBO Max | ||
* Amazon Prime Video | ||
* Hulu | ||
* Paramount+ | ||
* Disney+ | ||
* Google Podcasts | ||
|
||
### Partially compatible: | ||
|
||
* Netflix | ||
- `j` and `l` can cause the Netflix webpage to shut down, so they are disabled | ||
- Please use ← and → (Netflix's default) to seek backward and forward | ||
|
||
### Not compatible at all: | ||
|
||
* [YouTube Music](https://music.youtube.com/) | ||
- YouTube music has its [unofficial shortcuts](https://support.google.com/youtubemusic/thread/180145/keyboard-shortcuts-web-player-cheat-sheet?hl=en) which are very different from this extension | ||
- Therfore, I have disabled this extension on YouTube Music | ||
* [Vimeo](https://vimeo.com/) | ||
- This extension does not work on Vimeo at all | ||
- [Here](https://help.vimeo.com/hc/en-us/articles/12425998125073-What-are-player-keyboard-shortcuts-) are Vimeo's official keyboard shortcuts, which unfortunately don't always work | ||
* Spotify | ||
- This extension does not work on Spotify at all | ||
* Amazon Prime Music | ||
- This extension does not work on Spotify at all |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
chrome.action.onClicked.addListener((tab) => { | ||
chrome.scripting.executeScript({ | ||
target: { tabId: tab.id }, | ||
files: ['content.js'] | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
document.addEventListener('keydown', handleKeyDown); | ||
|
||
|
||
function handleKeyDown(event) { | ||
if ( // k, j, l, m, <, > are already defined in YouTube | ||
window.location.hostname.includes('youtube.com') | ||
&& ['k', 'j', 'l', 'm', '<', '>'].includes(event.key) | ||
) { | ||
return; | ||
} | ||
|
||
if ( // j & l cause issues on Netflix | ||
window.location.hostname.includes('netflix.com') | ||
&& ['j', 'l'].includes(event.key) | ||
) { | ||
return; | ||
} | ||
|
||
const mediaElements = Array.from(document.querySelectorAll('video, audio')); | ||
|
||
mediaElements.forEach((media) => { | ||
const volumeStep = 0.05; | ||
const playbackRateStep = 0.1; | ||
|
||
switch (event.key) { | ||
case 'k': | ||
if (media.paused) media.play(); | ||
else media.pause(); | ||
break; | ||
case 'j': | ||
media.currentTime = Math.max(media.currentTime - 10, 0); | ||
break; | ||
case 'l': | ||
media.currentTime = Math.min(media.currentTime + 10, media.duration); | ||
break; | ||
case 'm': | ||
media.muted = !media.muted; | ||
break; | ||
case 's': | ||
newVolume = Math.max(media.volume - volumeStep, 0); | ||
media.volume = newVolume; | ||
showStatusPrompt(newVolume, 'Volume'); | ||
break; | ||
case 'w': | ||
newVolume = Math.min(media.volume + volumeStep, 1); | ||
media.volume = newVolume; | ||
showStatusPrompt(newVolume, 'Volume'); | ||
break; | ||
case '<': | ||
newPlaybackRate = Math.max(media.playbackRate - playbackRateStep, 0.5); | ||
media.playbackRate = newPlaybackRate; | ||
showStatusPrompt(newPlaybackRate, 'Speed'); | ||
break; | ||
case '>': | ||
newPlaybackRate = Math.min(media.playbackRate + 0.1, 2); | ||
media.playbackRate = newPlaybackRate; | ||
showStatusPrompt(newPlaybackRate, 'Speed'); | ||
break; | ||
} | ||
}); | ||
} | ||
|
||
|
||
function showStatusPrompt(status, name) { | ||
let statusPrompt = document.getElementById('status-prompt'); | ||
|
||
if (!statusPrompt) { | ||
statusPrompt = document.createElement('div'); | ||
statusPrompt.id = 'status-prompt'; | ||
statusPrompt.style.position = 'fixed'; | ||
statusPrompt.style.top = '10%'; | ||
statusPrompt.style.left = '50%'; | ||
statusPrompt.style.transform = 'translate(-50%, -50%)'; | ||
statusPrompt.style.padding = '10px'; | ||
statusPrompt.style.borderRadius = '5px'; | ||
statusPrompt.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; | ||
statusPrompt.style.color = 'white'; | ||
statusPrompt.style.fontSize = '18px'; | ||
statusPrompt.style.fontWeight = 'regular'; | ||
statusPrompt.style.zIndex = '9999'; | ||
document.body.appendChild(statusPrompt); | ||
} | ||
|
||
statusPrompt.textContent = `${name}: ${(status * 100).toFixed(0)}%`; | ||
statusPrompt.style.display = 'block'; | ||
|
||
clearTimeout(statusPrompt.timeout); | ||
statusPrompt.timeout = setTimeout(() => { | ||
statusPrompt.style.display = 'none'; | ||
}, 1000); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"manifest_version": 3, | ||
"name": "Media Controller", | ||
"description": "Control video/audio in the webpage with keyboard shortcuts", | ||
"version": "0.0.1", | ||
"icons": { | ||
"48": "icon.png" | ||
}, | ||
"permissions": [ | ||
"activeTab" | ||
], | ||
"action": { | ||
"default_popup": "", | ||
"default_icon": { | ||
"48": "icon.png" | ||
} | ||
}, | ||
"background": { | ||
"service_worker": "background.js" | ||
}, | ||
"content_scripts": [ | ||
{ | ||
"matches": ["<all_urls>"], | ||
"js": ["content.js"] | ||
} | ||
] | ||
} |