Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Leibinger015/2f5e99b5920c1a3b8ca14cfa0a27321b to your computer and use it in GitHub Desktop.

Select an option

Save Leibinger015/2f5e99b5920c1a3b8ca14cfa0a27321b to your computer and use it in GitHub Desktop.
WebApp: For Smartphone and Tablets
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<title>auraTiVi</title>
<link rel="apple-touch-icon" href="img/apple-touch-icon.png" />
<style>
*, *::before, *::after {
margin: 0; padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
button { border: none; cursor: pointer; outline: none; font-family: inherit; }
html, body {
width: 100%; height: 100%;
background: #0e0e11;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
-webkit-font-smoothing: antialiased;
color: #f2f2f7;
}
#app {
display: flex;
flex-direction: column;
width: 100%;
height: 100dvh;
max-width: 560px;
margin: 0 auto;
background: #111113;
position: relative;
overflow: hidden;
box-shadow:
0 0 0 1px rgba(255,255,255,0.07),
0 20px 60px rgba(0,0,0,0.85),
0 4px 20px rgba(0,0,0,0.6);
}
.safe-top {
flex-shrink: 0;
height: env(safe-area-inset-top, 0px);
background: #000;
}
#video-wrap {
flex-shrink: 0;
position: relative;
width: 100%;
aspect-ratio: 16 / 9;
background: #000;
border-bottom: 2px solid #3a3a3e;
box-shadow: 0 4px 20px rgba(0,0,0,0.7);
z-index: 2;
}
#player {
width: 100%; height: 100%;
display: block; object-fit: cover;
}
#placeholder {
position: absolute; inset: 0;
background: #000;
display: flex; flex-direction: column;
align-items: center; justify-content: center; gap: 12px;
transition: opacity 0.3s ease;
}
#placeholder.hidden { opacity: 0; pointer-events: none; }
.spinner {
width: 36px; height: 36px;
border: 3px solid rgba(255,255,255,0.1);
border-top-color: #d4622a;
border-radius: 50%;
animation: spin 0.75s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
#ph-name { color: rgba(255,255,255,0.38); font-size: 13px; font-weight: 500; }
#overlay {
position: absolute; inset: 0;
display: flex; flex-direction: column;
justify-content: space-between;
opacity: 0; pointer-events: none;
transition: opacity 0.22s ease;
background: linear-gradient(180deg,
rgba(0,0,0,0.52) 0%, transparent 30%,
transparent 60%, rgba(0,0,0,0.65) 100%);
}
#overlay.show { opacity: 1; pointer-events: all; }
.ov-top {
display: flex; align-items: center;
justify-content: space-between; padding: 10px 12px;
}
.vid-icon-btn {
width: 32px; height: 32px;
background: rgba(0,0,0,0.38);
border: 1px solid rgba(255,255,255,0.15);
border-radius: 9px; color: #fff;
display: flex; align-items: center; justify-content: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.5);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.live-badge {
display: flex; align-items: center; gap: 5px;
background: rgba(0,0,0,0.42);
border: 1px solid rgba(255,255,255,0.14);
border-radius: 8px; padding: 4px 9px;
box-shadow: 0 2px 8px rgba(0,0,0,0.4);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.live-dot {
width: 7px; height: 7px;
background: #d4622a; border-radius: 50%;
box-shadow: 0 0 6px #d4622a;
animation: livepulse 2s ease-in-out infinite;
}
@keyframes livepulse { 0%,100%{opacity:1} 50%{opacity:0.35} }
.live-text { color: #fff; font-size: 11px; font-weight: 700; letter-spacing: 0.8px; }
.ch-badge {
background: #d4622a; color: #fff;
font-size: 11px; font-weight: 700;
padding: 4px 10px; border-radius: 8px;
letter-spacing: 0.4px;
box-shadow: 0 2px 10px rgba(212,98,42,0.45);
}
.ov-center {
display: flex; align-items: center;
justify-content: center; gap: 28px;
}
.ov-ctrl {
width: 46px; height: 46px;
background: rgba(0,0,0,0.38);
border: 1px solid rgba(255,255,255,0.16);
border-radius: 50%; color: #fff;
display: flex; align-items: center; justify-content: center;
box-shadow: 0 3px 12px rgba(0,0,0,0.5);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
transition: transform 0.1s;
}
.ov-ctrl:active { transform: scale(0.88); }
.ov-ctrl.big {
width: 58px; height: 58px;
background: rgba(255,255,255,0.16);
border-color: rgba(255,255,255,0.28);
box-shadow: 0 6px 22px rgba(0,0,0,0.55);
}
.ov-bottom { padding: 8px 12px 10px; }
.prog-row { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.prog-track {
flex: 1; height: 3px;
background: rgba(255,255,255,0.22);
border-radius: 3px; overflow: hidden;
}
.prog-fill { height: 100%; width: 99%; background: #fff; border-radius: 3px; }
.t-lbl { color: rgba(255,255,255,0.75); font-size: 11px; font-variant-numeric: tabular-nums; }
.meta-row { display: flex; align-items: center; justify-content: space-between; }
#prog-title {
color: rgba(255,255,255,0.6);
font-size: 10px; font-weight: 600;
text-transform: uppercase; letter-spacing: 0.9px;
}
.meta-btns { display: flex; gap: 10px; }
.meta-btn { background: none; color: rgba(255,255,255,0.6); font-size: 15px; padding: 2px; }
#remote {
flex: 1;
display: flex; flex-direction: column;
min-height: 0; overflow: hidden;
position: relative;
background:
repeating-linear-gradient(
92deg,
rgba(255,255,255,0.012) 0px,
rgba(255,255,255,0.012) 1px,
transparent 1px,
transparent 3px
),
linear-gradient(180deg,
#2e2e33 0%,
#262629 40%,
#212124 70%,
#1c1c1f 100%
);
border-top: 1px solid rgba(255,255,255,0.13);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.09),
inset 0 -1px 0 rgba(0,0,0,0.5);
}
#remote::before {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(ellipse 70% 55% at 50% 38%,
rgba(212,98,42,0.07) 0%,
transparent 70%
);
pointer-events: none;
}
.remote-body { flex: 1; display: flex; min-height: 0; position: relative; z-index: 1; }
.col-divider {
width: 1px; flex-shrink: 0;
background: linear-gradient(180deg,
transparent 0%,
rgba(255,255,255,0.09) 20%,
rgba(255,255,255,0.09) 80%,
transparent 100%
);
}
.remote-col {
flex: 1;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
gap: 12px; padding: 18px 14px;
}
.ch-cluster {
display: flex; align-items: center; gap: 6px;
background: linear-gradient(180deg, #141416 0%, #1e1e22 100%);
border: 1px solid rgba(0,0,0,0.7);
border-radius: 50px; padding: 10px 12px;
box-shadow:
inset 0 2px 6px rgba(0,0,0,0.7),
inset 0 1px 0 rgba(0,0,0,0.5),
0 1px 0 rgba(255,255,255,0.09),
0 4px 14px rgba(0,0,0,0.5);
}
.logo-display {
position: relative;
width: 146px;
height: 146px;
flex-shrink: 0;
border-radius: 14px;
background: linear-gradient(145deg, #141416 0%, #1a1a1e 60%, #141416 100%);
border: 1px solid rgba(0,0,0,0.7);
overflow: hidden;
box-shadow:
inset 0 3px 8px rgba(0,0,0,0.8),
inset 0 1px 0 rgba(0,0,0,0.6),
inset 0 -1px 0 rgba(255,255,255,0.03),
0 1px 0 rgba(255,255,255,0.07),
0 4px 14px rgba(0,0,0,0.5);
}
.logo-display::before {
content: "";
position: absolute; inset: 0;
background: radial-gradient(ellipse 70% 60% at 50% 50%,
rgba(212,98,42,0.09) 0%,
transparent 70%);
pointer-events: none;
z-index: 0;
}
.logo-display::after {
content: "";
position: absolute;
top: 0; left: 0; right: 0;
height: 40%;
background: linear-gradient(180deg,
rgba(255,255,255,0.045) 0%,
transparent 100%);
border-radius: 14px 14px 0 0;
pointer-events: none;
z-index: 0;
}
.logo-display img {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 72%; height: 72%;
object-fit: contain;
z-index: 1;
filter: drop-shadow(0 2px 6px rgba(0,0,0,0.7));
transition: opacity 0.25s ease;
}
.logo-display img.hidden { opacity: 0; }
.logo-placeholder {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
z-index: 1;
color: #d4622a;
opacity: 0.55;
display: flex; align-items: center; justify-content: center;
}
.ch-arrow {
width: 58px; height: 52px;
background: linear-gradient(145deg, #2e2e32 0%, #222226 55%, #1a1a1e 100%);
border: 1px solid rgba(0,0,0,0.6);
border-radius: 40px;
color: #d4622a;
display: flex; align-items: center; justify-content: center;
box-shadow:
0 4px 0 rgba(0,0,0,0.55),
0 6px 16px rgba(0,0,0,0.5),
inset 0 1px 0 rgba(255,255,255,0.1);
transition: transform 0.1s, box-shadow 0.1s;
-webkit-user-select: none;
}
.ch-arrow:active {
transform: translateY(3px);
box-shadow:
0 1px 0 rgba(0,0,0,0.55),
0 2px 6px rgba(0,0,0,0.4),
inset 0 1px 0 rgba(255,255,255,0.06);
}
.btn-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px 16px;
align-items: center;
justify-items: center;
}
.btn-cell {
display: flex; flex-direction: column;
align-items: center; gap: 7px;
}
.remote-lbl {
color: #4a4a4f;
font-size: 9px; font-weight: 600;
text-transform: uppercase; letter-spacing: 1.1px;
text-shadow: 0 1px 0 rgba(0,0,0,0.8);
}
.sub-btn {
width: 64px; height: 64px;
border-radius: 50%;
color: #fff;
font-size: 28px; font-weight: 400; font-style: normal;
letter-spacing: 0;
display: flex; align-items: center; justify-content: center;
transition: transform 0.1s, box-shadow 0.1s;
-webkit-user-select: none;
background: linear-gradient(145deg, #f0804a 0%, #d4622a 55%, #b84e1e 100%);
border: 1px solid rgba(0,0,0,0.4);
box-shadow:
0 5px 0 rgba(0,0,0,0.5),
0 8px 24px rgba(212,98,42,0.55),
0 2px 8px rgba(0,0,0,0.5),
inset 0 1px 0 rgba(255,255,255,0.28),
inset 0 -1px 0 rgba(0,0,0,0.2);
}
.sub-btn:active {
transform: translateY(3px);
box-shadow:
0 2px 0 rgba(0,0,0,0.5),
0 4px 12px rgba(212,98,42,0.4),
inset 0 1px 0 rgba(255,255,255,0.15);
}
.sub-btn.off {
color: #4a4a4f;
background: linear-gradient(145deg, #323236 0%, #252528 55%, #1e1e21 100%);
box-shadow:
0 5px 0 rgba(0,0,0,0.55),
0 8px 20px rgba(0,0,0,0.5),
inset 0 1px 0 rgba(255,255,255,0.1),
inset 0 -1px 0 rgba(0,0,0,0.3);
}
.ch-bar-wrap {
flex-shrink: 0;
position: relative; z-index: 1;
background: linear-gradient(180deg, #0e0e11 0%, #111114 100%);
border-top: 1px solid rgba(0,0,0,0.8);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.05),
0 -6px 20px rgba(0,0,0,0.5);
padding: 10px 0;
padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}
.ch-bar {
display: flex; gap: 8px;
overflow-x: auto;
padding: 2px 14px 4px;
scrollbar-width: none;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
}
.ch-bar::-webkit-scrollbar { display: none; }
.ch-pill {
flex-shrink: 0;
scroll-snap-align: start;
background: linear-gradient(180deg, #2a2a2e 0%, #1e1e22 100%);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 13px;
padding: 8px 14px 6px;
color: #aeaeb2;
font-size: 12px; font-weight: 700;
white-space: nowrap;
-webkit-user-select: none;
display: flex; flex-direction: column; align-items: center;
min-width: 54px;
box-shadow:
0 3px 0 rgba(0,0,0,0.5),
0 5px 14px rgba(0,0,0,0.5),
inset 0 1px 0 rgba(255,255,255,0.09);
transition: transform 0.15s, box-shadow 0.15s;
}
.ch-pill.active {
background: linear-gradient(145deg, #f0804a 0%, #d4622a 60%, #b84e1e 100%);
border-color: rgba(240,128,74,0.4);
color: #fff;
box-shadow:
0 3px 0 rgba(0,0,0,0.4),
0 6px 22px rgba(212,98,42,0.55),
inset 0 1px 0 rgba(255,255,255,0.28);
}
.ch-pill:active {
transform: translateY(2px);
box-shadow: 0 1px 0 rgba(0,0,0,0.5), 0 2px 6px rgba(0,0,0,0.4);
}
.pill-meta {
display: flex; align-items: center; justify-content: center;
gap: 4px; margin-top: 3px; line-height: 1;
}
.pill-tag {
font-size: 8px; font-weight: 700; opacity: 0.55;
letter-spacing: 0.5px; text-transform: uppercase;
}
.pill-lock {
display: flex; align-items: center; opacity: 0.55;
}
.safe-bottom {
flex-shrink: 0;
height: env(safe-area-inset-bottom, 0px);
background: #111113;
}
body::after {
content: "";
display: block;
position: fixed;
bottom: 0; left: 0; right: 0;
height: env(safe-area-inset-bottom, 0px);
background: #0e0e11;
z-index: 10000;
pointer-events: none;
}
#rotate-warning {
display: none;
position: fixed; inset: 0; z-index: 9999;
background: #0d0d0f;
flex-direction: column;
align-items: center; justify-content: center;
gap: 20px;
padding: 40px;
text-align: center;
}
.rotate-icon {
font-size: 56px;
animation: rotateHint 2s ease-in-out infinite;
}
@keyframes rotateHint {
0%,100% { transform: rotate(0deg); }
40% { transform: rotate(-90deg); }
60% { transform: rotate(-90deg); }
}
.rotate-title {
color: #f2f2f7; font-size: 18px; font-weight: 700; line-height: 1.35;
}
.rotate-sub {
color: #636366; font-size: 14px; line-height: 1.5;
}
#fs-video::cue { display: none; }
#fs-overlay {
display: none;
position: fixed; inset: 0; z-index: 8000;
background: #000;
align-items: center; justify-content: center;
}
#fs-overlay.active { display: flex; }
#fs-overlay #player {
width: 100%; height: 100%;
object-fit: contain;
display: block;
}
#fs-close {
position: absolute;
top: calc(env(safe-area-inset-top, 16px) + 10px);
right: 16px;
width: 38px; height: 38px;
background: rgba(0,0,0,0.55);
border: 1.5px solid rgba(255,255,255,0.25);
border-radius: 50%;
color: #fff; font-size: 18px;
display: flex; align-items: center; justify-content: center;
cursor: pointer;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
box-shadow: 0 2px 10px rgba(0,0,0,0.5);
z-index: 8001;
}
#fs-close:active { transform: scale(0.9); }
#toast {
position: fixed;
top: calc(env(safe-area-inset-top, 0px) + 12px);
left: 50%; transform: translateX(-50%) translateY(-8px);
background: rgba(26,26,28,0.96);
backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
border: 1px solid rgba(255,255,255,0.1);
color: #f2f2f7; font-size: 13px; font-weight: 500;
padding: 10px 18px; border-radius: 14px;
box-shadow: 0 6px 24px rgba(0,0,0,0.6);
opacity: 0; pointer-events: none;
transition: opacity 0.25s, transform 0.25s;
z-index: 9999; max-width: 88vw; text-align: center;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
@media (min-width: 560px) {
#app {
border-left: 1px solid rgba(255,255,255,0.06);
border-right: 1px solid rgba(255,255,255,0.06);
}
}
@media (min-width: 768px) {
html {
height: 100%;
background: #0e0e11;
overflow: hidden;
}
body {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
min-height: 100vh;
overflow: hidden;
background-color: #0e0e11;
background-image:
radial-gradient(ellipse 80% 60% at 50% 30%,
rgba(212,98,42,0.06) 0%, transparent 60%),
radial-gradient(ellipse 60% 50% at 50% 90%,
rgba(0,176,186,0.04) 0%, transparent 60%),
linear-gradient(180deg, #1a1a1e 0%, #111113 40%, #0e0e11 100%);
}
body::after { display: none !important; height: 0 !important; content: none !important; background: transparent !important; }
#app-scaler {
transform-origin: center center;
padding: 3px;
border-radius: 22px;
background: linear-gradient(180deg,
#d4622a 0%,
#b85c28 30%,
#0090a0 70%,
#00b0ba 100%
);
box-shadow:
0 -6px 24px rgba(212,98,42,0.35),
0 6px 24px rgba(0,176,186,0.25),
0 20px 60px rgba(0,0,0,0.7),
0 4px 20px rgba(0,0,0,0.5);
flex-shrink: 0;
}
#app {
width: 460px !important;
max-width: 460px !important;
height: 720px !important;
border-radius: 20px;
overflow: hidden;
margin: 0;
box-shadow: none;
}
.safe-top { height: 0px !important; }
}
</style>
</head>
<body>
<div id="app-scaler">
<div id="app">
<div class="safe-top"></div>
<div id="video-wrap" onclick="tapVideo()">
<video id="player" playsinline webkit-playsinline></video>
<div id="placeholder">
<div class="spinner"></div>
<div id="ph-name">Sender wird geladen ...</div>
</div>
<div id="overlay">
<div class="ov-top">
<button class="vid-icon-btn" onclick="event.stopPropagation();goFS()">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
</svg>
</button>
<div class="live-badge">
<div class="live-dot"></div>
<span class="live-text">LIVE</span>
</div>
<span class="ch-badge" id="ch-badge">--</span>
</div>
<div class="ov-center" onclick="event.stopPropagation()">
<button class="ov-ctrl" onclick="seek(-10)">
<svg width="20" height="20" viewBox="0 0 24 24" fill="white">
<path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/>
</svg>
</button>
<button class="ov-ctrl big" id="play-btn" onclick="togglePlay()">
<svg id="play-icon" width="26" height="26" viewBox="0 0 24 24" fill="white">
<path d="M6 4h4v16H6zM14 4h4v16h-4z"/>
</svg>
</button>
<button class="ov-ctrl" onclick="seek(10)">
<svg width="20" height="20" viewBox="0 0 24 24" fill="white">
<path d="M12 5V1l5 5-5 5V7c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6h2c0 4.42-3.58 8-8 8s-8-3.58-8-8 3.58-8 8-8z"/>
</svg>
</button>
</div>
<div class="ov-bottom" onclick="event.stopPropagation()">
<div class="prog-row">
<span class="t-lbl">LIVE</span>
<div class="prog-track"><div class="prog-fill"></div></div>
<span class="t-lbl">-0:05</span>
</div>
<div class="meta-row">
<span id="prog-title">--</span>
<div class="meta-btns">
<button class="meta-btn">⏤</button>
<button class="meta-btn">···</button>
</div>
</div>
</div>
</div>
</div>
<div id="remote">
<div class="remote-body">
<div class="remote-col">
<div class="ch-cluster">
<button class="ch-arrow" onclick="chStep(-1)">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#d4622a" stroke-width="2.5" stroke-linecap="round"><path d="M15 18l-6-6 6-6"/></svg>
</button>
<button class="ch-arrow" onclick="chStep(1)">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#d4622a" stroke-width="2.5" stroke-linecap="round"><path d="M9 18l6-6-6-6"/></svg>
</button>
</div>
<span class="remote-lbl">Kanal</span>
<div class="logo-display" id="logo-display">
<img id="logo-img" src="" alt="" class="hidden">
<div class="logo-placeholder" id="logo-ph" style="display:flex;">
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" stroke="#d4622a" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="2" y="7" width="20" height="13" rx="2"/>
<path d="M8 7V5a2 2 0 0 1 4 0v2"/>
<circle cx="12" cy="13.5" r="2.5" fill="#d4622a" stroke="none" opacity="0.6"/>
</svg>
</div>
</div>
</div>
<div class="col-divider"></div>
<div class="remote-col">
<div class="btn-grid">
<div class="btn-cell">
<button class="sub-btn off" id="mute-btn" onclick="toggleMute()">
<svg id="mute-icon" width="22" height="22" viewBox="0 0 24 24">
<path d="M11 5L6 9H2v6h4l5 4V5z" fill="#636366"/>
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07" fill="none" stroke="#636366" stroke-width="2" stroke-linecap="round"/>
</svg>
</button>
<span class="remote-lbl">Ton</span>
</div>
<div class="btn-cell">
<button class="sub-btn off" id="sub-btn" onclick="toggleSub()">🅤</button>
<span class="remote-lbl">Untertitel</span>
</div>
<div class="btn-cell">
<button class="sub-btn off" id="fs-btn" onclick="openFS()" style="font-size:22px;">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
</svg>
</button>
<span class="remote-lbl">Vollbild</span>
</div>
<div class="btn-cell">
<button class="sub-btn off" id="info-btn" onclick="openInfo()" style="font-size:22px;">ⓘ</button>
<span class="remote-lbl">Info</span>
</div>
</div>
</div>
</div>
<div class="ch-bar-wrap">
<div class="ch-bar" id="ch-bar"></div>
</div>
</div>
</div>
</div>
<div id="info-backdrop" onclick="closeInfo()" style="display:none; position:fixed; inset:0; z-index:9000; background:rgba(0,0,0,0.55); backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px);"></div>
<div id="info-modal" onclick="closeInfo()" style="
display:none; position:fixed; left:50%; bottom:0; z-index:9001;
width:100%; max-width:560px; transform:translateX(-50%) translateY(100%);
background:#1c1c1f; border-radius:20px 20px 0 0;
border-top:1px solid rgba(255,255,255,0.1);
box-shadow:0 -8px 40px rgba(0,0,0,0.7);
transition:transform 0.35s cubic-bezier(0.32,0.72,0,1);
padding:24px 24px calc(24px + env(safe-area-inset-bottom,0px));
">
<div style="width:36px;height:4px;background:rgba(255,255,255,0.2);border-radius:2px;margin:0 auto 22px;"></div>
<div style="display:flex;align-items:center;justify-content:space-between;gap:12px;">
<div style="font-size:17px;font-weight:700;color:#d4622a;margin-bottom:4px;">auraTiVi by anb030 <span style="color:#636366;font-weight:400;font-size:12px;"><br>
• Version: 2.265 (260313)<br>
• M3U-Liste / TV-Sender: 260313 / 28</span></div>
<img src="img/app_icon.png" alt="Icon" style="width:64px;height:64px;border-radius:14px;flex-shrink:0;box-shadow:0 4px 14px rgba(0,0,0,0.5);">
</div>
<div style="width:100%;height:1px;background:rgba(255,255,255,0.08);margin:14px 0;"></div>
<div style="font-size:14px;color:#aeaeb2;line-height:2;">
<b style="color:#f2f2f7;">Die Bedienelemente:</b><br>
<span style="display:flex;align-items:center;gap:10px;margin-top:6px;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#aeaeb2" stroke-width="2" stroke-linecap="round"><path d="M15 18l-6-6 6-6"/></svg>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#aeaeb2" stroke-width="2" stroke-linecap="round"><path d="M9 18l6-6-6-6"/></svg>
<span>Senderauswahltasten [Key: ↑←↓→]</span>
</span>
<span style="display:flex;align-items:center;gap:10px;margin-top:6px;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#aeaeb2" stroke-width="2" stroke-linecap="round"><path d="M11 5L6 9H2v6h4l5 4V5z"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>
<span>Ton AN / AUS [Key: M]</span>
</span>
<span style="display:flex;align-items:center;gap:10px;margin-top:6px;">
<span style="font-size:18px;line-height:1;">🅤</span>
<span>Untertitel AN / AUS [Key: U]</span>
</span>
<span style="display:flex;align-items:center;gap:10px;margin-top:6px;">
<span style="font-size:18px;line-height:1;">▶</span>
<span>Wiedergabe / Pause [Key: Space]</span>
</span>
<span style="display:flex;align-items:center;gap:10px;margin-top:6px;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#aeaeb2" stroke-width="2" stroke-linecap="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>
<span>Vollbild [Key: F], mit X schließen [Key: ESC]</span>
</span>
<span style="display:block;margin-top:8px;color:#636366;font-size:12px;">ⓘ Im <strong>Vollbildmodus</strong> ist das Gerät <strong>drehbar</strong>! Die <strong>Nutzung</strong> dieser GitHub <a href="https://github.com/iptv-org/iptv/tree/master/streams" style="color:#00b0ba; text-decoration:none;">M3U-Listen</a> und <a href="https://github.com/tv-logo/tv-logos/tree/main/countries/germany" style="color:#00b0ba; text-decoration:none;">TV-Logos</a> sind rechtlich eine <strong>Grauzone</strong>.</span>
</div>
<div style="width:100%;height:1px;background:rgba(255,255,255,0.08);margin:14px 0;"></div>
<div style="font-size:12px;color:#636366;text-align:center;">Designed for modern iOS experience!<br>Developed with ♥ by…<br>© <a href="https://anb030.de/a/" target="_blank" style="color:#00b0ba;text-decoration:none;">anb030.de</a>
<br><br>
<img src="img/webappready.png" alt="auraTiVi is WebApp Ready" style="max-width:80px;opacity:0.8;">
</div>
</div>
<div id="rotate-warning">
<div class="rotate-icon">📱</div>
<div class="rotate-title">Bitte Gerät drehen</div>
<div class="rotate-sub">Diese WebApp funktioniert nur im Hochformat&nbsp;/ Portrait&nbsp;Modus.</div>
</div>
<div id="fs-overlay">
<button id="fs-close" onclick="closeFS()">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
</button>
</div>
<div id="toast"></div>
<script>
async function loadM3U() {
try {
const r = await fetch("mytv.m3u");
if (!r.ok) throw new Error();
return parseM3U(await r.text());
} catch {
showToast("⚠ mytv.m3u konnte nicht geladen werden");
return [];
}
}
function parseM3U(txt) {
const lines = txt.split("\n").map(l => l.trim()).filter(Boolean);
const out = [];
for (let i = 0; i < lines.length; i++) {
if (!lines[i].startsWith("#EXTINF")) continue;
const url = lines[i + 1];
if (!url || url.startsWith("#")) continue;
const m = lines[i].match(/,(.+)$/);
const raw = m ? m[1].trim() : "Sender";
const geo = /\[geo-blocked\]/i.test(raw);
const logoAttr = lines[i].match(/tvg-logo="([^"]+)"/);
const logo = logoAttr ? logoAttr[1].trim() : null;
const shortMatch = raw.match(/\[short:([^\]]+)\]/i);
const langMatch = raw.match(/\[lang:([^\]]+)\]/i);
const qualityMatch = raw.match(/\[quality:([^\]]+)\]/i);
const short = shortMatch ? shortMatch[1].trim() : autoShort(raw);
const lang = langMatch ? langMatch[1].trim().toUpperCase() : null;
const quality = qualityMatch ? qualityMatch[1].trim().toUpperCase() : null;
const name = raw.replace(/\s*\[.*?\]/g, "").replace(/\s*\(.*?\)/g, "").trim();
out.push({ name, short, url, geo, lang, quality, logo });
i++;
}
return out;
}
function autoShort(raw) {
const clean = raw.replace(/\s*\[.*?\]/g, "").trim();
return clean.split(/[\s\-]/)[0].slice(0, 7);
}
let channels=[], curIdx=-1, muted=false, subOn=false, hls=null, oTimer=null;
const video = document.getElementById("player");
const ph = document.getElementById("placeholder");
const phName = document.getElementById("ph-name");
const overlay = document.getElementById("overlay");
const chBadge = document.getElementById("ch-badge");
const progTit = document.getElementById("prog-title");
const playIco = document.getElementById("play-icon");
const muteBtn = document.getElementById("mute-btn");
const muteIco = document.getElementById("mute-icon");
const subBtn = document.getElementById("sub-btn");
const chBar = document.getElementById("ch-bar");
function buildBar() {
chBar.innerHTML = "";
channels.forEach((ch, i) => {
const b = document.createElement("button");
b.className = "ch-pill";
b.id = "pill" + i;
const metaParts = [];
if (ch.lang) metaParts.push(`<span class="pill-tag">${ch.lang}</span>`);
if (ch.geo) metaParts.push(`<span class="pill-lock"><svg width="8" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></span>`);
if (ch.quality) metaParts.push(`<span class="pill-tag">${ch.quality}</span>`);
const metaRow = metaParts.length
? `<span class="pill-meta">${metaParts.join("")}</span>`
: "";
b.innerHTML = ch.short + metaRow;
b.onclick = () => loadCh(i);
chBar.appendChild(b);
});
}
function ensureHls(cb) {
if (window.Hls) return cb();
const s = document.createElement("script");
s.src = "https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.4.12/hls.min.js";
s.onload = cb;
document.head.appendChild(s);
}
function loadCh(idx) {
if (idx === curIdx) return;
curIdx = idx;
const ch = channels[idx];
document.querySelectorAll(".ch-pill").forEach((p,i) => p.classList.toggle("active", i===idx));
document.getElementById("pill"+idx)?.scrollIntoView({behavior:"smooth",inline:"center",block:"nearest"});
chBadge.textContent = ch.short;
progTit.textContent = ch.name;
const logoImg = document.getElementById("logo-img");
const logoPh = document.getElementById("logo-ph");
logoImg.onload = null;
logoImg.onerror = null;
logoImg.src = "";
logoImg.classList.add("hidden");
if (ch.logo) {
logoPh.style.display = "none";
logoImg.onload = () => logoImg.classList.remove("hidden");
logoImg.onerror = () => {
logoImg.classList.add("hidden");
logoPh.style.display = "flex";
};
logoImg.src = ch.logo;
} else {
logoPh.style.display = "flex";
}
phName.textContent = ch.name;
ph.classList.remove("hidden");
ensureHls(() => {
if (hls) { hls.destroy(); hls = null; }
video.src = "";
if (Hls.isSupported()) {
hls = new Hls({lowLatencyMode:true, enableWorker:true});
hls.loadSource(ch.url);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
ph.classList.add("hidden");
video.play().catch(()=>{});
});
hls.on(Hls.Events.SUBTITLE_TRACK_LOADED, () => {
for (const t of video.textTracks) t.mode = subOn ? "showing" : "hidden";
});
hls.on(Hls.Events.ERROR, (_, data) => {
if (data.fatal) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
showToast("⚠ Netzwerkfehler beim Stream");
hls.startLoad();
break;
case Hls.ErrorTypes.MEDIA_ERROR:
showToast("⚠ Media Fehler – versuche zu reparieren");
hls.recoverMediaError();
break;
default:
showToast("⚠ Stream nicht verfügbar" + (ch.geo ? " (Geo-blockiert)" : ""));
hls.destroy();
hls = null;
ph.classList.remove("hidden");
break;
}
}
});
} else if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = ch.url;
video.onloadedmetadata = () => {
ph.classList.add("hidden");
for (const t of video.textTracks) t.mode = subOn ? "showing" : "hidden";
video.play().catch(()=>{}); video.onloadedmetadata=null;
};
} else { showToast("Dein Browser unterstützt kein HLS"); }
});
}
function togglePlay() { video.paused ? video.play() : video.pause(); }
function updatePlayIcon() {
playIco.innerHTML = video.paused
? "<path d=\"M8 5v14l11-7z\" fill=\"white\"/>"
: "<path d=\"M6 4h4v16H6zM14 4h4v16h-4z\" fill=\"white\"/>";
}
video.addEventListener("play", updatePlayIcon);
video.addEventListener("pause", updatePlayIcon);
function seek(s) { video.currentTime = Math.max(0, video.currentTime+s); }
function chStep(d) { if(channels.length) loadCh((curIdx+d+channels.length)%channels.length); }
function toggleMute() {
muted = !muted; video.muted = muted;
muteBtn.classList.toggle("off", !muted);
muteIco.innerHTML = muted
? "<path d=\"M11 5L6 9H2v6h4l5 4V5z\" fill=\"#f0804a\"/><path d=\"M23 9l-6 6M17 9l6 6\" fill=\"none\" stroke=\"#f0804a\" stroke-width=\"2\" stroke-linecap=\"round\"/>"
: "<path d=\"M11 5L6 9H2v6h4l5 4V5z\" fill=\"#636366\"/><path d=\"M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07\" fill=\"none\" stroke=\"#636366\" stroke-width=\"2\" stroke-linecap=\"round\"/>";
}
function toggleSub() {
subOn = !subOn; subBtn.classList.toggle("off", !subOn);
for(const t of video.textTracks) t.mode = subOn?"showing":"hidden";
showToast(subOn?"Untertitel ein":"Untertitel aus");
}
const fsOverlay = document.getElementById("fs-overlay");
const rotateWarning = document.getElementById("rotate-warning");
const videoWrap = document.getElementById("video-wrap");
function openFS() {
if (!channels[curIdx]) return;
fsOverlay.insertBefore(video, fsOverlay.firstChild);
fsOverlay.classList.add("active");
document.body.classList.add("fs-active");
document.body.style.overflow = "hidden";
rotateWarning.style.display = "none";
document.getElementById("fs-btn").classList.remove("off");
for (const t of video.textTracks) t.mode = "hidden";
if (screen.orientation && screen.orientation.lock && window.innerWidth < 768) {
screen.orientation.lock("landscape").catch(() => {});
}
video.play().catch(()=>{});
}
function closeFS() {
videoWrap.insertBefore(video, videoWrap.firstChild);
fsOverlay.classList.remove("active");
document.body.classList.remove("fs-active");
document.body.style.overflow = "";
document.getElementById("fs-btn").classList.add("off");
for (const t of video.textTracks) t.mode = subOn ? "showing" : "hidden";
if (screen.orientation && screen.orientation.unlock && window.innerWidth < 768) {
screen.orientation.unlock();
}
updateRotateWarning();
video.play().catch(()=>{});
}
function isPhone() {
return Math.min(screen.width, screen.height) < 768;
}
function updateRotateWarning() {
const landscape = window.innerWidth > window.innerHeight;
const fsActive = fsOverlay.classList.contains("active");
rotateWarning.style.display = (isPhone() && landscape && !fsActive) ? "flex" : "none";
}
window.addEventListener("resize", () => { updateRotateWarning(); scaleApp(); });
window.addEventListener("orientationchange", () => setTimeout(() => { updateRotateWarning(); scaleApp(); }, 100));
updateRotateWarning();
function scaleApp() {
const scaler = document.getElementById("app-scaler");
if (window.innerWidth < 768) {
scaler.style.transform = "";
scaler.style.padding = "";
scaler.style.background = "";
scaler.style.borderRadius = "";
scaler.style.boxShadow = "";
return;
}
const appW = 460 + 6;
const appH = 720 + 6;
const vw = window.innerWidth;
const vh = window.innerHeight;
const scale = Math.min((vw - 40) / appW, (vh - 40) / appH, 1.4);
scaler.style.transform = `scale(${scale})`;
}
scaleApp();
const infoModal = document.getElementById("info-modal");
const infoBackdrop = document.getElementById("info-backdrop");
function openInfo() {
infoModal.style.display = "block";
infoBackdrop.style.display = "block";
requestAnimationFrame(() => requestAnimationFrame(() => {
infoModal.style.transform = "translateX(-50%) translateY(0)";
}));
}
function closeInfo() {
infoModal.style.transform = "translateX(-50%) translateY(100%)";
setTimeout(() => {
infoModal.style.display = "none";
infoBackdrop.style.display = "none";
}, 350);
}
function goFS() { openFS(); }
function tapVideo() {
overlay.classList.add("show");
clearTimeout(oTimer);
oTimer = setTimeout(()=>overlay.classList.remove("show"), 3200);
}
function showToast(msg) {
const t = document.getElementById("toast");
t.textContent = msg; t.classList.add("show");
setTimeout(()=>t.classList.remove("show"), 2800);
}
document.addEventListener("keydown", e => {
const k = e.key.toLowerCase();
if (k==="arrowright"||k==="arrowdown") chStep(1);
else if (k==="arrowleft"||k==="arrowup") chStep(-1);
else if (k===" ") { e.preventDefault(); togglePlay(); }
else if (k==="m") toggleMute();
else if (k==="u") toggleSub();
else if (k==="f") {
if (!document.fullscreenElement) openFS();
else closeFS();
}
});
video.addEventListener("loadedmetadata", () => {
for (const t of video.textTracks) t.mode = subOn ? "showing" : "hidden";
});
video.textTracks.addEventListener("addtrack", () => {
for (const t of video.textTracks) t.mode = subOn ? "showing" : "hidden";
});
(async()=>{ channels = await loadM3U(); buildBar(); if(channels.length) loadCh(0); })();
/*
* Created by anb030.de – all rights reserved!
* Copyright for the auraTiVi script belongs to A. Kleinod.
* Version: 2.265 (20260313)
* Lizenz: Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
*/
</script>
</body>
</html>
@Leibinger015
Copy link
Copy Markdown
Author

