Ako som vytvoril IPTV apku Couchly (a používam ju)
Občas, keď si potrebujem pozrieť niečo v telke, hoc mám Orange TV, nemôžem. Dôvodom je že tieto televízie nie sú dostupné v aplikácií napriek tomu že na TV sú dostupné. Je to v poriadku a chápem tomu. Preto som už dávnejšie zvolil možnosť používať IPTV Streams. Problém však občas nastáva v tom, že dobrá aplikácia pre iOS, ktorá by vo verzii zdarma pokrývala všetky moje use-cases (kategórie, PIP, obľúbené, či enkodovanie contentu) – za mňa neexistuje.
Napriek tomu uznávam, že niektoré z týchto aplikácií nemajú drahé subscriptions, či one-time payment pre lifetime prístup. Ale môj problém je v tom, že ako programátor nechcem platiť za niečo, čo si myslím že dokážem spraviť aj sám. Preto som sa rozhodol že si aplikáciu napíšem.
Keďže už mám skúsenosti s Ionicom (framework pre hybridné apps), rozhodol som sa pre túto cestu. Stack bol celkom tradičný pre mňa – to znamená Ionic v kombinácii s Vue 3 a Typescript support. Bootstrap pre aplikáciu bol jednoduchý, nasetupoval som všetky potrebné views v default UX scope. Pokračoval som ďalej a začal som pátrať, ako to vlastne celé fuguje. Parsing bol relatívne jednoduchý, m3u files majú dobre pred-definovanú štruktúru a tak všetky potrebné info boli ľahko dosiahnuteľné. Takže som mal dáta a bolo potrebné vytvoriť player. Apple sám má podporu pre video-player veľmi dobrú, použil som teda AVPlayer.


Všetko fungovalo bez problémov, ale po čase (testoval som iba jeden kanál) som si všimol že niektoré streamy majú problém s prehliadačom. Zistil som, že AVPlayer nemá úplnú podporu formátov a tak dekódovanie niektorých z nich môže spôsobovať problémy. Začal som pátrať a došiel som k tomu, že je zrejme lepšie použiť VLC Based prehrávač, ktorý už aj zo skúseností z PC vieme, že má výbornú podporu a prehrá „prakticky všetko“. A tak aj bolo. Začali fungovať aj streamy, ktoré predtým nefungovali. Ako som tak testoval celú aplikáciu a bol šťastný že celý prehrávač funguje, minimalizoval som aplikáciu aby som zistil – že PIP (Picture in Picture) prestal fungovať.
Toto bol logický krok. PIP podpora existuje pre AVPlayer ako natívny spôsob prehrávania obsahu, no VLC ho nepodporuje. Premýšľal som, ako viem tento problém vyriešiť, zapojil aj AI a zistil, že toto sa obíjsť jednoducho nedá. Rozhodol som sa preto ísť s dual-support. AVPlayer ako hlavný prehrávač a v prípade problémov, fallback na VLC. Toto si ale vyžadovalo systematické uvažovanie a vytvorenie pluginu pre Swift, keďže to natívne riešiť len cez Ionic je celkom problém. Zapojil som preto Claude Code (všetko bolo riešené cez Claude Opus 4.6 Thinking a ten spravil prácu ktorú som očakával. Vytvoril dual-support plugin, ktorý som len integtoval v XCode po builde wrapperu pre iOS a všetko fungovalo. Musel som ešte poriešiť pár issues s minimalizovaním apky, prerenderovaním a podobné maličkosti, ale gro aplikácie fungovalo.
V tomto momente som znova odložil AI a pokračoval s integráciou funkcionality. Pridal som možnosť ukladania staníc do obľúbených, posledné videné stanice a taktiež horizontal-scroll pre kategórie, keďže nie každému sa chce listovať. Otestoval v reálnom prostredí na produkčnom builde v XCode a všetko fungovalo tak ako som potreboval.
Aplikáciu mi trvalo vytvoriť približne dva dni a to s pomocou AI. Neviem ako dlho by som písal plugin vo Swifte ktorý by riešil dual-support pre dva video prehrávače, takže za túto časť som vďačný.
Jeden z problémov na ktoré som narazil bol pokus o zostrenie videa. Niektoré streamy majú nízku kvalitu a preto sa mi páčila myšlienka zostrenia obrazu pomocou SVG filtra alebo WebGL shaderu. Tu som ale narazil na viacero problémov. Hlavne teda support pre oba prehrávače, alebo prípadne nemožnosť použitia vo full-screene. Skúšal som aj CSS filtering či canvas, no obe mali problémy a skôr robili aplikáciu zbytočne nestabilnou, v niektorých prípadoch s obrovskou záťažou na baterku zariadenia.
S tým som sa ale zmieril a som rád, že môžem používať plnohodnotnú aplikáciu v iOS a sledovať streamy so všetkými výhodami ktoré potrebujem a zdarma. Ak máte záujem, build viem poskytnúť 🙃
A tu ešte krátke demo.