Skip to content

Instantly share code, notes, and snippets.

@1oh1
Last active April 18, 2025 20:50
Show Gist options
  • Save 1oh1/a52f038ec169f44a5386c14078b0e17d to your computer and use it in GitHub Desktop.
Save 1oh1/a52f038ec169f44a5386c14078b0e17d to your computer and use it in GitHub Desktop.
Hotstar Subtitles on Rewind
// ==UserScript==
// @name Hotstar Subtitles on Rewind (with Hotkey & Toast UI)
// @namespace http://tampermonkey.net/
// @version 2.0
// @description Auto-enable subtitles for 15s on rewind, with hotkeys and on-screen feedback
// @match https://www.hotstar.com/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
let timeoutId = null;
let subtitleMode = 'auto'; // 'auto', 'on', 'off'
function simulateClick(el) {
if (el) {
el.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
el.click();
}
}
function openAudioSubtitlesMenu() {
const icon = document.querySelector('i.icon-subtitle-line');
const button = icon?.closest('button');
if (button) {
simulateClick(button);
return true;
}
return false;
}
function waitForSubtitleButtons(timeout = 5000) {
return new Promise((resolve, reject) => {
const endTime = Date.now() + timeout;
function check() {
const allButtons = document.querySelectorAll('button, [role="button"]');
if (allButtons.length >= 17) {
resolve(Array.from(allButtons));
} else if (Date.now() > endTime) {
reject('Subtitle buttons did not appear');
} else {
setTimeout(check, 100);
}
}
check();
});
}
async function setSubtitlesTo(label, clickCount = 1) {
try {
const opened = openAudioSubtitlesMenu();
if (!opened) throw new Error('Could not open Audio & Subtitles menu');
const buttons = await waitForSubtitleButtons();
const matches = buttons.filter(btn => btn.textContent.trim().toLowerCase() === label.toLowerCase());
if (matches.length === 0) throw new Error(`No button found for "${label}"`);
let clicked = 0;
for (let i = 0; i < matches.length && clicked < clickCount; i++) {
simulateClick(matches[i]);
clicked++;
}
console.log(`[Hotstar] Clicked "${label}" ${clicked} time(s).`);
} catch (err) {
console.warn('[Hotstar] Subtitle change failed:', err);
}
}
function triggerSubtitleWindow() {
if (subtitleMode !== 'auto') return;
if (timeoutId) clearTimeout(timeoutId);
setSubtitlesTo('English', 2);
timeoutId = setTimeout(() => {
setSubtitlesTo('Off', 1);
}, 15000);
}
function setupRewindListener() {
const observer = new MutationObserver(() => {
const rewindBtn = document.querySelector('[data-testid="seek-rewind"]');
if (rewindBtn && !rewindBtn.dataset.listenerAdded) {
rewindBtn.dataset.listenerAdded = 'true';
rewindBtn.addEventListener('click', triggerSubtitleWindow);
console.log('[Hotstar] Rewind listener (button) attached');
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
function getUiContainer() {
return document.fullscreenElement || document.body;
}
function showToast(message, duration = 3000) {
const container = getUiContainer();
const toast = document.createElement('div');
toast.textContent = message;
toast.style.cssText = `
position: fixed;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
background: rgba(0,0,0,0.85);
color: white;
padding: 10px 20px;
border-radius: 8px;
font-size: 14px;
z-index: 9999;
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
`;
container.appendChild(toast);
requestAnimationFrame(() => {
toast.style.opacity = '1';
});
setTimeout(() => {
toast.style.opacity = '0';
setTimeout(() => toast.remove(), 300);
}, duration);
}
function showHelpBox() {
const container = getUiContainer();
const existing = container.querySelector('#hotstar-help-box');
if (existing) {
existing.remove();
return;
}
const box = document.createElement('div');
box.id = 'hotstar-help-box';
box.innerHTML = `
<div style="font-weight:bold; margin-bottom: 5px;">Hotstar Subtitle Hotkeys:</div>
<ul style="margin: 0; padding-left: 18px;">
<li><strong>Shift + Alt + E</strong> — Enable English subtitles permanently</li>
<li><strong>Shift + Alt + D</strong> — Disable subtitles permanently</li>
<li><strong>Shift + Alt + A</strong> — Auto mode (15s subtitles on rewind)</li>
<li><strong>Shift + Alt + ?</strong> — Show/hide this help menu</li>
</ul>
<div style="margin-top: 10px; text-align: right;">
<button id="close-help-btn" style="padding: 4px 8px; font-size: 12px;">Close</button>
</div>
`;
box.style.cssText = `
position: fixed;
top: 60px;
right: 60px;
background: #111;
color: #fff;
border-radius: 10px;
padding: 15px 20px;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
font-family: sans-serif;
font-size: 13px;
z-index: 10000;
max-width: 300px;
`;
container.appendChild(box);
box.querySelector('#close-help-btn').onclick = () => box.remove();
}
function setupKeyboardListener() {
window.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') {
triggerSubtitleWindow();
}
if (e.altKey && e.shiftKey) {
const key = e.key.toLowerCase();
if (key === 'e') {
subtitleMode = 'on';
clearTimeout(timeoutId);
setSubtitlesTo('English', 2);
showToast('Subtitles: ON (English)');
}
if (key === 'd') {
subtitleMode = 'off';
clearTimeout(timeoutId);
setSubtitlesTo('Off', 1);
showToast('Subtitles: OFF');
}
if (key === 'a') {
subtitleMode = 'auto';
showToast('Subtitles: AUTO (15s on rewind)');
}
if (key === '?') {
showHelpBox();
}
}
});
}
setTimeout(() => {
setupRewindListener();
setupKeyboardListener();
}, 3000);
})();
@1oh1
Copy link
Author

1oh1 commented Apr 18, 2025

🎬 Hotstar Subtitles Userscript

This userscript enhances your viewing experience on Hotstar.com by making subtitles smarter and more accessible with keyboard shortcuts:

✨ Features

  • Auto Subtitles on Rewind
    Whenever you click the "Rewind 10s" button or press the ← Left Arrow key, English subtitles will be enabled automatically for 15 seconds, then disabled. Perfect for catching missed dialogue without turning subs on permanently.

  • Subtitle Control Hotkeys
    Toggle subtitle behavior with simple keyboard combos:

    • Shift + Alt + E → Permanently enable English subtitles
    • Shift + Alt + D → Permanently disable subtitles
    • Shift + Alt + A → Return to Auto Mode (15s on rewind)
    • Shift + Alt + ? → Show or hide the help popup
  • Fullscreen Compatible
    Works seamlessly even in fullscreen mode — UI messages and help box show up correctly over the video.

  • Toast Notifications
    Displays a short message on-screen whenever the mode is changed, so you always know what subtitle mode you're in.


🛠 How to Use

  1. Install a userscript manager like Tampermonkey or Violentmonkey
  2. Create a new userscript and paste the script code
  3. Visit Hotstar.com and enjoy the enhanced experience!

Inspired by ThioJoe: https://www.youtube.com/watch?v=YM0lVVFBZ5w
Fully generated by ChatGPT

Need more features or language support? Ask ChatGPT!

@1oh1
Copy link
Author

1oh1 commented Apr 18, 2025

QS7uMax.1.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment