kick 레이턴시 줄이기
// ==UserScript==
// @name Killing Kick Latency
// @namespace http://tampermonkey.net/
// @version 1.01
// @description kick 레이턴시 줄이기
// @author purirun
// @match https://www.kick.com/*
// @match https://kick.com/*
// @grant none
// @run-at document-idle
// @license MIT
// ==/UserScript==
(function () {
const VIDEO_SEL = 'video';
let delayText = null;
let isCooling = false;
let chaseInterval = null;
function getControlBar() {
const all = document.querySelectorAll('.z-controls');
// absolute bottom-0 인 컨트롤바
return [...all].find(el => el.classList.contains('bottom-0'));
}
function createSyncBtn() {
if (document.getElementById('kick-tiny-sync')) return;
const bar = getControlBar();
if (!bar) return;
// index 1 = 오른쪽 버튼 그룹
const rightGroup = bar.children[1];
if (!rightGroup) return;
const syncBtn = document.createElement('div');
syncBtn.id = 'kick-tiny-sync';
syncBtn.title = '클릭하면 딜레이가 즉시 동기화됩니다.';
syncBtn.style.cssText = [
'display:inline-flex',
'align-items:center',
'gap:5px',
'background:rgba(255,255,255,0.1)',
'border:1px solid transparent',
'border-radius:6px',
'padding:3px 8px',
'cursor:pointer',
'user-select:none',
'transition:all 0.2s',
'font-family:monospace',
'height:32px',
'box-sizing:border-box',
'flex-shrink:0',
].join(';');
syncBtn.onmouseover = () => {
syncBtn.style.background = 'rgba(255,255,255,0.2)';
syncBtn.style.border = '1px solid #53FC18';
};
syncBtn.onmouseout = () => {
if (!isCooling) {
syncBtn.style.background = 'rgba(255,255,255,0.1)';
syncBtn.style.border = '1px solid transparent';
}
};
const icon = document.createElement('span');
icon.innerText = '⚡';
icon.style.fontSize = '12px';
delayText = document.createElement('span');
delayText.innerText = '-.-s';
delayText.style.cssText = 'font-size:12px;font-weight:bold;color:#fff;line-height:1;white-space:nowrap;';
syncBtn.appendChild(icon);
syncBtn.appendChild(delayText);
syncBtn.onclick = (e) => {
e.preventDefault();
e.stopPropagation();
if (isCooling) return;
const vid = document.querySelector(VIDEO_SEL);
if (!vid) return;
// 버퍼 끝으로 점프
if (vid.buffered.length > 0) {
vid.currentTime = vid.buffered.end(vid.buffered.length - 1) - 0.3;
} else {
vid.currentTime = vid.duration;
}
// 딜레이 남아있으면 1.3배속으로 추격
if (chaseInterval) clearInterval(chaseInterval);
chaseInterval = setInterval(() => {
const v = document.querySelector(VIDEO_SEL);
if (!v) { clearInterval(chaseInterval); return; }
const delay = v.buffered.length > 0
? v.buffered.end(v.buffered.length - 1) - v.currentTime
: 0;
if (delay > 1) {
v.playbackRate = 1.3;
} else {
v.playbackRate = 1.0;
clearInterval(chaseInterval);
}
}, 200);
isCooling = true;
delayText.innerText = 'OK!';
delayText.style.color = '#53FC18';
syncBtn.style.border = '1px solid #53FC18';
setTimeout(() => {
isCooling = false;
syncBtn.style.border = '1px solid transparent';
syncBtn.style.background = 'rgba(255,255,255,0.1)';
}, 1500);
};
// 오른쪽 그룹의 첫 번째 버튼 앞에 삽입
const firstBtn = rightGroup.querySelector('button');
if (firstBtn) {
rightGroup.insertBefore(syncBtn, firstBtn);
} else {
rightGroup.appendChild(syncBtn);
}
}
// 딜레이 수치 갱신
setInterval(() => {
if (!document.getElementById('kick-tiny-sync')) {
delayText = null;
createSyncBtn();
return;
}
if (!delayText || isCooling) return;
const vid = document.querySelector(VIDEO_SEL);
if (!vid || vid.paused) {
delayText.innerText = '---';
delayText.style.color = '#888';
return;
}
if (vid.buffered.length > 0) {
const delay = Math.max(0, vid.buffered.end(vid.buffered.length - 1) - vid.currentTime);
delayText.innerText = delay.toFixed(1) + 's';
delayText.style.color = delay < 1.5 ? '#53FC18' : delay < 3 ? '#FFD700' : '#FF4D4D';
} else {
delayText.innerText = '???';
delayText.style.color = '#888';
}
}, 500);
// 초기 생성 - 컨트롤바는 hover시에만 나타나므로 계속 재시도
let attempts = 0;
const initInterval = setInterval(() => {
if (document.body) {
createSyncBtn();
if (document.getElementById('kick-tiny-sync')) clearInterval(initInterval);
}
if (++attempts >= 40) clearInterval(initInterval);
}, 500);
})();