<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://hasoft.pl/blog</id>
    <title>Hasoft Blog</title>
    <updated>2026-08-16T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://hasoft.pl/blog"/>
    <subtitle>Hasoft Blog</subtitle>
    <icon>https://hasoft.pl/img/logo.svg</icon>
    <entry>
        <title type="html"><![CDATA[So, You Want to Migrate to Better Player?]]></title>
        <id>https://hasoft.pl/blog/better-player-migration</id>
        <link href="https://hasoft.pl/blog/better-player-migration"/>
        <updated>2026-08-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A comprehensive guide for migrating your Flutter app from video_player or Chewie to Better Player for advanced media features.]]></summary>
        <content type="html"><![CDATA[<p>Let’s be honest: we’ve all been there. You start a Flutter project, throw in the official <code>video_player</code> package, and think, <em>"Hey, this is pretty easy."</em></p>
<p>Then the client—or your own product roadmap—hits you with real-world requirements:</p>
<ul>
<li class=""><em>"Can we cache videos so users don't burn through their data?"</em></li>
<li class=""><em>"Why does the player controls overlay break when I rotate the phone?"</em></li>
<li class=""><em>"Can we add subtitles? And picture-in-picture? And a custom loading spinner?"</em></li>
</ul>
<p>Suddenly, you’re drowning in platform channels, custom gesture detectors, and a spaghetti mess of state management just to keep a simple video playing smoothly.</p>
<p>If you're currently wrapping your head around this and considering a switch to <strong>Better Player</strong> (or trying to decide between it and Chewie), let's walk through what the transition actually looks like in practice.</p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="The-Big-Question-Why-Better-Player">The Big Question: Why Better Player?<a href="https://hasoft.pl/blog/better-player-migration#The-Big-Question-Why-Better-Player" class="hash-link" aria-label="Direct link to The Big Question: Why Better Player?" title="Direct link to The Big Question: Why Better Player?" translate="no">​</a></h2>
<ul>
<li class=""><strong>If you're coming from raw <code>video_player</code>:</strong> You're basically writing your own media player UI from scratch. Better Player gives you full player controls, fullscreen handling, subtitle support, caching, and notification hooks right out of the box.</li>
<li class=""><strong>If you're coming from Chewie:</strong> Chewie is a nice lightweight wrapper, but it can feel restrictive once you need deep customization, bulletproof list/feed playback, or complex HLS/DASH configurations. Better Player is built heavier, but it's faster than ever thanks to modern JNI/FFI native bridges.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="Step-1-Swap-the-Dependencies">Step 1: Swap the Dependencies<a href="https://hasoft.pl/blog/better-player-migration#Step-1-Swap-the-Dependencies" class="hash-link" aria-label="Direct link to Step 1: Swap the Dependencies" title="Direct link to Step 1: Swap the Dependencies" translate="no">​</a></h2>
<p>First things first, open up your <code>pubspec.yaml</code>. If you were using Chewie, kick it out.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token key atrule">dependencies</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">flutter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">sdk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> flutter</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Bye-bye, chewie! 👋</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">better_player</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ^1.2.0 </span><br></div></code></pre></div></div>
<p>Run <code>flutter pub get</code>. If you're upgrading from an older version of Better Player (0.x.x), checking out the section below is your first stop.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="Upgrading-from-Older-Versions">Upgrading from Older Versions<a href="https://hasoft.pl/blog/better-player-migration#Upgrading-from-Older-Versions" class="hash-link" aria-label="Direct link to Upgrading from Older Versions" title="Direct link to Upgrading from Older Versions" translate="no">​</a></h2>
<p>If you're already using Better Player and just want to upgrade to the faster, cleaner modern version, there's good news: you don't have to rename everything manually.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="The-Magic-Command">The "Magic" Command<a href="https://hasoft.pl/blog/better-player-migration#The-Magic-Command" class="hash-link" aria-label="Direct link to The &quot;Magic&quot; Command" title="Direct link to The &quot;Magic&quot; Command" translate="no">​</a></h3>
<p>Flutter's <code>dart fix</code> tool can handle most of the renames for you. Simply run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">dart fix --apply</span><br></div></code></pre></div></div>
<p>This will automatically swap names like <code>BetterPlayerConfiguration</code> to <code>PlayerConfiguration</code> across your entire project.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="Why-the-Change">Why the Change?<a href="https://hasoft.pl/blog/better-player-migration#Why-the-Change" class="hash-link" aria-label="Direct link to Why the Change?" title="Direct link to Why the Change?" translate="no">​</a></h3>
<p>This isn't just about cleaner names. It's a fundamental architectural shift:</p>
<ul>
<li class=""><strong>Direct Native Bridges:</strong> Better Player now bypasses the slow <code>MethodChannel</code> serialization. It uses <strong>JNI (Android)</strong> and <strong>Swift FFI (iOS)</strong> to talk directly to the native media engines.</li>
<li class=""><strong>Federated Architecture:</strong> The core logic is now decoupled from platform-specific code, making it more stable and easier to maintain.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="Step-2-Ditching-Raw-video_player">Step 2: Ditching Raw <code>video_player</code><a href="https://hasoft.pl/blog/better-player-migration#Step-2-Ditching-Raw-video_player" class="hash-link" aria-label="Direct link to Step-2-Ditching-Raw-video_player" title="Direct link to Step-2-Ditching-Raw-video_player" translate="no">​</a></h2>
<p>If you've been using vanilla <code>video_player</code>, you know the drill: initialize the controller, add a listener, check if it's initialized, wrap it in an <code>AspectRatio</code>, and manually build your own play/pause buttons if you want anything interactive.</p>
<p>Here is roughly what your old code looked like:</p>
<div class="language-dart codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dart codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// The old, boilerplate-heavy way</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">MyOldPlayer</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">StatefulWidget</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token metadata function" style="color:rgb(80, 250, 123)">@override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  _MyOldPlayerState </span><span class="token function" style="color:rgb(80, 250, 123)">createState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">_MyOldPlayerState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> _MyOldPlayerState </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">State</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics class-name">MyOldPlayer</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  late </span><span class="token class-name">VideoPlayerController</span><span class="token plain"> _controller</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token metadata function" style="color:rgb(80, 250, 123)">@override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">initState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">initState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    _controller </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">VideoPlayerController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">networkUrl</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">Uri</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-literal string" style="color:rgb(255, 121, 198)">'https://example.com/video.mp4'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">initialize</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">then</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">_</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">setState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// wait for it...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token metadata function" style="color:rgb(80, 250, 123)">@override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">dispose</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    _controller</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">dispose</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">dispose</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token metadata function" style="color:rgb(80, 250, 123)">@override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token class-name">Widget</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">BuildContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> _controller</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">isInitialized</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token operator">?</span><span class="token plain"> </span><span class="token class-name">AspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            aspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> _controller</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">aspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">            child</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">VideoPlayer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">_controller</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">Center</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">child</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">CircularProgressIndicator</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>Now, look at how clean that gets with Better Player. No manual initialization checks, no separate loading state boilerplate:</p>
<div class="language-dart codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dart codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// The Better Player way ✨</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">MyBetterPlayer</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">StatefulWidget</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token metadata function" style="color:rgb(80, 250, 123)">@override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  _MyBetterPlayerState </span><span class="token function" style="color:rgb(80, 250, 123)">createState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">_MyBetterPlayerState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> _MyBetterPlayerState </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">State</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token generics class-name">MyBetterPlayer</span><span class="token generics punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  late </span><span class="token class-name">BetterPlayerController</span><span class="token plain"> _betterPlayerController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token metadata function" style="color:rgb(80, 250, 123)">@override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">initState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">initState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// 1. Setup your behavior and styling preferences</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">final</span><span class="token plain"> config </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">PlayerConfiguration</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      aspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">16</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> </span><span class="token number">9</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      autoPlay</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      looping</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// 2. Point it to your source</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">final</span><span class="token plain"> dataSource </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">PlayerDataSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token class-name">DataSourceType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">network</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"https://example.com/video.mp4"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    _betterPlayerController </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">BetterPlayerController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> betterPlayerDataSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> dataSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token metadata function" style="color:rgb(80, 250, 123)">@override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">dispose</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    _betterPlayerController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">dispose</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">dispose</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token metadata function" style="color:rgb(80, 250, 123)">@override</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token class-name">Widget</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token class-name">BuildContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token class-name">AspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      aspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">16</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> </span><span class="token number">9</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      child</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BetterPlayer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">controller</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> _betterPlayerController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>That's it. It handles the loading spinner, controls overlay, and sizing out of the box.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="Step-3-Migrating-from-Chewie">Step 3: Migrating from Chewie<a href="https://hasoft.pl/blog/better-player-migration#Step-3-Migrating-from-Chewie" class="hash-link" aria-label="Direct link to Step 3: Migrating from Chewie" title="Direct link to Step 3: Migrating from Chewie" translate="no">​</a></h2>
<p>If you were already using Chewie, switching to Better Player is even less painful because the conceptual model is almost identical. Both use a controller + widget setup.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="The-configuration-shift">The configuration shift<a href="https://hasoft.pl/blog/better-player-migration#The-configuration-shift" class="hash-link" aria-label="Direct link to The configuration shift" title="Direct link to The configuration shift" translate="no">​</a></h3>
<p>In Chewie, everything lived inside the <code>ChewieController</code>:</p>
<div class="language-dart codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dart codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// Chewie style</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">final</span><span class="token plain"> chewieController </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">ChewieController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  videoPlayerController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> videoPlayerController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  aspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">16</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> </span><span class="token number">9</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  autoPlay</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  materialProgressColors</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">ChewieProgressColors</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">playedColor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">Colors</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">red</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>In Better Player, configuration is cleanly split between <strong>how the player behaves</strong> (<code>PlayerConfiguration</code>) and <strong>where the video comes from</strong> (<code>PlayerDataSource</code>):</p>
<div class="language-dart codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dart codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// Better Player style</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">final</span><span class="token plain"> betterPlayerController </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">BetterPlayerController</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token class-name">PlayerConfiguration</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    aspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">16</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> </span><span class="token number">9</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    autoPlay</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  betterPlayerDataSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">PlayerDataSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token class-name">DataSourceType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">network</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"https://example.com/video.mp4"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="Step-4-Leveling-Up-Advanced-Features-Youll-Actually-Use">Step 4: Leveling Up (Advanced Features You’ll Actually Use)<a href="https://hasoft.pl/blog/better-player-migration#Step-4-Leveling-Up-Advanced-Features-Youll-Actually-Use" class="hash-link" aria-label="Direct link to Step 4: Leveling Up (Advanced Features You’ll Actually Use)" title="Direct link to Step 4: Leveling Up (Advanced Features You’ll Actually Use)" translate="no">​</a></h2>
<p>Once you've got the basic player rendering, you can unlock the features that make Better Player worth the migration effort.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-Bulletproof-Video-Caching">1. Bulletproof Video Caching<a href="https://hasoft.pl/blog/better-player-migration#1-Bulletproof-Video-Caching" class="hash-link" aria-label="Direct link to 1. Bulletproof Video Caching" title="Direct link to 1. Bulletproof Video Caching" translate="no">​</a></h3>
<p>If your app has a feed, a playlist, or users who might re-watch content, caching is a lifesaver. Without it, every scroll or repeat playback re-downloads the entire stream. Better Player handles this seamlessly under the hood:</p>
<div class="language-dart codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dart codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">final</span><span class="token plain"> dataSource </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">PlayerDataSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token class-name">DataSourceType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">network</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"https://example.com/heavy_video.mp4"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  cacheConfiguration</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">CacheConfiguration</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    useCache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    maxCacheSize</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">1024</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">1024</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// 200 MB max cache pool</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    maxCacheFileSize</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">20</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">1024</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">1024</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// individual file ceiling</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-Subtitles-That-Dont-Make-You-Cry">2. Subtitles That Don’t Make You Cry<a href="https://hasoft.pl/blog/better-player-migration#2-Subtitles-That-Dont-Make-You-Cry" class="hash-link" aria-label="Direct link to 2. Subtitles That Don’t Make You Cry" title="Direct link to 2. Subtitles That Don’t Make You Cry" translate="no">​</a></h3>
<p>Trying to overlay custom <code>.srt</code> or <code>.vtt</code> subtitles cleanly in <code>video_player</code> usually leads to custom UI positioning hacks. With Better Player, it's a first-class citizen:</p>
<div class="language-dart codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dart codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">final</span><span class="token plain"> dataSource </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">PlayerDataSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token class-name">DataSourceType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">network</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"https://example.com/video_with_audio.mp4"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  subtitles</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">PlayerSubtitlesSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">single</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">PlayerSubtitlesSourceType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">file</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"https://example.com/subtitles_en.srt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string-literal string" style="color:rgb(255, 121, 198)">"English Subtitles"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>Users can toggle them right from the built-in overflow menu without you writing a single line of subtitle UI code.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-Picture-in-Picture-PiP-Mode">3. Picture-in-Picture (PiP) Mode<a href="https://hasoft.pl/blog/better-player-migration#3-Picture-in-Picture-PiP-Mode" class="hash-link" aria-label="Direct link to 3. Picture-in-Picture (PiP) Mode" title="Direct link to 3. Picture-in-Picture (PiP) Mode" translate="no">​</a></h3>
<p>Users love floating video windows, especially on mobile. Better Player hooks into native Android and iOS PiP APIs with minimal fuss.
To enable it, make sure your configuration allows PiP and hook into your app lifecycle:</p>
<div class="language-dart codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dart codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">final</span><span class="token plain"> config </span><span class="token operator">=</span><span class="token plain"> </span><span class="token class-name">PlayerConfiguration</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  aspectRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">16</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> </span><span class="token number">9</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  autoPlay</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  allowedScreenSleep</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="Step-5-Handling-Feeds-and-Lists-Like-a-Pro-BetterPlayerListVideoPlayer">Step 5: Handling Feeds and Lists Like a Pro (<code>BetterPlayerListVideoPlayer</code>)<a href="https://hasoft.pl/blog/better-player-migration#Step-5-Handling-Feeds-and-Lists-Like-a-Pro-BetterPlayerListVideoPlayer" class="hash-link" aria-label="Direct link to Step-5-Handling-Feeds-and-Lists-Like-a-Pro-BetterPlayerListVideoPlayer" title="Direct link to Step-5-Handling-Feeds-and-Lists-Like-a-Pro-BetterPlayerListVideoPlayer" translate="no">​</a></h2>
<p>If you're building a scrollable feed (think TikTok, Instagram Reels, or a course video list), putting a standard <code>BetterPlayer</code> widget inside a <code>ListView</code> is a recipe for memory leaks and audio playing when videos are completely off-screen.</p>
<p>Instead, Better Player provides a dedicated widget called <strong><code>BetterPlayerListVideoPlayer</code></strong> for this exact scenario:</p>
<div class="language-dart codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dart codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token class-name">ListView</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">builder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  itemCount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> videoUrls</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">length</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  itemBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token class-name">BetterPlayerListVideoPlayer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token class-name">PlayerDataSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token class-name">DataSourceType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">network</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        videoUrls</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">index</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      playFraction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">0.6</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// auto-play when 60% of the player is visible</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      autoPlay</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>Behind the scenes, it automatically tracks visibility, auto-plays when the item scrolls into view, and cleanly pauses when it scrolls away. No custom intersection observers required!</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="Real-Talk-Pitfalls-to-Watch-Out-For">Real-Talk Pitfalls to Watch Out For<a href="https://hasoft.pl/blog/better-player-migration#Real-Talk-Pitfalls-to-Watch-Out-For" class="hash-link" aria-label="Direct link to Real-Talk Pitfalls to Watch Out For" title="Direct link to Real-Talk Pitfalls to Watch Out For" translate="no">​</a></h2>
<p>Before you ship to production, keep these common gotchas in mind:</p>
<ol>
<li class=""><strong>The Ghost Audio Bug:</strong> Always, <em>always</em> call <code>_betterPlayerController.dispose()</code> in your widget's <code>dispose()</code> method. If you forget, the video player instance lingers in memory, playing audio in the background while your user is three screens away.</li>
<li class=""><strong>Platform Permissions:</strong>
<ul>
<li class="">On <strong>Android</strong>, make sure your <code>AndroidManifest.xml</code> allows cleartext traffic if you're testing against local dev servers (<code>android:usesCleartextTraffic="true"</code>).</li>
<li class="">On <strong>iOS</strong>, check your <code>Info.plist</code> for App Transport Security settings if your streams aren't strictly HTTPS.</li>
</ul>
</li>
<li class=""><strong>Over-Configuring:</strong> Better Player has <em>a lot</em> of knobs and switches (<code>PlayerControlsConfiguration</code>, <code>translations</code>, event listeners, custom overflows). Don't try to customize every single thing on day one. Get the basic player working stably first, then layer on the custom styling.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="Wrapping-Up">Wrapping Up<a href="https://hasoft.pl/blog/better-player-migration#Wrapping-Up" class="hash-link" aria-label="Direct link to Wrapping Up" title="Direct link to Wrapping Up" translate="no">​</a></h2>
<p>Migrating shouldn't feel like open heart surgery, and moving to Better Player is honestly pretty painless once you wrap your head around the <code>Configuration</code> + <code>DataSource</code> split. You'll drop a ton of custom boilerplate code and get a much more robust player experience for your users.</p>
<p>Have you run into any stubborn playback bugs or weird edge cases during your migration? Let us know, and we'll troubleshoot it together!</p>
<hr>
<p><strong>Jakub Homlala</strong></p>]]></content>
        <author>
            <name>Jakub Homlala</name>
            <uri>https://github.com/jhomlala</uri>
        </author>
        <category label="flutter" term="flutter"/>
        <category label="better-player" term="better-player"/>
        <category label="migration" term="migration"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Welcome to the new Hasoft.pl]]></title>
        <id>https://hasoft.pl/blog/2026/08/15/welcome-to-hasoft</id>
        <link href="https://hasoft.pl/blog/2026/08/15/welcome-to-hasoft"/>
        <updated>2026-08-15T10:00:00.000Z</updated>
        <summary type="html"><![CDATA[We are excited to launch our new static website for hasoft.pl!]]></summary>
        <content type="html"><![CDATA[<p>We are excited to launch our new static website for hasoft.pl!</p>
<!-- -->
<p>Here you will find detailed information about our Flutter packages: <strong>Better Player</strong>, <strong>Alice</strong>, and <strong>Catcher</strong>. We plan to share technical articles, optimization tips, and roadmap updates here.</p>
<p>Stay tuned for more content!</p>]]></content>
    </entry>
</feed>