SSD Nodes Learn Hosting plans →
मार्गदर्शक Matt Connorद्वारे Matt Connor · अपडेटेड 2026-08-29

Halcyon: Jellyfin ला 90 च्या दशकातील व्हिडिओ स्टोअर बनवा

Halcyon तुमची Jellyfin लायब्ररी ब्राउझरमधील 1990 च्या दशकातील चालता येणाऱ्या rental store मध्ये बदलते. Docker command, reverse proxy आणि मर्यादा जाणून घ्या.

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

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

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

हा 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 ग्राफिक्स काढते. WebGL म्हणजे web graphics library; ती ब्राउझरचा GPU शी संवाद साधणारा इंटरफेस आहे. स्टोअरची geometry आणि box art स्क्रीन चालवणारे मशीन एकत्रितपणे render करते.

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

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

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

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

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

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

काहीही स्थापित करण्यापूर्वी व्हिडिओ स्टोअरचे डेमो वापरून पाहा

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

याचा hardware test म्हणून वापर करा. डेमो library मध्ये सुमारे 2,000 titles आहेत आणि त्यासाठी browser memory च्या साधारण 2 GB ची आवश्यकता असते. हे बहुतांश personal libraries पेक्षा अधिक आहे. तुम्ही browsing साठी वापरणार असलेल्या device वर डेमो अडखळत चालत असेल, तर तुमची स्वतःची library देखील अडखळेल. अशा वेळी मोठा 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 ला उत्तर दिले पाहिजे. काही सेकंदांत बंद होणारा 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 ला public interface सहित मशीनवरील प्रत्येक interface मिळतो. 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 करा.

August 2026 पर्यंतची एक महत्त्वाची मर्यादा अशी आहे: published image फक्त linux/amd64 आहे. Multi-architecture push मधील arm64 भाग emulation अंतर्गत अयशस्वी झाला आहे आणि native arm runners उपलब्ध होण्याची प्रतीक्षा आहे. arm64 VPS वर pull no matching manifest for linux/arm64/v8 in the manifest list entries मुळे अयशस्वी होते. अशा वेळी clone मधून build करणे हा उपाय आहे.

तुमच्या Jellyfin सर्व्हरकडे निर्देश करा

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

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

पहिले, Jellyfin browser कडून पोहोचण्याजोगा असणे आवश्यक आहे. Halcyon serve करणाऱ्या VPS कडूनच तो पोहोचण्याजोगा असणे पुरेसे नाही. 127.0.0.1:8096 शी bind केलेला Jellyfin स्थानिक चाचणीसाठी योग्य आहे; परंतु इतर सर्व users साठी 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 दिसतात.

प्रमाणीकरण पुढे ठेवून ते reverse proxy मागे ठेवा

vite preview हा preview server आहे. तो कोणतेही TLS (transport layer security) termination करत नाही आणि त्याचे स्वतःचे 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;
  }
}

कंटेनरसमोर domain name वापरताना आणखी एक setting आवश्यक आहे. DNS rebinding पासून संरक्षण करण्यासाठी Halcyon localhost, raw IP addresses आणि ज्या मशीनवर तो चालतो तिची नावे स्वीकारतो. कंटेनरमध्ये तो ज्या मशीनवर चालतो ती मशीन म्हणजे कंटेनरच असतो. त्यामुळे त्या मशीनचे 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 वापरल्यास ही तपासणी बंद होते. all फक्त बाहेरून कोणालाही पोहोचता येत नसलेल्या मशीनवर वापरा.

Store https:// वरून उपलब्ध केल्यानंतर 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 वर उपलब्ध करा किंवा 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 चा traffic वाहून नेतो. Remote Play stream हा UDP वरील WebRTC असतो आणि HTTP proxy मधून जात नाही. त्यामुळे 3478/udp आणि bundled TURN relay वापरात असल्यास 49200 ते 49260/udp वर त्यासाठी स्वतंत्र path आवश्यक असतो. तसेच वरील 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 करते. निष्क्रिय स्टोअर कोणतेही frames तयार करत नाही. तसेच window 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 तपासण्यासाठी काही seconds पुरेसे असतात. मात्र याबाबत वास्तववादी अपेक्षा ठेवा. लेखक flat mode चे वर्णन प्राथमिक आणि अद्याप development मध्ये असल्याचे करतो. कमकुवत clients साठी त्याचा fallback म्हणून वापर करा.

एखादा client 3D store साठी खूपच कमी क्षमतेचा असल्यास, समस्या स्पष्टपणे दिसते. 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 अयशस्वी झाला. Upstream कडे bug reports पाठवणे स्वीकार्य आहे; patches पाठवणे नाही. त्यामुळे release stream ही एका व्यक्तीची working state आहे.

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

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

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

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

10 August 2026 रोजी तो digest 0.3.1 होता. तो कॉपी करण्याऐवजी सध्याचा digest स्वतः वाचा. बदल करण्यापूर्वी release notes देखील वाचा, कारण येथे patch release मध्ये fixes सोबत store layout मधील बदलही असू शकतात.

FAQ

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

सामान्य वापरासाठी नाही. स्टोअर ब्राउझरमध्ये three.js द्वारे render केला जातो. त्यामुळे rendering क्लायंट मशीनवर होते आणि container port 1420 वर केवळ static files पुरवतो. Remote Play हा अपवाद आहे. तो server वर headless Chromium चालवतो आणि त्याचा परिणाम stream करतो. Hardware acceleration साठी /dev/dri container मध्ये map केले नसेल, तर या प्रक्रियेत CPU वर rendering होते.

Halcyon सार्वजनिक internet वर ठेवू शकतो का?

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

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

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

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

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

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

latest ऐवजी digest pin करा. docker buildx imagetools inspect ghcr.io/halcyon-video/halcyon-video:0.3.1 असलेल्या version चा digest वाचा, तो digest चालवा आणि release notes वाचल्यानंतरच बदल करा. August 2026 पर्यंत प्रकाशित image फक्त linux/amd64 आहे. त्यामुळे arm64 host वर clone मधून docker compose up -d वापरून build करावे लागेल.