Jellyfin kütüphanesini 90'lar video mağazasına dönüştürme
Halcyon ile Jellyfin kütüphanenizi 90'lar tarzı bir video mağazası arayüzüne çevirin. Docker kurulumu, ters vekil sunucu ayarları ve bilmeniz gereken teknik kısıtlamalar burada.
Halcyon'un Jellyfin kütüphaneniz üzerindeki etkisi
Halcyon Video, Jellyfin kütüphanenizi tarayıcı üzerinde gezilebilir bir 1990'lar video mağazasına dönüştürür. Sahip olduğunuz her film, rafta bir kutu haline gelir. Floresan ışıkların altında koridorlarda yürür, bir kutuyu raftan indirir, teknik özellikleri okumak için arkasını çevirir ve oynatmayı başlatmak için kasaya götürürsünüz. Oynatma durumu, ilerleme ve durdurma bilgileri Jellyfin'e geri raporlanır; böylece kaldığınız yerden devam etme noktaları ve izleme geçmişi doğru kalır.
Halcyon, mevcut bir Jellyfin sunucusunu Jellyfin API üzerinden okur ve kendine ait bir kütüphane tutmaz. Bu kılavuz, Jellyfin'in halihazırda çalıştığını ve düzgün bir şekilde tarandığını varsayar. Eğer durum böyle değilse, önce bir VPS üzerinde medya sunucusu olarak Jellyfin kurulumunu yapın ve kütüphaneniz normal web istemcisinde düzgün göründüğünde geri dönün. Bu, kütüphaneniz zaten hazır olduğu için kuracağınız türden bir yazılımdır; kendi kendine barındırma listenize başka bir servis eklemeniz gerektiği için değil.
Proje GPL-3.0 lisanslıdır ve tek bir kişi tarafından yazılmıştır; README dosyası, pull request kabul edilmediğini açıkça belirtir. Geliştirme süreci hızlı ilerler ve bir regresyon durumunda müdahale edecek ikinci bir bakım sorumlusu yoktur; bu nedenle mağazayı başkasına göstermeden önce imaj sürümünü sabitleyin. Son bölüm bunun nasıl yapılacağını açıklar.
Oluşturma (rendering) işlemi nerede gerçekleşir?
Tarayıcıda. Halcyon, WebGL (tarayıcının GPU arayüzü olan web grafik kütüphanesi) aracılığıyla 3D grafikler çizen bir JavaScript kütüphanesi olan three.js üzerine inşa edilmiş bir Vite ve TypeScript uygulamasıdır. Mağaza geometrisi ve kutu görselleri, ekranı barındıran makine tarafından birleştirilir.
Konteyner çok az iş yapar. npm run serve çalıştırır, bu da vite preview --port 1420 --strictPort --host'dır ve derlenmiş dosyalar ile birkaç küçük ara katman (middleware) rotası sunar. Halcyon sunucu tarafında hiçbir kod dönüştürme (transcoding) yapmaz ve herhangi bir motor çalıştırmaz.
Dolayısıyla GPU sorusu istemciye aittir. Küçük bir VPS bunu rahatlıkla sunabilir, çünkü sunum işlemi statik dosyalardan ve HTTP üzerinden birkaç hafif rotadan ibarettir. Mağazanın akıcı bir şekilde hareket edip etmeyeceğine veya yavaşlayıp yavaşlamayacağına tarayıcıyı çalıştıran dizüstü bilgisayar, tablet veya televizyon karar verir.
Bir özellik bu kuralı bozar. Remote Play'in özel örnekleri (private instances), sunucuda ziyaretçi başına bir adet olmak üzere başsız (headless) Chromium başlatır ve oluşturulan mağazayı WebRTC (web gerçek zamanlı iletişim) üzerinden bir telefona veya set üstü kutuya aktarır. Bu yol, sunucuda oluşturma yapar; varsayılan olarak iki örnekle sınırlıdır ve REMOTE_PLAY_MAX_INSTANCES ile ayarlanabilir. Ayrıca orada bir GPU gerektirir. Yayınlanan imaj herhangi bir yazılımsal oluşturucu (software renderer) içermez, bu nedenle eşlenmiş bir /dev/dri oluşturma düğümü (render node) olmadan sunucu özel bir mağaza başlatmayı reddeder ve This store server has no GPU available, so it can’t render a private store. yanıtını verir.
Mağazanın kütüphanenizden okudukları
Reyonlar, Jellyfin'in kendi yapısından gelir. Halcyon, kütüphanelerinizden ve türlerinizden bölümler oluşturur ve devam filmlerini BoxSets öğelerinizden gruplandırır. Her kutunun arkasında yazılı olan teknik özellikler, Jellyfin'in halihazırda tuttuğu MediaStreams meta verilerinden gelir; bu da Jellyfin'de eksik olan her şeyin rafta da eksik olacağı anlamına gelir.
Bu durum, mağazayı meta verilerinizin adil bir yansıması haline getirir. Görselleri ve türleri önceden doldurulmuş Docker Compose içindeki bir arr yığını tarafından beslenen bir kütüphane, burada genel isimlere sahip dağınık dosya klasörlerinden çok daha iyi görünür. Fotoğraf kütüphaneleri de onları indeksleyen her şeye aynı bağımlılığa sahiptir; aynı sunucuda duran sabit görüntüler için PhotoPrism ile Immich'i kıyaslarken bunu hatırlamakta fayda vardır.
Kurulum yapmadan önce video mağazası demosunu deneyin
Proje, herhangi bir sunucu veya oturum açma gerektirmeyen bir demo barındırır. Mevcut kaynak kodunda, bu barındırılan yapı kendi kütüphaneniz yerine akış başlıklarıyla doludur; bu nedenle bunu sadece mağazaya bir bakış olarak değerlendirin. Kendi dağıtımınızın URL'sinin sonuna ?demo=1 eklemek, bunun yerine sentetik bir kütüphane yükler.
Bu sentetik kütüphane bir donanım testidir, ancak bir istisnası vardır: kendini cihazın kapasitesine göre boyutlandırır. GPU kapasitesi yeterli olan bir tarayıcı, yaklaşık 2.000 başlıktan oluşan tam mağazayı alır. Orta seviye bir GPU yaklaşık 800 başlık alır. Bir telefon veya 4 GB ya da daha az cihaz belleği bildiren herhangi bir tarayıcı yaklaşık 300 başlık alır. Zayıf bir cihazda sorunsuz çalışan bir demo zaten kendini küçültmüştür, bu nedenle kendi tam kütüphanenizin orada nasıl çalışacağı hakkında size pek bir şey söylemez. Faydalı test, tam mağazayı alan bir cihazdır. Eğer bu takılırsa, benzer boyuttaki kendi kütüphaneniz de takılacaktır ve çözüm, daha güçlü bir VPS yerine aşağıda açıklanan 2.5D modudur.
Docker ile çalıştırma
Upstream belgelerinde belirtilen komut budur.
docker run -d --name halcyon --network host --restart unless-stopped \
ghcr.io/halcyon-video/halcyon-videoArdından servisin ayağa kalktığını doğrulayın.
docker logs halcyon
curl -I http://127.0.0.1:1420Günlük kayıtları, önizleme sunucusunun 1420 numaralı portu dinlediğini ve curl sorgusuna HTTP/1.1 200 OK yanıtı döndüğünü göstermelidir. Birkaç saniye içinde kapanan bir container, neredeyse her zaman port çakışması yaşıyordur. --strictPort hatası, 1420 numaralı port dolu olduğunda sunucunun 1421 numaralı porta geçmeyi reddedip doğrudan durduğunu gösterir.
--network host parametresi mağaza için değil, Remote Play içindir. WebRTC, akışı talep eden cihaza makinenin gerçek adresini bildirmek zorundadır. Varsayılan Docker bridge ağının arkasında container yalnızca kendi 172.x adresini bilir; ağınızdaki hiçbir telefon bu adrese erişemeyeceği için akış bağlantısı kurulamaz. Yalnızca mağazayı bir tarayıcıda görüntülemek istiyorsanız, portu yayınlamanız yeterlidir.
docker run -d --name halcyon -p 1420:1420 --restart unless-stopped \
ghcr.io/halcyon-video/halcyon-videoHost networking, container'ı makinedeki tüm arayüzlere (genel ağ arayüzü dahil) dahil ettiği için bir VPS üzerinde daha uygun bir varsayılan ayardır. VPS üzerinde Docker çalıştırma konusu bu durumun getirdiği diğer hususları ele almaktadır. --restart unless-stopped, yeniden başlatma sonrasında mağazanın tekrar erişilebilir olmasını sağlar; bu, Açılışta başlayan Compose servisleri ile aynı mantıktır.
Depoyu klonlayıp docker compose up -d komutunu çalıştırmak, imajı yerel olarak derler. Mevcut Compose dosyası varsayılan olarak kaynak koddan derleme yapar ve önceden derlenmiş image: satırını yorum satırı olarak içerir; yayınlanan imajı Compose ile kullanmak isterseniz bu satırı aktif hale getirin.
Yayınlanan imaj hem linux/amd64 hem de linux/arm64 sürümlerini kapsar. 11 Ekim 2026 tarihinde kontrol edildiği üzere, güncel 0.25.0 sürümü her platform için ayrı bir digest listelemektedir; bu nedenle bir arm64 VPS, diğer tüm hostlar ile aynı komutu kullanarak imajı çekebilir. Yalnızca amd64 mimarisine özel olan süreç kısa sürmüştür: değişiklik günlüğüne göre arm64 imajı v0.2.1 sürümünde 8 Ağustos 2026 tarihinde kaldırılmış, ancak 11 Ağustos 2026 tarihinde v0.4.0 sürümü ile yerel derleyiciler üzerinde tekrar kullanıma sunulmuştur. Yalnızca o aralıktaki bir etikete sabitlenmiş bir hostun klon üzerinden derleme yapması gerekir.
Jellyfin sunucunuzu işaretleyin
http://<host>:1420 dosyasını açın ve Jellyfin sunucu adresiniz, kullanıcı adınız ve parolanızla giriş yapın. Depodaki .env.local.example dosyası yalnızca yerel geliştirme içindir. Vite, VITE_ ön ekine sahip değişkenleri istemci tarafındaki koda dahil eder; bu nedenle oraya yazılan bir Jellyfin parolası, her ziyaretçinin indirdiği JavaScript paketinin içine derlenir. Başkalarının erişebildiği bir sunucuda, arayüz üzerinden giriş yapın.
Tarayıcı, Jellyfin ile doğrudan iletişim kurar. Halcyon container'ı, Jellyfin API'sini proxy üzerinden yönlendirmez; hata ayıklamaya başlamadan önce bilinmesi gereken iki sonuç doğurur.
Birincisi, Jellyfin'in yalnızca Halcyon'u sunan VPS'den değil, tarayıcıdan da erişilebilir olması gerekir. 127.0.0.1:8096 adresine bağlı bir Jellyfin, yerel test için uygundur ancak diğer herkes için rafların boş görünmesine neden olur.
İkincisi, çağrı Halcyon adresinden Jellyfin adresine çapraz kökenli (cross origin) bir istektir. Jellyfin, API isteklerini varsayılan olarak Access-Control-Allow-Origin: * ile yanıtlar, bu nedenle ek bir yapılandırma gerekmeden çalışır. Eğer bu ayarı daralttıysanız veya Jellyfin API'sinin önüne bir kimlik doğrulama proxy'si koyduysanız, tarayıcı konsolu blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource hatası verir ve mağaza boş raflarla yüklenir.
Reverse proxy arkasına alın ve ön tarafa kimlik doğrulama ekleyin
vite preview bir önizleme sunucusudur. TLS (transport layer security) sonlandırması yapmaz ve kendi erişim denetimi yoktur; bu nedenle genel ağa açık herhangi bir sistemde nginx veya Caddy arkasında çalıştırılmalıdır.
server {
listen 443 ssl;
server_name halcyon.example.com;
location / {
proxy_pass http://127.0.0.1:1420;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Konteynerin önündeki alan adı için bir ayar daha gereklidir. Halcyon, DNS rebinding saldırılarına karşı bir önlem olarak localhost, ham IP adresleri ve üzerinde çalıştığı makinenin isimlerine yanıt verir. Bir konteynerin içinde, üzerinde çalıştığı makine konteynerin kendisidir, dolayısıyla ana makine adı (hostname) sizin belirlediğiniz isim değildir. halcyon.example.com olarak gelen bir istek reddedilir ve yanıt, reddedilen ana makine adını içerir. Bu ismi ekleyin.
docker run -d --name halcyon -p 127.0.0.1:1420:1420 --restart unless-stopped \
-e HALCYON_ALLOWED_HOSTS=halcyon.example.com \
ghcr.io/halcyon-video/halcyon-videoDeğer virgülle ayrılır; .example.com gibi başında nokta olan bir ifade alt alan adlarıyla eşleşir, all ise kontrolü devre dışı bırakır. all seçeneğine yalnızca dışarıdan erişilemeyen bir makinede başvurun.
Mağaza https:// üzerinden sunulduğunda, giriş yaparken yazdığınız Jellyfin adresi de https:// olmalıdır. Tarayıcılar, HTTPS bir sayfadan yapılan düz http:// API çağrılarını engeller ve konsolda Mixed Content: The page at 'https://halcyon.example.com/' was loaded over HTTPS, but requested an insecure resource hatası görünür. Giriş işlemi, Halcyon içinde bir açıklama olmaksızın başarısız olur. Her ikisini de TLS üzerinden sunun veya her ikisini de özel bir ağ içinde düz HTTP üzerinde tutun.
Ardından kimlik doğrulama gelir. Mağaza, Jellyfin kimlik bilgilerinizi ister; bu nedenle URL'yi bulan bir yabancı, giriş ekranıyla karşılaşır. Bir özellik bunu değiştirir. Ayarlar altındaki Bağlantı (Connection) kısmından Uzaktan Oynatma (Remote Play) özelliğini açmak, Jellyfin oturumunuzu sunucuya aktarır; böylece /remote.html adresini ziyaret edenler, gerçek kütüphanenizin kendi örneklerine erişebilirler. Bu özelliğin amacı budur ve bu, URL'nin gizliliğinin internet ile filmleriniz arasındaki tek engel olduğu anlamına gelir. Uzaktan Oynatma özelliğini etkinleştirirseniz, tüm sitenin önüne kendi kendine barındırılan bir SSO ağ geçidi olarak Authentik ile tek oturum açma (SSO) ekleyin veya genel ana makine adını kaldırıp mağazaya wg-easy ile yönetilen bir WireGuard tüneli üzerinden erişin.
Bununla ilgili iki detay daha vardır. Reverse proxy yalnızca mağaza trafiğini taşır: Uzaktan Oynatma akışı UDP üzerinden WebRTC'dir ve HTTP proxy üzerinden geçmez; bu nedenle 3478/udp üzerinde ve yerleşik TURN rölesi kullanımdayken 49200 ile 49260/udp aralığında kendi yoluna ihtiyaç duyar. Ayrıca yukarıdaki düz docker run herhangi bir birim (volume) tutmaz, bu nedenle Uzaktan Oynatma verisi docker rm sonrasında kaybolur. Compose dosyası, tam olarak bu sebeple /data yoluna bir halcyon-data birimi bağlar ve REMOTE_PLAY_SEED değerini /data/remote-play-seed.json olarak ayarlar.
Mağaza kötü çalıştığında ne yapılmalı
Halcyon, isteğe bağlı olarak render işlemi yapar. Boşta duran bir mağaza kare oluşturmaz ve pencere odağının kaybedilmesi animasyon döngüsünü durdurur; bu sayede açık bırakılan bir sekme dizüstü bilgisayar pilini tüketmez. Bu durum, sınırda performans gösteren bir makine için yardımcı olur. Ancak mağazayı hiç çizemeyen bir makine için bir etkisi yoktur.
Bu tür istemciler için, Raspberry Pi kadar küçük donanımlar düşünülerek tasarlanmış, WebGL içermeyen, düz HTML ve CSS tabanlı 2.5D modu mevcuttur. 3D ve 2.5D modları arasında, sayfa yenilemeye gerek kalmadan ayarlar veya güç menüsü üzerinden geçiş yapabilirsiniz; bu nedenle her iki modu aynı cihazda test etmek saniyeler sürer. Elde edeceğiniz sonuç konusunda gerçekçi olun: Ağustos 2026'da yazar, düz modu kaba olarak nitelendirmiş ve projenin henüz başlangıç aşamasında olduğunu belirtmiştir. Bunu, zayıf istemciler için bir yedekleme seçeneği olarak değerlendirin.
Bir istemci 3D mağaza için çok yetersiz kaldığında, hata belirgin şekilde ortaya çıkar. Sekme kendi kendini yeniler veya tarayıcı, genellikle raflar henüz dolarken WebGL bağlamının kaybedildiğini bildirir. Bu durumda kütüphanenizi küçültmek yerine cihazı 2.5D moduna alın.
İmajı sabitleyin ve çekmeden önce kontrol edin
Bu kısmı ciddiye alın. v0.1.0 ile v0.3.1 arasındaki tüm etiketler birbirini izleyen birkaç gün içinde yayınlandı ve v0.2.1 sadece v0.2.0 için yapılan imaj gönderimi başarısız olduğu için var. O günden bu yana hız kesilmedi: v0.25.0, v0.23.0'dan üç gün sonra, 7 Ekim 2026 tarihinde yayınlandı. Hata raporları yukarı akış (upstream) tarafında kabul edilse de yamalar kabul edilmiyor; bu nedenle yayın akışı, tek bir kişinin çalışma durumunu yansıtmaktadır.
latest komutunu docker pull alışkanlığıyla çalıştırmak, herhangi bir sıradan Salı gününde deponun altınızda değişebileceği anlamına gelir. Değiştirilemez tek referans olan özet (digest) değerine göre sabitleme yapın.
docker buildx imagetools inspect ghcr.io/halcyon-video/halcyon-video:0.25.0Bu komut, etiketin arkasındaki özet değerini yazdırır. Etiket yerine bunu kullanın.
docker run -d --name halcyon -p 1420:1420 --restart unless-stopped \
ghcr.io/halcyon-video/halcyon-video@sha256:7fc00e619a30004d275faa79ad36d810e5a8530757132603065ba4e848dd67de11 Ekim 2026 tarihinde 0.25.0 etiketinin arkasındaki özet değeri buydu. Kopyalamak yerine güncel olanı kendiniz okuyun ve geçiş yapmadan önce sürüm notlarını inceleyin; çünkü buradaki bir yama sürümü, düzeltmelerin yanı sıra depo düzeni değişikliklerini de beraberinde getirebilir.
FAQ
Halcyon VPS üzerinde GPU gerektirir mi?
Normal kullanım için gerekmez. Mağaza, tarayıcıda three.js ile çizilir; bu nedenle render işlemi istemci makinede gerçekleşir. Container, oluşturulan dosyaları ve 1420 numaralı port üzerindeki birkaç hafif sunucu rotasını servis eder. İstisna durum, sunucuda headless Chromium çalıştıran ve sonucu stream eden Remote Play'in özel örnekleridir. Yayınlanan imaj ile bu yolun container içine /dev/dri olarak eşlenmesi gerekir. GPU yoksa sunucu, özel bir mağaza başlatmayı reddeder.
Halcyon'u genel internete açabilir miyim?
Yalnızca kimlik doğrulama arkasında. Mağaza, Jellyfin kimlik bilgilerinizi ister ancak Remote Play'i açmak, Jellyfin oturumunuzu sunucuya devreder. Bu nedenle /remote.html adresini yükleyen herkes, giriş yapmadan gerçek kütüphanenizin bir örneğine erişebilir. Önüne tek oturum açma (SSO) özellikli bir reverse proxy koyun veya ana makine adını genel DNS'ten uzak tutarak mağazaya bir VPN üzerinden erişin.
Giriş yaptıktan sonra raflar neden boş görünüyor?
Tarayıcı, Jellyfin API'sini doğrudan çağırır. Bu nedenle Jellyfin'e yalnızca VPS üzerinden değil, tarayıcı üzerinden de erişilebilir olmalıdır. Tarayıcı konsolunu açın. blocked by CORS policy hatası, Jellyfin'in Halcyon adresinden gelen isteği kabul etmediği anlamına gelir. Mixed Content mesajı ise sayfanın HTTPS üzerinde olduğunu, ancak girdiğiniz Jellyfin adresinin düz HTTP olduğunu belirtir.
--network host kullanmam gerekiyor mu?
Yalnızca Remote Play için gereklidir. WebRTC, makinenin gerçek adresini duyurmalıdır. Docker köprüsü arkasında container, ağınızdaki hiçbir telefonun erişemeyeceği bir 172.x adresi sunabilir. Mağazayı tarayıcıda görüntülemek için -p 1420:1420 yeterlidir ve ana makinenin daha az kısmını dışarıya açar.
Hangi imaj etiketini kullanmalıyım?
latest yerine bir digest sabitleyin. docker buildx imagetools inspect ghcr.io/halcyon-video/halcyon-video:0.25.0 içeren bir sürüm için digest değerini okuyun, bu digest ile çalıştırın ve yalnızca sürüm notlarını okuduktan sonra güncelleyin. 11 Ekim 2026 itibarıyla yayınlanan imaj hem linux/amd64 hem de linux/arm64 içerir; bu nedenle bir arm64 ana makinesi, bunu diğerleri gibi çeker ve klondan derlemeye ihtiyaç duymaz.