Leibinger015 commented Mar 24, 2026

My m3u file as an example…

#EXTM3U

#EXTINF:-1 tvg-id="DasErste.de@HD" tvg-logo="img/ard.webp" tvg-language="German",ARD (Das Erste) HD [short:ARD] [lang:DE] [Geo-blocked] [quality:HD]
https://daserste-live.ard-mcdn.de/daserste/live/hls/de/master.m3u8

#EXTINF:-1 tvg-id="ZDF.de@HD" tvg-logo="img/zdf.webp" tvg-language="German",ZDF HD [short:ZDF] [lang:DE] [Geo-blocked] [quality:HD]
https://zdf-hls-15.akamaized.net/hls/live/2016498/de/high/master.m3u8

#EXTINF:-1 tvg-id="rbbFernsehen.de@Berlin" tvg-logo="img/rbb_bln.webp" tvg-language="German",RBB Berlin [short:RBB] [lang:DE] [Geo-blocked] [quality:HD]
https://rbb-hls-berlin.akamaized.net/hls/live/2017824/rbb_berlin/index.m3u8

#EXTINF:-1 tvg-id="ZDFinfo.de@HD" tvg-logo="img/zdf_info.webp" tvg-language="German",ZDFinfo HD [short:ZDFinfo] [lang:DE] [Geo-blocked] [quality:HD]
https://zdf-hls-17.akamaized.net/hls/live/2016500/de/veryhigh/master.m3u8

