openjutsu
영상에서 원클릭으로 인물 교체, ComfyUI·MiniMax H3 기반 오픈소스 로컬 힉스필드 겐주츠 대안, FLUX.3 Klein 재조명 지원
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗LeviTV — a single HTML file (levi-infotv.html) for 1920×1080 screens.
It scales to any TV and switches to a scrolling mobile layout on phones (≤ 900 px wide).
Locations (pick with ?loc=):
Add &view=full for the full-screen layout: the whole camera picture is shown
uncropped (1520×855, nothing on top of it), with the information in a sidebar and
the camera name, ad and ticker below the picture. TV and full views always keep
the 1920×1080 canvas, even on small screens. Click or press F to go full screen.
Picker page: https://oomfmarketing.github.io/levi-infotv/
Short links: /levi/, /levi/full/, /yllas/, /yllas/full/, /rovaniemi/, /rovaniemi/full/, /helsinki/, /helsinki/full/.
Add ?screen=<name> to name a physical TV in analytics, e.g. /levi/full/?screen=hotel-lobby.
robots.txt allows all crawlers including AI ones (GPTBot, OAI-SearchBot,
ClaudeBot, PerplexityBot, Google-Extended…); sitemap.xml; llms.txt summary.noindex and point canonically to the location page.Cookieless, so no consent banner is needed. Set it up in config.js:
analytics: { provider:'umami', id:'<website id>' }analytics: { provider:'plausible', id:'<domain>' }What is recorded:
| Event | When | Props |
|---|---|---|
| pageview | page opens | URL incl. loc, view |
screen_online | every heartbeatMinutes (default 60) on TV / full views | loc, view, screen |
qr_scan | someone scans an ad QR code (via go.html) | ad, loc, screen |
ad_click | someone taps an ad (mobile) | ad, loc, screen |
camera_pick | camera chosen on mobile | cam, loc |
Ad links and QR codes carry utm_source=infotv, utm_medium=qr|screen,
utm_campaign=<location>, utm_content=<screen>, so advertisers see the traffic
in their own analytics too. Ad targets live in config.js (ads).
| What | Source |
|---|---|
| Weather now | FMI observations: Levi fmisid=101886, Helsinki Kaisaniemi 100971; Ylläs uses the FMI forecast for the current hour |
| Forecast, cloud cover | FMI forecast for the location's coordinates |
| Northern lights | NOAA SWPC planetary Kp + Kp forecast |
| Sunrise / sunset / night mode | Calculated in the browser |
| Cameras | Levi YouTube live streams (two players, crossfaded) |
levi-infotv.html is the template. The location pages /levi/, /yllas/ and
/helsinki/ are generated from it — after editing it, run python3 build.py
(location texts, FAQs and SEO data live in build.py).
At the top of the <script> block:
LOCS holds every location: name, coordinates, FMI station, cameras,
ticker lines and ad banners. Add a new location by copying one block.SLOPE_FEED_URL is an optional live slope and lift feed (see below).An external bot writes slopes.json to the data branch of this repo (not main,
so the site is not rebuilt on every update). The page reads it from
https://raw.githubusercontent.com/Oomfmarketing/levi-infotv/data/slopes.json
every 10 minutes and shows e.g. "Slopes open 12/43 · Lifts open 8/26 · Snow depth 45 cm"
first in the ticker. Missing numbers or data older than 6 hours are not shown.
{
"updated": "2026-12-01T08:15:00Z",
"levi": {"updated": "2026-12-01T08:15:00Z", "slopesOpen": 12, "slopesTotal": 43,
"liftsOpen": 8, "liftsTotal": 26, "snowDepthCm": 45, "source": "https://www.levi.fi/"},
"yllas": {"updated": "2026-12-01T08:15:00Z", "slopesOpen": 20, "slopesTotal": 63,
"liftsOpen": 10, "liftsTotal": 29, "snowDepthCm": 52, "source": "https://www.yllas.fi/"}
}
Optional lists of what is open (shown as chips on the mobile card, and as "Open slopes: …" in the ticker):
"openSlopes": [{"name": "N.1", "difficulty": "red", "hours": "09:30-19:00"}],
"openLifts": [{"name": "Express gondoli", "hours": "09:30-19:00"}]
difficulty is green, blue, red or black; hours is today's opening time "HH:MM-HH:MM" (plain strings also work).
Keys are the location keys (levi, yllas, …). Every field is optional.
Hotels, restaurants and other businesses can show their own banners, ticker lines and logo on LeviTV screens.
levitv.com/hallinta/admin.html (log in with ADMIN_KEY). Create a customer; you get a
six-character screen code and a one-time management link (/hallinta/#t=…) to send to the customer.
"Uusi linkki" makes a new link and stops the old one. Season end date and on/off are set here./hallinta/. Name, location, logo, banners and ticker lines,
each with an optional schedule (weekdays, time of day, date range). Images are shrunk in the browser.levi-infotv.html?view=tv&c=CODE. Content refreshes every 5 min, schedules every minute. While a customer
has banners showing, LeviTV's own ads are hidden.levitv: worker.js sends /api/* to functions/api/[[path]].js and everything else
to the static assets (.assetsignore lists what is left out). One KV namespace, configured in wrangler.jsonc.
config.js → api tells the pages where it runs.The Worker levitv is connected to this repo with Workers Builds: every push to main runs npx wrangler deploy.
It is served at https://levitv.flat-cloud-8d4c.workers.dev. KV namespace levitv is bound as DB in wrangler.jsonc.
The admin key is set once: Workers & Pages → levitv → Settings → Variables and secrets → add secret ADMIN_KEY
(a long random password, at least 16 characters, keep it in the password manager).
Check: https://levitv.flat-cloud-8d4c.workers.dev/api/screen/AAAAAA answers {"error":"unknown code"}.
levitv.pages.dev belongs to an unrelated third party. Never use it as the API address.
Local test: npx wrangler dev --var ADMIN_KEY:<16+ chars> and point config.js → api at it.
android/ (built by GitHub Actions → levitv.com/app).tizen/ — see tizen/README.md. Opens /tv.html?app=tizen.webos/ — see webos/README.md. Opens /tv.html?app=webos; Actions builds the .ipk./tv.html is generated by build.py: the same page with JavaScript rewritten for older
TV browsers (esbuild, Chromium 56). Smart-TV apps get an on-page settings menu (OK button).