commit dde15001d4f30b31d71b3977b3dec671f5b882fb Author: Linus Olofsson Date: Thu Sep 24 20:55:18 2026 +0200 publiccloud.se: himmel som följer sol, måne och väder i Örebro Frame-by-frame dag/natt-filmer, väderlager (Open-Meteo), vind, måne, norrsken (NOAA Kp), fyra informationsrutor med karta och platsval. Cloudflare Worker med Range-stöd för video. Co-Authored-By: Claude Opus 5.5 (1M context) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b4bde7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +.wrangler/ +*.master.mp4 +dns-backup*.json +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..1f36aba --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# PublicCloud – himlen över Örebro + +Källkoden till **https://publiccloud.se**: en helskärmshimmel som följer solen, månen och det aktuella vädret, med fyra informationsrutor runt en klocka. + +## Vad sidan gör + +- **Himlen följer klockan.** Dagfilmen spelas från verklig soluppgång till solnedgång och nattfilmen från solnedgång till soluppgång, en bildruta åt gången (en genomspelning per period, med mjuk övertoning mellan bildrutor). +- **Vädret läggs ovanpå** (Open-Meteo, var 10:e minut): klart (molnen tonas bort), växlande (solen genom molnen), mulet, dimma, duggregn, regn, kraftigt regn med droppar på "glaset", åska med blixtar, snö. +- **Vind** (hastighet, byar, riktning): snett regn, blåsande snö och droppar, vindstråk, höstlöv (sep–nov) och byar. Vyn är vänd mot söder, så västlig vind blåser åt vänster. +- **Natten:** månen med rätt fas och position (skymd bakom molnen vid växlande molnighet), glittrande stjärnor, mörkt molntäcke vid mulet, **norrsken** från NOAA:s Kp-index. +- **Fyra rutor:** *Just nu* (väder, temperatur, vind, måne, sol, plats) · *Plats* (karta, "Utgå från min plats" via GPS, klick i kartan, standard Örebro slott) · *Kväll & natt* (betyg för stjärnhimlen, norrskenschans, meteorregn, fullmåne/nymåne) · *Fotoljus* (gyllene och blå timmen med väder, månens upp- och nedgång, dimma, regnbåge, nattlysande moln). + +## Struktur + +``` +site/ + public/index.html hela sidan (HTML, CSS, JS – inga byggsteg) + public/_headers cache-regler (filmerna cachas i ett år → nytt filnamn vid ny film) + public/video/ day-v2 / night som WebM (VP9) + MP4 (H.264, reserv för äldre Safari) + worker.js Cloudflare Worker: statiska filer + HTTP Range (206) för /video/* (krävs av Safari/iOS) + wrangler.jsonc Worker-konfiguration (namn publiccloud-sky) +tools/ + upscale-slowmo.sh hur filmerna togs fram: Real-ESRGAN x4plus (uppskalning) + RIFE v4.6 (slowmotion) +``` + +## Driftsättning + +Sajten körs som en Cloudflare Worker med statiska filer och custom domain `publiccloud.se`. + +```bash +cd site +export CLOUDFLARE_API_TOKEN=... # konto-token med Workers-rättighet +export CLOUDFLARE_ACCOUNT_ID=... +npx wrangler deploy +``` + +## Testparametrar + +| Parameter | Exempel | Effekt | +|---|---|---| +| `t` | `?t=2026-09-26T23:00%2B02:00` | startar klockan vid en viss tid | +| `speed` | `?speed=600` | kör klockan snabbare | +| `weather` | `?weather=thunder` | tvingar väder: clear, partly, overcast, fog, drizzle, rain, heavyrain, thunder, snow | +| `wind`, `winddir` | `?wind=75&winddir=270` | tvingar vind (km/h, grader) | +| `kp` | `?kp=6.5` | tvingar Kp-index (norrsken) | +| `instant` | `?instant=1` | inga övertoningar (för skärmdumpar) | +| `debug` | `?debug=1` | visar bildruta, sol, väder, vind, måne, norrsken | + +## Datakällor + +- Väder och prognos per timme: [Open-Meteo](https://open-meteo.com/) (gratis för icke-kommersiellt bruk) +- Kp-index nu och 3-dygnsprognos: [NOAA SWPC](https://www.swpc.noaa.gov/) +- Karta: [OpenStreetMap](https://www.openstreetmap.org/copyright) via [Leaflet](https://leafletjs.com/) 1.9.4 (cdnjs, SRI) +- Platsnamn: OpenStreetMap Nominatim +- Sol- och månberäkningar: formler från SunCalc (Vladimir Agafonkin), inbäddade i sidan +- Meteorregn: American Meteor Society / IMO:s kalendrar diff --git a/site/public/_headers b/site/public/_headers new file mode 100644 index 0000000..32a1b9e --- /dev/null +++ b/site/public/_headers @@ -0,0 +1,4 @@ +/video/* + Cache-Control: public, max-age=31536000, immutable +/ + Cache-Control: public, max-age=300 diff --git a/site/public/index.html b/site/public/index.html new file mode 100644 index 0000000..f53848b --- /dev/null +++ b/site/public/index.html @@ -0,0 +1,947 @@ + + + + + +publiccloud.se + + + + + + + + +
+ + + +
+
+
+ + +
+
+
+ Date: + Sunrise: + Sunset: + Current Time: +
+
+

Just nu

+
–
+
+
+
+
+

Plats

+
+
Örebro slott
+
+ + +
+
Klicka i kartan för att välja en annan plats.
+
+
+

Kväll & natt

+
+
+
+

Fotoljus

+
+
+
+
+ + + diff --git a/site/public/video/day-v2.mp4 b/site/public/video/day-v2.mp4 new file mode 100644 index 0000000..3dbbba5 Binary files /dev/null and b/site/public/video/day-v2.mp4 differ diff --git a/site/public/video/day-v2.webm b/site/public/video/day-v2.webm new file mode 100644 index 0000000..b6a8eaa Binary files /dev/null and b/site/public/video/day-v2.webm differ diff --git a/site/public/video/night.mp4 b/site/public/video/night.mp4 new file mode 100644 index 0000000..1223c8a Binary files /dev/null and b/site/public/video/night.mp4 differ diff --git a/site/public/video/night.webm b/site/public/video/night.webm new file mode 100644 index 0000000..ecc711e Binary files /dev/null and b/site/public/video/night.webm differ diff --git a/site/worker.js b/site/worker.js new file mode 100644 index 0000000..3d62b53 --- /dev/null +++ b/site/worker.js @@ -0,0 +1,24 @@ +// Static assets + HTTP Range for /video/* (Safari/iOS will not play video without 206 responses) +export default { + async fetch(req, env) { + const url = new URL(req.url); + const range = req.headers.get('Range'); + if (!url.pathname.startsWith('/video/') || !range) return env.ASSETS.fetch(req); + + const full = await env.ASSETS.fetch(new Request(url, { method: 'GET' })); + if (!full.ok) return full; + const buf = await full.arrayBuffer(), size = buf.byteLength; + const m = /^bytes=(\d*)-(\d*)$/.exec(range.trim()); + let start, end; + if (m && m[1] !== '') { start = +m[1]; end = m[2] !== '' ? Math.min(+m[2], size - 1) : size - 1; } + else if (m && m[2] !== '') { start = Math.max(0, size - +m[2]); end = size - 1; } + if (!m || start > end || start >= size) + return new Response(null, { status: 416, headers: { 'Content-Range': `bytes */${size}` } }); + + const h = new Headers(full.headers); + h.set('Content-Range', `bytes ${start}-${end}/${size}`); + h.set('Content-Length', String(end - start + 1)); + h.set('Accept-Ranges', 'bytes'); + return new Response(req.method === 'HEAD' ? null : buf.slice(start, end + 1), { status: 206, headers: h }); + }, +}; diff --git a/site/wrangler.jsonc b/site/wrangler.jsonc new file mode 100644 index 0000000..1ef5a00 --- /dev/null +++ b/site/wrangler.jsonc @@ -0,0 +1,7 @@ +{ + "name": "publiccloud-sky", + "main": "worker.js", + "compatibility_date": "2026-09-01", + "assets": { "directory": "./public", "binding": "ASSETS", "run_worker_first": ["/video/*"] }, + "workers_dev": true +} diff --git a/tools/upscale-slowmo.sh b/tools/upscale-slowmo.sh new file mode 100644 index 0000000..89e5327 --- /dev/null +++ b/tools/upscale-slowmo.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e +R=/c/Users/Demo/tools/ai-video; W=$R/work; cd $R +ES="$R/esrgan/realesrgan-ncnn-vulkan.exe"; RF="$R/rife-ncnn-vulkan-20221029-windows/rife-ncnn-vulkan.exe" +declare -A SLOW=([a1]=3 [a2]=3 [a3]=3 [a4]=3 [a5]=3 [b1]=2) +for s in a1 a2 a3 a4 a5 b1; do + echo "[$(date +%T)] $s upscale"; mkdir -p $W/$s/x4 $W/$s/hd $W/$s/slow + "$ES" -i $W/$s/src -o $W/$s/x4 -n realesrgan-x4plus -m $R/esrgan/models -f png >/dev/null 2>&1 + ffmpeg -v error -y -i $W/$s/x4/%05d.png -vf "scale=1920:1080:flags=lanczos" $W/$s/hd/%05d.png + rm -rf $W/$s/x4 + n=$(( $(ls $W/$s/hd | wc -l) * ${SLOW[$s]} )) + echo "[$(date +%T)] $s rife -> $n frames" + "$RF" -i $W/$s/hd -o $W/$s/slow -m $R/rife-ncnn-vulkan-20221029-windows/rife-v4.6 -n $n -f %05d.png >/dev/null 2>&1 +done +mkdir -p $W/img +for f in f3557d7c-e4fa-45fe-9925-4fa301e1944d 476dce33-89cd-4a59-b7b0-a7df779f126b f27c81d7-6978-4c57-8e56-537fa96c53c5 e3af2663-05d6-4ee1-8d27-6a87866b4237 89b40766-a7a1-4bc7-b7e4-e672ec36d130; do + echo "[$(date +%T)] img $f"; "$ES" -i /c/Users/Demo/Downloads/$f.png -o $W/img/$f.png -n realesrgan-x4plus -m $R/esrgan/models >/dev/null 2>&1 +done +cp /c/Users/Demo/Downloads/6a99d399-e4a8-46a7-82e9-74b4c21eaddb.png $W/img/ +echo "[$(date +%T)] DONE"