#EXTINF:-1 tvg-id="ZDFneo.de@HD" tvg-logo="img/zdf_neo.webp" tvg-language="German",ZDFneo HD [short:ZDFneo] [lang:DE] [Geo-blocked] [quality:HD]
https://zdf-hls-16.akamaized.net/hls/live/2016499/de/veryhigh/master.m3u8

#EXTINF:-1 tvg-id="ARDone.de@HD" tvg-logo="img/ard_one.webp" tvg-language="German",ARD One HD [short:ARD one] [lang:DE] [Geo-blocked] [quality:HD]
https://mcdn-one.ard.de/ardone/hls/master.m3u8

#EXTINF:-1 tvg-id="3sat.de@HD" tvg-logo="img/3sat.webp" tvg-language="German",3sat HD [short:3sat] [lang:DE] [Geo-blocked] [quality:HD]
https://zdf-hls-18.akamaized.net/hls/live/2016501/dach/high/master.m3u8

#EXTINF:-1 tvg-id="arte.de@HD" tvg-logo="img/arte.webp" tvg-language="German",arte HD [short:arte] [lang:DE] [Geo-blocked] [quality:HD]
https://artesimulcast.akamaized.net/hls/live/2030993/artelive_de/index.m3u8

#EXTINF:-1 tvg-id="WELT.de@HD" tvg-logo="img/welt.webp" tvg-language="German",WELT HD [short:WELT] [lang:DE] [Geo-blocked] [quality:HD]
https://w-live2weltcms.akamaized.net/hls/live/2041019/Welt-LivePGM/index.m3u8

