Skip to content

Instantly share code, notes, and snippets.

@yukulele
Last active May 20, 2024 21:42
Show Gist options
  • Save yukulele/805c382f371852e8f25efd7b2ec5876a to your computer and use it in GitHub Desktop.
Save yukulele/805c382f371852e8f25efd7b2ec5876a to your computer and use it in GitHub Desktop.

Twitter native video player

Replace the user-unfriendly Twitter video player with the browser's native video player.

This allows you to:

  • seek backward/forward with the / keys
  • change the volume with the / keys
  • switch full screen with double-click or f key
  • access the video's contextual menu
  • change the playback speed with the + / - and 0 keys or via the contextual menu
  • share the playback speed between videos

install: https://gist.github.com/yukulele/805c382f371852e8f25efd7b2ec5876a/raw/twitter-native-video-player.user.js

Display the source blob
Display the rendered blob
Raw
<svg width="48" height="48" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<rect fill="#fff" y="6" width="48" height="36" rx="5" />
<rect fill="#1CB7EB" x="1" y="7" width="46" height="34" rx="4" />
<path
d="M36.8 15.4c-.9.5-2 .8-3 .9 1.1-.7 1.9-1.8 2.3-3.1-1 .6-2.1 1.1-3.4 1.4-1-1.1-2.3-1.8-3.8-1.8-2.9 0-5.3 2.5-5.3 5.7 0 .4 0 .9.1 1.3-4.4-.2-8.3-2.5-10.9-5.9-.5.8-.7 1.8-.7 2.9 0 2 .9 3.7 2.3 4.7-.9 0-1.7-.3-2.4-.7v.1c0 2.7 1.8 5 4.2 5.6-.4.1-.9.2-1.4.2-.3 0-.7 0-1-.1.7 2.3 2.6 3.9 4.9 3.9-1.8 1.5-4.1 2.4-6.5 2.4-.4 0-.8 0-1.3-.1 2.3 1.6 5.1 2.6 8.1 2.6 9.7 0 15-8.6 15-16.1v-.7c1.2-1 2.1-2 2.8-3.2z"
fill="#FFF" />
</svg>
// ==UserScript==
// @name Twitter native video player
// @namespace https://gist.github.com/yukulele/805c382f371852e8f25efd7b2ec5876a
// @match https://twitter.com/*
// @match https://mobile.twitter.com/*
// @match https://x.com/*
// @match https://mobile.x.com/*
// @grant GM.getValue
// @grant GM.setValue
// @version 1.0.11
// @author yukulele
// @homepage https://gist.github.com/yukulele/805c382f371852e8f25efd7b2ec5876a
// @description Replace the user-unfriendly Twitter video player with the browser's native video player. This allows you to: seek backward/forward with the left/right keyboard keys, change the volume with the up/down keyboard keys, switch to full screen with double-click of f key, access the video's contextual menu, change the playback speed with the <kbd>+</kbd>, <kbd>-</kbd> and <kbd>0</kbd> keys or via the contextual menu, share the playback speed between videos.
// @icon https://gist.github.com/yukulele/805c382f371852e8f25efd7b2ec5876a/raw/twitter-native-video-player-icon.svg
// @downloadURL https://gist.github.com/yukulele/805c382f371852e8f25efd7b2ec5876a/raw/twitter-native-video-player.user.js
// @updateURL https://gist.github.com/yukulele/805c382f371852e8f25efd7b2ec5876a/raw/twitter-native-video-player.user.js
// @supportURL https://gist.github.com/yukulele/805c382f371852e8f25efd7b2ec5876a#comments
// @inject-into auto
// ==/UserScript==
let timeout
async function nativePlayer(video) {
video.playbackRate = await GM.getValue('playbackRate') ?? 1
video.addEventListener('ratechange', () => GM.setValue('playbackRate', video.playbackRate))
video.addEventListener('mouseenter', () => showControls(video))
video.addEventListener('mouseleave', () => hideControls(video))
video.addEventListener('keydown', e => keyboard(e, video))
video.style.zIndex = 1
video.focus()
}
function showControls(video) {
clearTimeout(timeout)
video.controls = true
}
function hideControls(video) {
clearTimeout(timeout)
timeout = setTimeout(() => video.controls = false, 1000)
}
function toggleFullscreen(video) {
if (document.fullscreenElement) return document.exitFullscreen()
video.requestFullscreen()
}
function keyboard(e, video) {
if (e.key === 'f') return toggleFullscreen(video)
if (e.key === '0' || e.code === 'Numpad0') return video.playbackRate = 1
if (e.key === '+') return video.playbackRate += 0.05
if (e.key === '-') return video.playbackRate -= 0.05
}
new MutationObserver(mutationsList => {
for (var mutation of mutationsList) {
if (mutation.type !== 'childList') continue
for (const node of mutation.addedNodes) {
if (!(node instanceof HTMLElement)) continue
for (const video of node.querySelectorAll('video')) nativePlayer(video)
}
}
}).observe(document.documentElement, {
childList: true,
subtree: true,
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment