SSD Nodes Learn Hosting plans →
मार्गदर्शक Matt Connorद्वारे Matt Connor

Jellyfin ला 90s व्हिडिओ स्टोअरमध्ये बदलणारा Halcyon

Halcyon तुमची Jellyfin लायब्ररी ब्राउझरमधील 1990 च्या दशकातील स्टोअर बनवते. Docker command, reverse proxy आणि प्रकल्पाच्या मर्यादा जाणून घ्या.

Halcyon तुमच्या Jellyfin लायब्ररीसाठी काय करते

Halcyon Video तुमच्या Jellyfin लायब्ररीला ब्राउझरमध्ये चालता येणाऱ्या 1990 च्या दशकातील व्हिडिओ स्टोअरच्या रूपात पुन्हा सादर करते. तुमच्या मालकीचा प्रत्येक चित्रपट शेल्फवरील एका केसमध्ये दिसतो. तुम्ही पट्ट्यांच्या दिव्यांखालील मार्गिकांमधून फिरता, एक बॉक्स खाली काढता, मागील बाजूस दिलेली माहिती वाचण्यासाठी तो उलटता आणि playback सुरू करण्यासाठी तो काउंटरवर नेता. Playback सुरू होणे, प्रगती आणि थांबणे याची माहिती Jellyfin कडे परत पाठवली जाते. त्यामुळे resume points आणि watch history अचूक राहतात.

Halcyon विद्यमान Jellyfin server मधील माहिती Jellyfin API द्वारे वाचते आणि स्वतःची स्वतंत्र लायब्ररी ठेवत नाही. या मार्गदर्शकात Jellyfin आधीपासून सुरू असून त्यात media scanning व्यवस्थित सुरू आहे असे गृहीत धरले आहे. तसे नसल्यास, प्रथम VPS वर Jellyfin media server म्हणून सेट करा आणि नेहमीच्या web client मध्ये तुमची लायब्ररी योग्य दिसू लागल्यानंतर येथे परत या. लायब्ररी आधीपासून उपलब्ध असल्यामुळे तुम्ही हे install करता; तुमच्या self hosting यादीत आणखी एक service जोडण्याची गरज असल्यामुळे नाही.

हा project GPL-3.0 अंतर्गत उपलब्ध असून तो एका व्यक्तीने लिहिला आहे. README मध्ये pull requests स्वीकारले जात नाहीत, असे स्पष्टपणे नमूद केले आहे. Development वेगाने बदलते आणि regression तपासण्यासाठी दुसरा maintainer नाही. त्यामुळे store इतरांना दाखवण्यापूर्वी image version pin करा. ते कसे करायचे हे शेवटच्या section मध्ये दिले आहे.

रेंडरिंग कुठे होते?

ब्राउझरमध्ये. Halcyon हे three.js वर आधारित Vite आणि TypeScript अॅप आहे. three.js ही JavaScript लायब्ररी WebGL द्वारे 3D graphics रेखाटते. WebGL म्हणजे web graphics library; ती ब्राउझरचा GPU शी संवाद साधणारा interface आहे. Store ची geometry आणि box art स्क्रीन असलेल्या मशीनवर एकत्र render केली जातात.

Container फारच कमी काम करतो. तो npm run serve चालवतो, जे vite preview --port 1420 --strictPort --host आहे, आणि build केलेल्या files सोबत काही लहान middleware routes serve करतो. Halcyon कोणतेही transcoding करत नाही आणि server वर कोणतेही engine चालवत नाही.

त्यामुळे GPU संबंधी प्रश्न client शी संबंधित आहे. हे काम लहान VPS सहजपणे करू शकतो, कारण येथे serving म्हणजे HTTP द्वारे static files देणे. Browser चालवणारा laptop, tablet किंवा television store सुरळीत चालेल की अडखळेल हे ठरवतो.

एक feature या नियमाला अपवाद आहे. Remote Play server वर headless Chromium instances सुरू करतो आणि render केलेला store WebRTC द्वारे phone किंवा set top box वर stream करतो. WebRTC म्हणजे web real time communication. या प्रक्रियेत rendering server वर होते. By default जास्तीत जास्त two instances चालतात; ही संख्या REMOTE_PLAY_MAX_INSTANCES ने बदलता येते. Mapped /dev/dri device नसल्यास ही instances CPU वर render करतात. त्यामुळे two core VPS वर प्रत्येक अतिरिक्त viewer चा परिणाम स्पष्टपणे जाणवतो.

तुमच्या लायब्ररीमधून स्टोअर काय वाचते

दुकानातील विभाग Jellyfin च्या स्वतःच्या रचनेतून येतात. Halcyon तुमच्या लायब्ररी आणि genres मधून विभाग तयार करते आणि तुमच्या BoxSets मधील sequels एकत्र करते. प्रत्येक केसच्या मागील बाजूस छापलेली specs Jellyfin कडे आधीपासून असलेल्या MediaStreams metadata मधून येतात. त्यामुळे Jellyfin मध्ये जे उपलब्ध नाही, ते shelf वरही उपलब्ध नसते.

त्यामुळे हे स्टोअर तुमच्या metadata चे अचूक प्रतिबिंब ठरते. Docker Compose मधील arr stack ने भरलेली आणि artwork व genres आधीच असलेली लायब्ररी येथे generic names असलेल्या स्वतंत्र files च्या folder पेक्षा अधिक चांगली दिसते. Photo libraries देखील त्यांना index करणाऱ्या प्रणालीवर अवलंबून असतात. त्यामुळे त्याच server वर असलेल्या stills साठी PhotoPrism आणि Immich यांची तुलना करताना हे लक्षात ठेवणे उपयुक्त ठरते.

काहीही install करण्यापूर्वी video store demo वापरून पाहा

हा प्रकल्प hosted demo वर synthetic library वापरून संपूर्ण store चालवतो. तुमच्या स्वतःच्या deployment मध्ये कोणत्याही Halcyon URL च्या शेवटी ?demo=1 जोडल्यास तेच कार्य होते.

याचा hardware test म्हणून वापर करा; मात्र एक महत्त्वाची मर्यादा आहे. Demo स्वतःचा आकार device नुसार ठरवतो. पुरेशी GPU क्षमता असलेल्या browser ला सुमारे 2,000 titles असलेला पूर्ण store मिळतो. मध्यम क्षमतेच्या GPU ला सुमारे 800 titles मिळतात. फोन किंवा device memory 4 GB किंवा त्यापेक्षा कमी असल्याचे दर्शवणाऱ्या कोणत्याही browser ला सुमारे 300 titles मिळतात. कमकुवत device वर सुरळीत चालणाऱ्या demo ने स्वतःचा आकार आधीच कमी केलेला असतो. त्यामुळे तुमची पूर्ण library त्या device वर कशी चालेल याबद्दल त्यातून फारशी माहिती मिळत नाही. पूर्ण store मिळवणारे device वापरणे ही उपयुक्त चाचणी आहे. त्यात stutter होत असल्यास, समान आकाराची तुमची स्वतःची library देखील stutter करेल. अशा वेळी मोठा VPS घेण्याऐवजी खाली वर्णन केलेला 2.5D mode वापरणे हा योग्य उपाय आहे.

Docker सह चालवा

Upstream मध्ये दिलेला हा command आहे.

docker run -d --name halcyon --network host --restart unless-stopped \
  ghcr.io/halcyon-video/halcyon-video

त्यानंतर ते सुरू झाले आहे का ते तपासा.

docker logs halcyon
curl -I http://127.0.0.1:1420

Log मध्ये preview server port 1420 वर listening असल्याचे दिसले पाहिजे आणि curl ने HTTP/1.1 200 OK ला प्रतिसाद दिला पाहिजे. काही सेकंदांतच exit होणारा container बहुतेक वेळा port मुळे थांबतो. --strictPort याचा अर्थ 1420 वापरात असल्यास server 1421 वर जाण्यास नकार देतो आणि त्याऐवजी थांबतो.

--network host हे Remote Play साठी आहे; store साठी नाही. Stream मागणाऱ्या device ला WebRTC ने मशीनचा वास्तविक address सांगणे आवश्यक आहे. Default Docker bridge मागे container ला फक्त स्वतःचा 172.x address माहीत असतो. तुमच्या network वरील कोणताही phone त्या address पर्यंत पोहोचू शकत नाही. त्यामुळे stream कधीही connect होत नाही. तुम्हाला browser मध्ये फक्त store वापरायचा असल्यास port publish करा.

docker run -d --name halcyon -p 1420:1420 --restart unless-stopped \
  ghcr.io/halcyon-video/halcyon-video

VPS वर हा अधिक योग्य default आहे, कारण host networking मुळे container मशीनकडे असलेल्या प्रत्येक interface वर येतो, public interface वरही. या trade-off च्या उर्वरित भागासाठी VPS वर Docker चालवणे पाहा. Reboot नंतर store पुन्हा सुरू करण्यासाठी --restart unless-stopped वापरले जाते. हीच कल्पना boot वेळी सुरू होणाऱ्या Compose services मध्येही आहे.

Repository clone करून docker compose up -d चालवल्यास image स्थानिक पातळीवर build होते. Commit केलेली Compose file default नुसार source मधून build करते आणि prebuilt image: line comment केलेली ठेवते. Compose अंतर्गत published image वापरायची असल्यास ती line uncomment करा.

Published image मध्ये linux/amd64 आणि linux/arm64 दोन्ही समाविष्ट आहेत. 9 October 2026 रोजी तपासल्यावर, सध्याच्या 0.25.0 release मध्ये प्रत्येक platform साठी स्वतंत्र digest दिलेला आहे. त्यामुळे arm64 VPS वर इतर कोणत्याही host प्रमाणेच तोच command वापरून image pull करता येते. amd64-only कालावधी अल्प होता: 8 August 2026 रोजी changelog मध्ये v0.2.1 मधील arm64 image काढण्यात आली आणि 11 August 2026 रोजी native runners वर build करून ती v0.4.0 मध्ये पुन्हा आणण्यात आली. त्या कालावधीतील tag वर pinned असलेल्या host लाच clone मधून build करावे लागते.

Jellyfin सर्व्हरकडे निर्देश करा

http://<host>:1420 उघडा आणि Jellyfin सर्व्हरचा पत्ता, username आणि password वापरून लॉग इन करा. Repository मधील .env.local.example फाइल फक्त स्थानिक विकासासाठी आहे. Vite, VITE_ ने सुरू होणारे variables client-side code ला उपलब्ध करून देते. त्यामुळे तेथे लिहिलेला Jellyfin password प्रत्येक visitor डाउनलोड करत असलेल्या JavaScript bundle मध्ये समाविष्ट होतो. इतर लोक पोहोचू शकतील अशा सर्व्हरवर interface द्वारे लॉग इन करा.

ब्राउझर Jellyfin शी थेट संवाद साधतो. Halcyon चा container Jellyfin API साठी proxy म्हणून काम करत नाही. Debugging सुरू करण्यापूर्वी याचे दोन परिणाम लक्षात ठेवा.

पहिले, Jellyfin फक्त Halcyon उपलब्ध करून देणाऱ्या VPS वरून नव्हे, तर ब्राउझरवरूनही पोहोचण्याजोगा असणे आवश्यक आहे. 127.0.0.1:8096 शी bind केलेला Jellyfin स्थानिक चाचणीसाठी योग्य आहे. मात्र इतर सर्व वापरकर्त्यांसाठी shelves रिकाम्या राहतील.

दुसरे, ही call cross-origin आहे. ती Halcyon च्या address वरून Jellyfin च्या address कडे जाते. Jellyfin API requests ला default ने Access-Control-Allow-Origin: * सह उत्तर देतो. त्यामुळे अतिरिक्त configuration शिवाय ते कार्य करते. हे setting अधिक मर्यादित केले असल्यास किंवा Jellyfin API समोर authentication proxy ठेवला असल्यास, browser console मध्ये blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource दिसते आणि store मध्ये रिकाम्या shelves लोड होतात.

रिव्हर्स proxy मागे ठेवा आणि समोर authentication लावा

vite preview हा preview server आहे. तो TLS (transport layer security) terminate करत नाही आणि त्याचे स्वतःचे access control नाही. त्यामुळे सार्वजनिक वापरासाठी तो nginx किंवा Caddy मागे ठेवणे आवश्यक आहे.

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;
  }
}

Container समोर domain name वापरायचा असल्यास आणखी एक setting आवश्यक आहे. DNS rebinding पासून संरक्षण करण्यासाठी Halcyon localhost, raw IP addresses आणि ज्या machine वर तो चालतो त्या machine ची नावे स्वीकारतो. Container मध्ये ज्या machine वर तो चालतो ती machine म्हणजे container असते; त्यामुळे तिचे hostname तुमचे hostname नसते. halcyon.example.com म्हणून आलेली request नाकारली जाते आणि response मध्ये नाकारलेल्या host चे नाव दिले जाते. ते नाव जोडा.

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-video

ही value comma-separated असते. .example.com सारखा सुरुवातीचा dot subdomains शी जुळतो. all check बंद करते. all फक्त बाहेरून कोणालाही पोहोचता न येणाऱ्या machine वर वापरा.

Store https:// द्वारे serve केल्यानंतर login वेळी टाइप करायचा Jellyfin address देखील https:// असला पाहिजे. HTTPS page मधून केलेली plain http:// API call browser block करतो आणि console मध्ये Mixed Content: The page at 'https://halcyon.example.com/' was loaded over HTTPS, but requested an insecure resource दिसते. Halcyon मध्ये कोणतेही स्पष्टीकरण न देता login अपयशी ठरतो. दोन्ही सेवा TLS द्वारे serve करा किंवा private network मध्ये दोन्ही plain HTTP वर ठेवा.

यानंतर authentication. Store Jellyfin credentials मागतो. त्यामुळे URL शोधणाऱ्या अनोळखी व्यक्तीसमोर login screen दिसते. मात्र एक feature हे बदलते. Settings आणि त्यानंतर Connection अंतर्गत Remote Play सुरू केल्यास तुमचे Jellyfin session server ला दिले जाते. त्यामुळे /remote.html वर येणाऱ्या visitors ना तुमच्या वास्तविक library ची स्वतंत्र instance मिळते. या feature चा उद्देश हाच आहे. त्यामुळे URL गुप्त ठेवणे हे internet आणि तुमच्या films यांच्यामधील एकमेव अडथळा ठरते. Remote Play सुरू केल्यास संपूर्ण site समोर single sign-on लावा आणि self-hosted SSO gateway म्हणून Authentik वापरा, किंवा public hostname काढून store पर्यंत wg-easy द्वारे व्यवस्थापित WireGuard tunnel वापरून पोहोचा.

यासोबत दोन गोष्टी लक्षात ठेवा. Reverse proxy फक्त store वाहून नेतो. Remote Play stream हा UDP वरील WebRTC असतो आणि HTTP proxy मधून जात नाही. त्यामुळे 3478/udp आणि bundled TURN relay वापरात असल्यास 49200 ते 49260/udp वर त्यासाठी स्वतंत्र मार्ग आवश्यक असतो. तसेच वरचा plain docker run कोणताही volume टिकवून ठेवत नाही. त्यामुळे Remote Play seed docker rm नंतर टिकत नाही. याच कारणासाठी Compose file halcyon-data volume ला /data येथे mount करते आणि REMOTE_PLAY_SEED ची value /data/remote-play-seed.json ठेवते.

स्टोअर खराब काम करत असल्यास काय करावे

Halcyon मागणीनुसार rendering करते. निष्क्रिय स्टोअर कोणतेही frame तयार करत नाही. विंडोचा focus गमावल्यावर animation loop थांबतो. त्यामुळे उघडा ठेवलेला tab laptop ची battery वेगाने संपवत नाही. केवळ मर्यादित क्षमतेच्या मशीनसाठी ही बाब उपयुक्त ठरते. परंतु स्टोअरचे rendering अजिबात करू न शकणाऱ्या मशीनसाठी याचा उपयोग होत नाही.

अशा clients साठी 2.5D mode उपलब्ध आहे. यात WebGL नसलेले साधे HTML आणि CSS वापरले जाते. हे Raspberry Pi सारख्या कमी क्षमतेच्या hardware साठी तयार केले आहे. Page reload न करता settings किंवा power menu मधून 3D आणि 2.5D यांमध्ये बदल करता येतो. त्यामुळे एकाच device वर दोन्ही modes तपासण्यासाठी काही सेकंद पुरतात. मात्र अपेक्षा वास्तववादी ठेवा. लेखक flat mode ला प्राथमिक अवस्थेतील आणि अजूनही विकासाधीन असे वर्णन करतो. कमकुवत clients साठी ते fallback म्हणून वापरा.

एखादा client 3D store साठी खूपच कमी क्षमतेचा असेल, तर failure स्पष्टपणे दिसतो. Tab स्वतः reload होतो किंवा browser lost WebGL context असा संदेश दाखवतो. हे सहसा shelves अजून भरल्या जात असतानाच घडते. तुमची library कमी करण्याऐवजी त्या device ला 2.5D वर बदला.

प्रतिमा pin करा आणि pull करण्यापूर्वी तपासा

हा भाग गांभीर्याने घ्या. v0.1.0 ते v0.3.1 हे tags काही दिवसांच्या अंतरातच release झाले आणि v0.2.1 केवळ v0.2.0 साठी image push अयशस्वी झाल्यामुळे अस्तित्वात आहे. त्यानंतरही हा वेग कमी झालेला नाही: v0.25.0 हे 7 October 2026 रोजी प्रकाशित झाले, म्हणजे v0.23.0 नंतर तीन दिवसांनी. Upstream कडे bug reports पाठवण्याचे स्वागत आहे; patches मात्र स्वीकारले जात नाहीत. त्यामुळे release stream म्हणजे एका व्यक्तीची सध्याची working state आहे.

latest चालवताना docker pull करण्याची सवय असल्यास, कोणत्याही सामान्य Tuesday दिवशी store तुमच्या नकळत बदलू शकतो. Digest ने pin करा. बदलू न शकणारा हा एकमेव reference आहे.

docker buildx imagetools inspect ghcr.io/halcyon-video/halcyon-video:0.25.0

यामुळे tag मागील digest दिसतो. Tag ऐवजी तो digest वापरा.

docker run -d --name halcyon -p 1420:1420 --restart unless-stopped \
  ghcr.io/halcyon-video/halcyon-video@sha256:7fc00e619a30004d275faa79ad36d810e5a8530757132603065ba4e848dd67de

9 October 2026 रोजी तो digest 0.25.0 होता. तो थेट copy करण्याऐवजी सध्याचा digest स्वतः तपासा. तसेच बदल करण्यापूर्वी release notes वाचा, कारण येथे patch release मध्ये fixes सोबत store layout मधील बदलही असू शकतात.

FAQ

Halcyon साठी माझ्या VPS वर GPU आवश्यक आहे का?

सामान्य वापरासाठी नाही. स्टोअर browser मध्ये three.js वापरून render केले जाते, त्यामुळे rendering client machine करते आणि container फक्त port 1420 वर static files देते. अपवाद म्हणजे Remote Play. ते server वर headless Chromium चालवते आणि त्याचा परिणाम stream करते. तुम्ही hardware acceleration साठी /dev/dri container मध्ये map केले नाही, तर हा भाग CPU वर render होतो.

Halcyon public internet वर ठेवता येईल का?

फक्त authentication मागे ठेवून. स्टोअर Jellyfin credentials मागते; परंतु Remote Play सुरू केल्यावर तुमचे Jellyfin session server ला दिले जाते. त्यामुळे /remote.html लोड करणाऱ्या कोणालाही login न करता तुमच्या प्रत्यक्ष library चे instance मिळते. त्यासमोर single sign on असलेला reverse proxy ठेवा किंवा hostname public DNS वर प्रकाशित करू नका आणि VPN द्वारे स्टोअरपर्यंत पोहोचा.

Login केल्यानंतर shelves रिकामे का दिसतात?

Browser Jellyfin API ला थेट call करतो. त्यामुळे Jellyfin फक्त VPS वरून नव्हे, तर browser कडूनही reachable असणे आवश्यक आहे. Browser console उघडा. blocked by CORS policy याचा अर्थ Jellyfin Halcyon च्या address कडून आलेली request स्वीकारत नाही. Mixed Content message याचा अर्थ page HTTPS वर आहे, तर तुम्ही दिलेला Jellyfin address plain HTTP आहे.

--network host आवश्यक आहे का?

फक्त Remote Play साठी. WebRTC ने machine चा वास्तविक address advertise करणे आवश्यक आहे. Docker bridge मागे container फक्त 172.x address देऊ शकतो, ज्यापर्यंत तुमच्या network वरील कोणताही phone पोहोचू शकत नाही. Browser मध्ये स्टोअर पाहण्यासाठी -p 1420:1420 पुरेसे आहे आणि host चा बराच कमी भाग expose होतो.

कोणता image tag वापरावा?

latest ऐवजी digest pin करा. docker buildx imagetools inspect ghcr.io/halcyon-video/halcyon-video:0.25.0 असलेल्या version चा digest वाचा, तो digest वापरून चालवा आणि release notes वाचल्यानंतरच पुढे update करा. 9 October 2026 रोजी प्रकाशित image मध्ये linux/amd64 आणि linux/arm64 दोन्ही समाविष्ट आहेत. त्यामुळे arm64 host ते इतर image प्रमाणे pull करतो आणि clone मधून build करण्याची आवश्यकता नसते.