<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Synchronization on mhbxyz.me</title><link>https://mhbxyz.github.io/en/tags/synchronization/</link><description>Recent content in Synchronization on mhbxyz.me</description><generator>Hugo</generator><language>en</language><lastBuildDate>Mon, 19 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://mhbxyz.github.io/en/tags/synchronization/index.xml" rel="self" type="application/rss+xml"/><item><title>OpenWatchParty: synchronize playback despite latency</title><link>https://mhbxyz.github.io/en/articles/openwatchparty-synchronize-playback-despite-latency/</link><pubDate>Mon, 19 Oct 2026 00:00:00 +0000</pubDate><guid>https://mhbxyz.github.io/en/articles/openwatchparty-synchronize-playback-despite-latency/</guid><description>&lt;p&gt;In my &lt;a href="https://mhbxyz.github.io/en/articles/openwatchparty-synchronized-watch-parties-for-jellyfin/"&gt;first OpenWatchParty article&lt;/a&gt;, I introduced the Jellyfin plugin and its Rust session server. The harder question remained: how do you make the same scene play at the same time on several machines when their clocks, networks, and players behave differently?&lt;/p&gt;


&lt;h2 id="establish-a-shared-clock"&gt;Establish a shared clock&lt;/h2&gt;
&lt;p&gt;The server cannot assume that two computers display the same time. The client therefore sends a timestamped ping. When the response arrives, it measures the round-trip time and estimates the offset between its clock and the server&amp;rsquo;s. Several measurements are smoothed so that a latency spike does not cause a sudden jump.&lt;/p&gt;</description></item><item><title>OpenWatchParty: Synchronized Watch Parties for Jellyfin</title><link>https://mhbxyz.github.io/en/articles/openwatchparty-synchronized-watch-parties-for-jellyfin/</link><pubDate>Mon, 19 Jan 2026 00:00:00 +0000</pubDate><guid>https://mhbxyz.github.io/en/articles/openwatchparty-synchronized-watch-parties-for-jellyfin/</guid><description>&lt;h2 id="what-is-openwatchparty"&gt;What is OpenWatchParty?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;OpenWatchParty&lt;/strong&gt; is a Jellyfin plugin that enables synchronized media playback across multiple clients. Watch movies and shows with friends, wherever they are.&lt;/p&gt;
&lt;p&gt;Unlike Jellyfin&amp;rsquo;s built-in SyncPlay, OpenWatchParty uses a dedicated external session server, providing more reliable synchronization and better latency handling.&lt;/p&gt;


&lt;h2 id="architecture"&gt;Architecture&lt;/h2&gt;
&lt;p&gt;The system has three components:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Component&lt;/th&gt;
 &lt;th&gt;Technology&lt;/th&gt;
 &lt;th&gt;Role&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Jellyfin Plugin&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;C#&lt;/td&gt;
 &lt;td&gt;Delivers client JavaScript and configuration UI&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Session Server&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Rust&lt;/td&gt;
 &lt;td&gt;Manages rooms and relays synchronization messages over WebSocket&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Web Client&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;JavaScript&lt;/td&gt;
 &lt;td&gt;Embedded in the Jellyfin UI; coordinates playback&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class="mermaid-source"&gt;&lt;code class="language-mermaid"&gt;flowchart LR
 A[Client A] &amp;lt;--&amp;gt;|WebSocket| S[Session Server&amp;lt;br/&amp;gt;Rust]
 B[Client B] &amp;lt;--&amp;gt;|WebSocket| S
 C[Client C] &amp;lt;--&amp;gt;|WebSocket| S&lt;/code&gt;&lt;/pre&gt;



&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Real-time Synchronization&lt;/strong&gt;: Playback stays in sync across all participants&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Room-based Management&lt;/strong&gt;: Create and join watch party rooms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Host Control&lt;/strong&gt;: The party creator controls playback (play, pause, seek)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Latency Monitoring&lt;/strong&gt;: RTT (Round-Trip Time) measurement and display&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drift Correction&lt;/strong&gt;: Automatic playback rate adjustment to maintain sync&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HLS Support&lt;/strong&gt;: Works with transcoded content via HTTP Live Streaming&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JWT Authentication&lt;/strong&gt;: Secure user identity verification&lt;/li&gt;
&lt;/ul&gt;


&lt;h2 id="installation"&gt;Installation&lt;/h2&gt;


&lt;h3 id="1-deploy-the-session-server"&gt;1. Deploy the Session Server&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -d &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -p 3000:3000 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -e ALLOWED_ORIGINS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;https://your-jellyfin-domain.com &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ghcr.io/mhbxyz/openwatchparty-session-server:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="2-add-the-plugin-repository"&gt;2. Add the Plugin Repository&lt;/h3&gt;
&lt;p&gt;In the Jellyfin dashboard:&lt;/p&gt;</description></item></channel></rss>