Spaces:
Running
Running
Upload 3 files
Browse files- Dockerfile +2 -0
- manifest.webmanifest +4 -2
- start.sh +23 -0
Dockerfile
CHANGED
|
@@ -10,6 +10,7 @@ RUN apt-get update && apt-get install -y \
|
|
| 10 |
python3-pip \
|
| 11 |
curl \
|
| 12 |
tzdata \
|
|
|
|
| 13 |
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
| 14 |
|
| 15 |
RUN pip3 install --no-cache-dir \
|
|
@@ -17,6 +18,7 @@ RUN pip3 install --no-cache-dir \
|
|
| 17 |
httpx \
|
| 18 |
huggingface_hub \
|
| 19 |
mutagen \
|
|
|
|
| 20 |
requests
|
| 21 |
|
| 22 |
COPY start.sh /app/start.sh
|
|
|
|
| 10 |
python3-pip \
|
| 11 |
curl \
|
| 12 |
tzdata \
|
| 13 |
+
libcairo2 \
|
| 14 |
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
| 15 |
|
| 16 |
RUN pip3 install --no-cache-dir \
|
|
|
|
| 18 |
httpx \
|
| 19 |
huggingface_hub \
|
| 20 |
mutagen \
|
| 21 |
+
cairosvg \
|
| 22 |
requests
|
| 23 |
|
| 24 |
COPY start.sh /app/start.sh
|
manifest.webmanifest
CHANGED
|
@@ -13,7 +13,9 @@
|
|
| 13 |
"theme_color": "#9B2626",
|
| 14 |
"categories": ["music", "entertainment", "lifestyle"],
|
| 15 |
"icons": [
|
| 16 |
-
{ "src": "/pwa-icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any
|
| 17 |
-
{ "src": "/pwa-icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any
|
|
|
|
|
|
|
| 18 |
]
|
| 19 |
}
|
|
|
|
| 13 |
"theme_color": "#9B2626",
|
| 14 |
"categories": ["music", "entertainment", "lifestyle"],
|
| 15 |
"icons": [
|
| 16 |
+
{ "src": "/pwa-icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" },
|
| 17 |
+
{ "src": "/pwa-icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" },
|
| 18 |
+
{ "src": "/pwa-icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable" },
|
| 19 |
+
{ "src": "/pwa-icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
|
| 20 |
]
|
| 21 |
}
|
start.sh
CHANGED
|
@@ -1827,6 +1827,17 @@ def _cf_enrich(film):
|
|
| 1827 |
|
| 1828 |
class H(http.server.BaseHTTPRequestHandler):
|
| 1829 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1830 |
def _is_admin_request(self):
|
| 1831 |
"""Verifica header X-Admin-Token con confronto a tempo costante."""
|
| 1832 |
if not ADMIN_LOG_TOKEN:
|
|
@@ -1837,6 +1848,8 @@ class H(http.server.BaseHTTPRequestHandler):
|
|
| 1837 |
def do_HEAD(self):
|
| 1838 |
self.send_response(200)
|
| 1839 |
self.send_header('Content-Type', 'text/plain')
|
|
|
|
|
|
|
| 1840 |
self.end_headers()
|
| 1841 |
|
| 1842 |
def do_GET(self):
|
|
@@ -2558,6 +2571,10 @@ class H(http.server.BaseHTTPRequestHandler):
|
|
| 2558 |
self.send_header('Content-Type', 'audio/mpeg')
|
| 2559 |
self.send_header('Cache-Control', 'no-cache, no-store')
|
| 2560 |
self.send_header('Access-Control-Allow-Origin', '*')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2561 |
self.end_headers()
|
| 2562 |
up.settimeout(30)
|
| 2563 |
while True:
|
|
@@ -2614,9 +2631,15 @@ class H(http.server.BaseHTTPRequestHandler):
|
|
| 2614 |
return
|
| 2615 |
self.send_response(200)
|
| 2616 |
self.send_header('Content-Length', '0')
|
|
|
|
|
|
|
| 2617 |
self.end_headers()
|
| 2618 |
try: self.wfile.flush()
|
| 2619 |
except: pass
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2620 |
_stream_to_icecast(self.rfile, mount)
|
| 2621 |
return
|
| 2622 |
|
|
|
|
| 1827 |
|
| 1828 |
class H(http.server.BaseHTTPRequestHandler):
|
| 1829 |
|
| 1830 |
+
# Keep-alive HTTP/1.1: una sola connessione TCP per client, riusata per
|
| 1831 |
+
# tutte le richieste HLS (playlist ogni ~4s + ogni segmento) invece di
|
| 1832 |
+
# aprirne una nuova ad ogni richiesta. Con molti dispositivi connessi
|
| 1833 |
+
# riduce di molto l'overhead di connessione.
|
| 1834 |
+
# NB: ogni risposta finita manda gia' Content-Length; gli unici flussi
|
| 1835 |
+
# "infiniti" (/stream e /stream_broadcast) mandano Connection: close.
|
| 1836 |
+
protocol_version = 'HTTP/1.1'
|
| 1837 |
+
# Chiude le connessioni keep-alive rimaste inattive, cosi' non tengono
|
| 1838 |
+
# occupato un thread all'infinito (le richieste finite durano ms).
|
| 1839 |
+
timeout = 65
|
| 1840 |
+
|
| 1841 |
def _is_admin_request(self):
|
| 1842 |
"""Verifica header X-Admin-Token con confronto a tempo costante."""
|
| 1843 |
if not ADMIN_LOG_TOKEN:
|
|
|
|
| 1848 |
def do_HEAD(self):
|
| 1849 |
self.send_response(200)
|
| 1850 |
self.send_header('Content-Type', 'text/plain')
|
| 1851 |
+
self.send_header('Connection', 'close') # HEAD senza body: evita ambiguita' keep-alive
|
| 1852 |
+
self.close_connection = True
|
| 1853 |
self.end_headers()
|
| 1854 |
|
| 1855 |
def do_GET(self):
|
|
|
|
| 2571 |
self.send_header('Content-Type', 'audio/mpeg')
|
| 2572 |
self.send_header('Cache-Control', 'no-cache, no-store')
|
| 2573 |
self.send_header('Access-Control-Allow-Origin', '*')
|
| 2574 |
+
# Flusso infinito, senza Content-Length: in HTTP/1.1 va dichiarato
|
| 2575 |
+
# esplicitamente che la connessione si chiude a fine stream.
|
| 2576 |
+
self.send_header('Connection', 'close')
|
| 2577 |
+
self.close_connection = True
|
| 2578 |
self.end_headers()
|
| 2579 |
up.settimeout(30)
|
| 2580 |
while True:
|
|
|
|
| 2631 |
return
|
| 2632 |
self.send_response(200)
|
| 2633 |
self.send_header('Content-Length', '0')
|
| 2634 |
+
self.send_header('Connection', 'close') # upload infinito: no keep-alive
|
| 2635 |
+
self.close_connection = True
|
| 2636 |
self.end_headers()
|
| 2637 |
try: self.wfile.flush()
|
| 2638 |
except: pass
|
| 2639 |
+
# Upload lungo: togli il timeout di idle keep-alive su QUESTA
|
| 2640 |
+
# connessione, altrimenti una pausa del presentatore la chiuderebbe.
|
| 2641 |
+
try: self.connection.settimeout(None)
|
| 2642 |
+
except Exception: pass
|
| 2643 |
_stream_to_icecast(self.rfile, mount)
|
| 2644 |
return
|
| 2645 |
|