#EXTINF:-1 tvg-id="tagesschau24.de@HD" tvg-logo="img/ts24.webp" tvg-language="German",Tagesschau 24 HD [short:TS24] [lang:DE] [Geo-blocked] [quality:HD]
https://tagesschau.akamaized.net/hls/live/2020115/tagesschau/tagesschau_1/master.m3u8

#EXTINF:-1 tvg-id="Nachrichten360.de@HD" tvg-logo="img/n_360.webp" tvg-language="German",Nachrichten 360 [short:N360] [lang:DE] [Geo-blocked] [quality:HD]
https://cdn-apse1-prod.tsv2.amagi.tv/linear/amg01821-lovetvfast-nachrichten360-samsungde/playlist.m3u8

#EXTINF:-1 tvg-id="phoenix.de@HD" tvg-logo="img/phoenix.webp" tvg-language="German",Phoenix HD [short:Phoenix] [lang:DE] [Geo-blocked] [quality:HD]
https://zdf-hls-19.akamaized.net/hls/live/2016502/de/high/master.m3u8

#EXTINF:-1 tvg-id="AlJazeera.qa@English" tvg-logo="img/aljazeera.webp" tvg-language="English", AlJazeera News [short:AlJazeera] [lang:EN] [Geo-blocked] [quality:SD]
https://dash4.antik.sk/live/test_aljazeera_eng/playlist.m3u8

#EXTINF:-1 tvg-id="bbc@HD" tvg-logo="img/bbc_engl.webp" tvg-language="English",BBC News HD [short:BBC] [lang:EN] [Geo-blocked] [quality:HD]
https://vs-hls-push-ww-live.akamaized.net/x=4/i=urn:bbc:pips:service:bbc_news_channel_hd/t=3840/v=pv14/b=5070016/main.m3u8

#EXTINF:-1 tvg-id="cnn@SD" tvg-logo="img/cnn_engl.webp" tvg-language="English",CNN [short:CNN] [lang:EN] [Geo-blocked] [quality:SD]
https://turnerlive.warnermediacdn.com/hls/live/586495/cnngo/cnn_slate/VIDEO_0_3564000.m3u8

#EXTINF:-1 tvg-id="DW.de@English" tvg-logo="img/dw_engl.webp" tvg-language="English",DW English HD [short:DW] [lang:EN] [Geo-blocked] [quality:HD]
https://dwamdstream102.akamaized.net/hls/live/2015525/dwstream102/index.m3u8

#EXTINF:-1 tvg-id="euronewsgerman.fr@DE" tvg-logo="img/euronews.webp" tvg-language="German",EuroNews Deutsch [short:EuroNews] [lang:DE] [Geo-blocked] [quality:SD]
https://575b7833.wurl.com/master/f36d25e7e52f1ba8d7e56eb859c636563214f541/UmxheHhUVi1ldV9FdXJvbmV3c0RldXRzY2hfSExT/playlist.m3u8

#EXTINF:-1 tvg-id="euronewsenglish.fr@EN" tvg-logo="img/euronews.webp" tvg-language="English",EuroNews English HD [short:EuroNews] [lang:EN] [Geo-blocked] [quality:HD]
https://dash4.antik.sk/live/test_euronews/playlist.m3u8

#EXTINF:-1 tvg-id="BRFernsehen.de@Nord" tvg-logo="img/br_no.webp" tvg-language="German",BR Fernsehen Nord HD [short:BR No] [lang:DE] [Geo-blocked] [quality:HD]
https://mcdn.br.de/br/fs/bfs_sued/hls/de/master.m3u8

#EXTINF:-1 tvg-id="hrfernsehen.de@SD" tvg-logo="img/hr.webp" tvg-language="German",hr-fernsehen [short:hr] [lang:DE] [Geo-blocked] [quality:SD]
https://hrhls.akamaized.net/hls/live/2024525/hrhls/index.m3u8

#EXTINF:-1 tvg-id="MDRFernsehen.de@Sachsen" tvg-logo="img/mdr_sa.webp" tvg-language="German",MDR Sachsen HD [short:MDR Sa] [lang:DE] [Geo-blocked] [quality:HD]
https://mdrtvsnhls.akamaized.net/hls/live/2016928/mdrtvsn/index.m3u8

#EXTINF:-1 tvg-id="NDRFernsehen.de@MecklenburgVorpommern" tvg-logo="img/ndr_mv.webp" tvg-language="German",NDR MV HD [short:NDR MV] [lang:DE] [Geo-blocked] [quality:HD]
https://mcdn.ndr.de/ndr/hls/ndr_fs/ndr_mv/master.m3u8

#EXTINF:-1 tvg-id="SRFernsehen.de@HD" tvg-logo="img/sr.webp" tvg-language="German",SR Fernsehen HD [short:SR] [lang:DE] [Geo-blocked] [quality:HD]
https://srfs.akamaized.net/hls/live/689649/srfsgeo/index.m3u8

#EXTINF:-1 tvg-id="SWRFernsehenBadenWurttemberg.de@HD" tvg-logo="img/swr_bw.webp" tvg-language="German",SWR BW HD [short:SWR BW] [lang:DE] [Geo-blocked] [quality:HD]
https://swrbwd-hls.akamaized.net/hls/live/2018672/swrbwd/master.m3u8

#EXTINF:-1 tvg-id="WDRFernsehen.de@Essen" tvg-logo="img/wdr_es.webp" tvg-language="German",WDR Essen HD [short:WDR Es] [lang:DE] [Geo-blocked] [quality:HD]
https://wdrlokalzeit.akamaized.net/hls/live/2018027-b/wdrlz_essen/master.m3u8

#EXTINF:-1 tvg-id="ARDalpha.de@HD" tvg-logo="img/ard_alpha.webp" tvg-language="German",ARD alpha HD [short:ARD α] [lang:DE] [Geo-blocked] [quality:HD]
https://mcdn.br.de/br/fs/ard_alpha/hls/de/master.m3u8

#EXTINF:-1 tvg-id="KiKA.de@HD" tvg-logo="img/kika.webp" tvg-language="German",KiKA HD [short:KiKA] [lang:DE] [Geo-blocked] [quality:HD]
https://kikageohls.akamaized.net/hls/live/2022693/livetvkika_de/master.m3u8

#EXTINF:-1 tvg-id="nickelodeon.de@SD" tvg-logo="img/nick.webp" tvg-language="German",Nickelodeon [short:NICK] [lang:DE] [Geo-blocked] [quality:SD]
https://ma.anixa.tv/clips/stream/nickelodeon/playlist.php

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment