Compare commits

..

3 Commits

8 changed files with 58 additions and 15 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
<a href="https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc"><img src="https://img.shields.io/badge/Chrome-Download-blue?logo=googlechrome&logoColor=white" alt="Chrome Extension"></a>
</p>
<p align="center"><i>KoalaSync is a lightweight Browser Extension and Relay Server for synchronized video playback across any website—YouTube, Twitch, Netflix, and custom HTML5 players. Built with a focus on <b>Data Sovereignty</b> and <b>Performance</b>.</i></p>
<p align="center"><i>KoalaSync is a lightweight Browser Extension and Relay Server for synchronized video playback on almost any website with a video element—YouTube, Twitch, Netflix, Emby, Jellyfin, and beyond. Built with a focus on <b>Data Sovereignty</b> and <b>Performance</b>.</i></p>
### 🌟 Why KoalaSync?
+42 -4
View File
@@ -417,6 +417,10 @@
}
return;
}
// Suppress only SEEK during visibility grace period (tab re-focus ghost jump).
// Play/Pause pass through — user may want to immediately pause after tabbing back.
if (Date.now() < visibilityGraceUntil && action === EVENTS.SEEK) return;
chrome.runtime.sendMessage({
type: 'CONTENT_EVENT',
@@ -433,6 +437,38 @@
scheduleProactiveHeartbeat();
}
// --- Tab Visibility Handling ---
// Browsers (especially Firefox) aggressively throttle background tabs.
// When the user returns to a video tab, the video element may have lost
// time-sync and fires spurious seek events as it recovers (jumping back).
// We suppress only SEEK for a short grace period after tab re-focus.
// Play/Pause are NOT suppressed — the user may legitimately want to
// pause immediately after switching back.
let pageVisible = !document.hidden;
let visibilityGraceUntil = 0;
const VISIBILITY_GRACE_MS = 1000;
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
pageVisible = false;
} else if (!pageVisible) {
pageVisible = true;
visibilityGraceUntil = Date.now() + VISIBILITY_GRACE_MS;
reportLog(`Tab re-focused — suppressing seeks for ${VISIBILITY_GRACE_MS / 1000}s to prevent ghost relay`, 'warn');
}
});
// Reset on page hide/show (bfcache, tab discard)
window.addEventListener('pagehide', () => { pageVisible = false; });
window.addEventListener('pageshow', (event) => {
// event.persisted is true ONLY when restored from bfcache, not on initial load
if (event.persisted && !pageVisible) {
pageVisible = true;
visibilityGraceUntil = Date.now() + VISIBILITY_GRACE_MS;
reportLog(`Page restored from cache — suppressing seeks for ${VISIBILITY_GRACE_MS / 1000}s`, 'warn');
}
});
const handlePlay = () => reportEvent(EVENTS.PLAY);
const handlePause = () => reportEvent(EVENTS.PAUSE);
@@ -444,7 +480,7 @@
const current = video.currentTime;
if (!Number.isFinite(current)) return;
// Step 1: Check expectedEvents (programmatic seek suppression)
// Step 1: Check expectedEvents (programmatic seek from remote peer — ALWAYS process)
if (expectedEvents.has('seek')) {
expectedEvents.delete('seek');
if (expectedTimeouts['seek']) {
@@ -452,20 +488,22 @@
delete expectedTimeouts['seek'];
}
lastReportedSeekTime = current;
// No log — this is routine programmatic behavior (Force Sync, lobby, peer command)
return;
}
// Step 2: Suppress during visibility grace period (tab re-focus ghost events)
if (Date.now() < visibilityGraceUntil) return;
const delta = lastReportedSeekTime !== null ? Math.abs(current - lastReportedSeekTime) : null;
const deltaStr = delta !== null ? `Δ${delta.toFixed(2)}s` : 'Δ?';
// Step 2: Delta check — skip micro-seeks (buffering, chapter markers, etc.)
// Step 3: Delta check — skip micro-seeks (buffering, chapter markers, etc.)
if (lastReportedSeekTime !== null && delta < MIN_SEEK_DELTA) {
reportLog(`[Seek] Filtered (${deltaStr} < ${MIN_SEEK_DELTA}s threshold) @ ${current.toFixed(2)}s — not relayed`, 'warn');
return;
}
// Step 3: Debounce rapid consecutive seeks (e.g. scrubbing)
// Step 4: Debounce rapid consecutive seeks (e.g. scrubbing)
// — wait 800ms for the user to settle before relaying
if (seekDebounceTimer) clearTimeout(seekDebounceTimer);
seekDebounceTimer = setTimeout(() => {
+2 -2
View File
@@ -1,8 +1,8 @@
{
"manifest_version": 3,
"name": "KoalaSync",
"version": "1.8.5",
"description": "Watch party extension to synchronize video playback on YouTube, Twitch, Netflix, and HTML5 sites in real-time with friends.",
"version": "1.8.6",
"description": "Watch party extension to synchronize video playback on YouTube, Twitch, Netflix, Emby, Jellyfin, and any HTML5 site in real-time with friends.",
"permissions": [
"storage",
"tabs",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "koalasync",
"version": "1.8.6",
"version": "1.8.7",
"description": "KoalaSync Build Scripts",
"private": true,
"scripts": {
+1 -1
View File
@@ -7,7 +7,7 @@
*/
export const PROTOCOL_VERSION = "1.0.0";
export const APP_VERSION = "1.3.1";
export const APP_VERSION = "1.8.6";
export const OFFICIAL_SERVER_URL = 'wss://syncserver.koalastuff.net';
export const OFFICIAL_LANDING_PAGE_URL = 'https://sync.koalastuff.net';
+7 -4
View File
@@ -3,15 +3,18 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KoalaSync | Real-time Video Synchronization for Friends</title>
<meta name="description" content="Watch YouTube, Twitch, and HTML5 videos in sync with friends. KoalaSync is a privacy-first, open-source browser extension for Chrome and Firefox.">
<title>KoalaSync | Sync Netflix, Emby, Jellyfin & Any Video with Friends Browser Extension</title>
<meta name="description" content="Watch Netflix, Emby, Jellyfin, YouTube, Twitch and any HTML5 video in perfect sync with friends. KoalaSync is a privacy-first, open-source browser extension for Chrome and Firefox. Works on almost any site with a video element.">
<link rel="stylesheet" href="style.css">
<link rel="icon" type="image/png" href="assets/logo.png">
<meta property="og:title" content="KoalaSync | Sync your videos">
<meta property="og:description" content="Watch together, stay in sync. Privacy-first video synchronization.">
<link rel="canonical" href="https://sync.koalastuff.net/">
<meta name="robots" content="index, follow">
<meta property="og:title" content="KoalaSync | Sync Netflix, Emby, Jellyfin & Any Video with Friends">
<meta property="og:description" content="Watch Netflix, Emby, Jellyfin, YouTube, Twitch and any HTML5 video in perfect sync. Privacy-first, open-source browser extension for Chrome & Firefox.">
<meta property="og:image" content="https://sync.koalastuff.net/assets/logo.png">
<meta property="og:type" content="website">
<meta property="og:url" content="https://sync.koalastuff.net/">
<script src="lang-init.js"></script>
</head>
+2
View File
@@ -1,4 +1,6 @@
# KoalaSync Website — Allow all crawlers, full indexing
User-agent: *
Allow: /
# Sitemap for search engines
Sitemap: https://sync.koalastuff.net/sitemap.xml
+2 -2
View File
@@ -1,4 +1,4 @@
{
"version": "1.8.5",
"date": "2026-05-25T21:56:58Z"
"version": "1.8.6",
"date": "2026-05-25T23:07:55Z"
}