diff --git a/website/hightube/assets/hightube-icon.png b/website/hightube/assets/hightube-icon.png new file mode 100644 index 0000000..5337445 Binary files /dev/null and b/website/hightube/assets/hightube-icon.png differ diff --git a/website/hightube/index.html b/website/hightube/index.html new file mode 100644 index 0000000..e77f263 --- /dev/null +++ b/website/hightube/index.html @@ -0,0 +1,395 @@ + + + + + + + Hightube | Open Source Live Streaming Platform + + + + +
+ + + Hightube + + +
+ + +
+
+ +
+
+
+

Flutter + Go live streaming stack

+

Hightube

+

+ An open source live streaming platform designed for creators, + private communities, classrooms, labs, and self-hosted media + services. +

+ +
+
+
+
+ + + +
+
+
LIVE
+
+
+
+
+ Flutter + Client UI +
+
+ Go + Backend API +
+
+ RTMP + Streaming +
+
+ Open + Source +
+
+
+
+
+ +
+
+

Architecture

+

Built with Flutter clients and a Go streaming backend

+

+ Hightube separates a portable client experience from a compact, + self-hostable backend, keeping deployment simple while leaving room + for native desktop, mobile, and web clients. +

+
+
+
+
+ Flutter +
+

Flutter frontends

+

+ One UI technology stack targets Linux, Android, Web, and future + desktop builds with consistent interaction patterns. +

+
+
+
+ Go +
+

Go backend

+

+ The server handles API requests, authentication, live room state, + RTMP publishing, HTTP-FLV playback, chat, and monitoring. +

+
+
+
+ Gitea +
+

Self-hosted streaming

+

+ Deploy the server on your own Linux host and connect compatible + broadcasters such as OBS through standard RTMP workflows. +

+
+
+
+ +
+
+

Project highlights

+

Open, free, and cross-platform by design

+
+
+
+
+ +
+

Open source freedom

+

+ Read, modify, build, and deploy the platform from source without + vendor lock-in. +

+
+
+
+ +
+

Cross-platform clients

+

+ Current builds include Linux, Web, and Android client packages, + with Windows builds planned later. +

+
+
+
+ +
+

Practical live features

+

+ Live rooms, RTMP publishing, HTTP-FLV playback, multi-quality + transcoding, chat, danmaku-style messages, and admin monitoring. +

+
+
+
+ +
+

Small deployment surface

+

+ The Go server uses a lightweight runtime model and can be deployed + as a single Linux server component. +

+
+
+
+ +
+
+

Downloads

+

Get the current executable builds

+

+ All builds are distributed through the project release page. Apple + device builds are not provided at this time. +

+
+
+ + + +
+ Available +
+ Android +
+

Android client

+

ARM64 Android APK build for mobile viewing and interaction.

+ + Download Android APK + +
+ + +
+ Available +
+ Web +
+

Web client

+

Static web build archive for hosting the Flutter web frontend.

+ + Download Web archive + +
+
+
+ +
+
+

Source code

+

Build it, audit it, host it your way

+

+ Hightube is developed as an open source project. Clone the source, + inspect the Flutter and Go code, build your own binaries, and adapt + it for your own live platform. +

+
+ + Open repository + +
+
+ + + + + diff --git a/website/hightube/styles.css b/website/hightube/styles.css new file mode 100644 index 0000000..44af7b2 --- /dev/null +++ b/website/hightube/styles.css @@ -0,0 +1,804 @@ +:root { + color-scheme: light dark; + --primary: #0b57d0; + --on-primary: #ffffff; + --primary-container: #d7e3ff; + --on-primary-container: #001b3f; + --secondary: #565f71; + --tertiary: #705575; + --surface: #fbfcff; + --surface-rgb: 251 252 255; + --surface-container: #eef3fb; + --surface-container-high: #e5ebf5; + --outline: #727782; + --outline-rgb: 114 119 130; + --text: #191c20; + --muted: #42474f; + --success: #146c2e; + --warning: #7a5900; + --shadow: 0 24px 60px rgba(11, 87, 208, 0.16); + --topbar-bg: rgba(251, 252, 255, 0.68); + --topbar-border: rgba(114, 119, 130, 0.18); + --topbar-shadow: 0 12px 36px rgba(11, 87, 208, 0.08); + --grid-divider: rgba(114, 119, 130, 0.24); + --card-border: rgba(114, 119, 130, 0.24); + --device-border: rgba(114, 119, 130, 0.32); + --status-available-bg: rgba(20, 108, 46, 0.12); + --status-planned-bg: rgba(122, 89, 0, 0.12); +} + +/* ---- Dark theme: forced ---- */ +[data-theme="dark"] { + --primary: #a8c7ff; + --on-primary: #001b3f; + --primary-container: #003a7a; + --on-primary-container: #d7e3ff; + --secondary: #bcc7db; + --tertiary: #d7bde0; + --surface: #111318; + --surface-rgb: 17 19 24; + --surface-container: #1a1d25; + --surface-container-high: #21242d; + --outline: #8b909c; + --outline-rgb: 139 144 156; + --text: #e3e3e8; + --muted: #b0b3bd; + --success: #81c784; + --warning: #ffe08a; + --shadow: 0 24px 60px rgba(0, 0, 0, 0.4); + --topbar-bg: rgba(17, 19, 24, 0.72); + --topbar-border: rgba(139, 144, 156, 0.18); + --topbar-shadow: 0 12px 36px rgba(0, 0, 0, 0.28); + --grid-divider: rgba(139, 144, 156, 0.2); + --card-border: rgba(139, 144, 156, 0.2); + --device-border: rgba(139, 144, 156, 0.28); + --status-available-bg: rgba(129, 199, 132, 0.15); + --status-planned-bg: rgba(255, 224, 138, 0.15); +} + +/* ---- Dark theme: auto (system preference, no manual override) ---- */ +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) { + --primary: #a8c7ff; + --on-primary: #001b3f; + --primary-container: #003a7a; + --on-primary-container: #d7e3ff; + --secondary: #bcc7db; + --tertiary: #d7bde0; + --surface: #111318; + --surface-rgb: 17 19 24; + --surface-container: #1a1d25; + --surface-container-high: #21242d; + --outline: #8b909c; + --outline-rgb: 139 144 156; + --text: #e3e3e8; + --muted: #b0b3bd; + --success: #81c784; + --warning: #ffe08a; + --shadow: 0 24px 60px rgba(0, 0, 0, 0.4); + --topbar-bg: rgba(17, 19, 24, 0.72); + --topbar-border: rgba(139, 144, 156, 0.18); + --topbar-shadow: 0 12px 36px rgba(0, 0, 0, 0.28); + --grid-divider: rgba(139, 144, 156, 0.2); + --card-border: rgba(139, 144, 156, 0.2); + --device-border: rgba(139, 144, 156, 0.28); + --status-available-bg: rgba(129, 199, 132, 0.15); + --status-planned-bg: rgba(255, 224, 138, 0.15); + } +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + margin: 0; + min-width: 320px; + background: var(--surface); + color: var(--text); + font-family: + Inter, Roboto, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", + sans-serif; + line-height: 1.6; + transition: background-color 300ms ease, color 300ms ease; +} + +a { + color: inherit; +} + +.topbar { + position: sticky; + top: 0; + z-index: 10; + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + padding: 14px clamp(20px, 5vw, 72px); + background: var(--topbar-bg); + border-bottom: 1px solid var(--topbar-border); + box-shadow: var(--topbar-shadow); + -webkit-backdrop-filter: blur(22px) saturate(160%); + backdrop-filter: blur(22px) saturate(160%); +} + +.brand { + display: inline-flex; + align-items: center; + gap: 10px; + color: var(--text); + font-weight: 800; + text-decoration: none; +} + +.brand img { + width: 36px; + height: 36px; + border-radius: 10px; +} + +.nav { + display: flex; + align-items: center; + gap: 6px; +} + +.nav a { + min-height: 40px; + padding: 8px 14px; + border-radius: 20px; + color: var(--muted); + font-size: 0.94rem; + font-weight: 650; + text-decoration: none; +} + +.nav a:hover { + background: var(--surface-container); + color: var(--primary); +} + +/* 立即尝试 CTA button in nav */ +.nav-cta { + background: var(--primary) !important; + color: var(--on-primary) !important; + margin-left: 8px; + font-weight: 800 !important; + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2); + transition: transform 160ms ease, box-shadow 160ms ease, background 160ms ease; +} + +.nav-cta:hover { + filter: brightness(0.88); + transform: translateY(-1px); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.26); +} + +/* Hamburger menu button — hidden on desktop */ +.hamburger { + display: none; + flex-direction: column; + justify-content: center; + gap: 5px; + width: 40px; + height: 40px; + padding: 8px; + border: none; + border-radius: 10px; + background: transparent; + cursor: pointer; + z-index: 20; +} + +.hamburger span { + display: block; + width: 100%; + height: 2.5px; + border-radius: 2px; + background: var(--text); + transition: transform 200ms ease, opacity 200ms ease; +} + +.hamburger[aria-expanded="true"] span:nth-child(1) { + transform: translateY(7.5px) rotate(45deg); +} + +.hamburger[aria-expanded="true"] span:nth-child(2) { + opacity: 0; +} + +.hamburger[aria-expanded="true"] span:nth-child(3) { + transform: translateY(-7.5px) rotate(-45deg); +} + +/* Right-side controls group (theme + hamburger) */ +.topbar-actions { + display: flex; + align-items: center; + gap: 4px; + flex-shrink: 0; +} + +/* Theme toggle button */ +.theme-toggle { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + padding: 0; + border: none; + border-radius: 50%; + background: transparent; + color: var(--text); + font-size: 1.25rem; + cursor: pointer; + transition: background 200ms ease, transform 200ms ease; + flex-shrink: 0; +} + +.theme-toggle:hover { + background: var(--surface-container); + transform: scale(1.08); +} + +.theme-toggle:active { + transform: scale(0.94); +} + +.theme-toggle svg { + width: 22px; + height: 22px; + fill: none; + stroke: currentColor; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} + +/* hide all icons by default, show based on data-state */ +.theme-toggle .icon-sun, +.theme-toggle .icon-moon, +.theme-toggle .icon-auto { + display: none; +} + +.theme-toggle[data-state="light"] .icon-sun { + display: block; +} + +.theme-toggle[data-state="dark"] .icon-moon { + display: block; +} + +.theme-toggle[data-state="auto"] .icon-auto { + display: block; +} + +.hero { + display: grid; + grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr); + gap: clamp(28px, 6vw, 84px); + align-items: center; + min-height: calc(100vh - 68px); + padding: clamp(48px, 7vw, 96px) clamp(20px, 5vw, 72px); +} + +.hero-copy { + max-width: 680px; +} + +.eyebrow { + margin: 0 0 12px; + color: var(--primary); + font-size: 0.85rem; + font-weight: 800; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +h1, +h2, +h3, +p { + overflow-wrap: anywhere; +} + +h1 { + margin: 0; + color: var(--text); + font-size: clamp(3.5rem, 11vw, 8rem); + line-height: 0.9; + letter-spacing: 0; +} + +h2 { + margin: 0; + font-size: clamp(2rem, 4vw, 3.5rem); + line-height: 1.05; + letter-spacing: 0; +} + +h3 { + margin: 0; + font-size: 1.2rem; + line-height: 1.2; + letter-spacing: 0; +} + +.lead { + max-width: 620px; + margin: 28px 0 0; + color: var(--muted); + font-size: clamp(1.1rem, 2vw, 1.35rem); +} + +.actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-top: 34px; +} + +.button, +.download-link { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 48px; + padding: 12px 22px; + border-radius: 24px; + font-weight: 800; + text-decoration: none; + transition: + transform 160ms ease, + box-shadow 160ms ease, + background 160ms ease; +} + +.button:hover, +.download-link:hover { + transform: translateY(-1px); +} + +.primary { + background: var(--primary); + color: var(--on-primary); + box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18); +} + +.secondary { + background: var(--primary-container); + color: var(--on-primary-container); +} + +.hero-panel { + display: flex; + justify-content: center; +} + +.device-window { + width: min(100%, 560px); + overflow: hidden; + border: 1px solid var(--device-border); + border-radius: 28px; + background: var(--surface-container); + box-shadow: var(--shadow); +} + +.window-bar { + display: flex; + gap: 8px; + padding: 16px 18px; + border-bottom: 1px solid var(--card-border); +} + +.window-bar span { + width: 12px; + height: 12px; + border-radius: 50%; + background: var(--outline); +} + +.window-bar span:first-child { + background: #ba1a1a; +} + +.window-bar span:nth-child(2) { + background: #a46700; +} + +.window-bar span:nth-child(3) { + background: #146c2e; +} + +.stream-preview { + position: relative; + display: grid; + min-height: 280px; + place-items: center; + background: + linear-gradient(135deg, rgba(11, 87, 208, 0.94), rgba(112, 85, 117, 0.9)), + radial-gradient(circle at 30% 30%, #d7e3ff, transparent 32%); +} + +.live-badge { + position: absolute; + top: 18px; + left: 18px; + padding: 6px 12px; + border-radius: 16px; + background: #ba1a1a; + color: #ffffff; + font-size: 0.8rem; + font-weight: 900; +} + +.play-symbol { + width: 86px; + height: 86px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.88); + clip-path: polygon(28% 18%, 28% 82%, 82% 50%); +} + +.stats-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1px; + background: var(--grid-divider); +} + +.stats-grid div { + min-width: 0; + padding: 18px 14px; + background: var(--surface); +} + +.stats-grid strong, +.stats-grid span { + display: block; +} + +.stats-grid strong { + color: var(--primary); + font-size: 1.02rem; +} + +.stats-grid span { + color: var(--muted); + font-size: 0.88rem; +} + +.section { + padding: clamp(64px, 8vw, 112px) clamp(20px, 5vw, 72px); +} + +.section-heading { + max-width: 820px; + margin-bottom: 32px; +} + +.section-heading p:not(.eyebrow) { + max-width: 760px; + color: var(--muted); + font-size: 1.06rem; +} + +.architecture-grid, +.download-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 18px; +} + +.architecture-card, +.download-card { + min-width: 0; + padding: 24px; + border: 1px solid var(--card-border); + border-radius: 24px; + background: var(--surface-container); +} + +.architecture-card .icon { + display: grid; + width: 48px; + height: 48px; + margin-bottom: 20px; + place-items: center; + border-radius: 16px; + background: var(--primary); + color: var(--on-primary); +} + +.architecture-card .icon svg { + width: 26px; + height: 26px; +} + +.architecture-card p, +.download-card p, +.feature-item p, +.source-section p { + color: var(--muted); +} + +.feature-band { + background: var(--surface-container); +} + +.feature-list { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1px; + overflow: hidden; + border: 1px solid var(--card-border); + border-radius: 28px; + background: var(--grid-divider); +} + +.feature-item { + min-width: 0; + padding: 28px; + background: var(--surface); +} + +.feature-icon { + width: 36px; + height: 36px; + margin-bottom: 14px; + color: var(--primary); +} + +.feature-icon svg { + width: 100%; + height: 100%; + display: block; +} + +.download-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.download-card { + display: flex; + min-height: 240px; + flex-direction: column; + align-items: flex-start; +} + +.download-icon { + width: 32px; + height: 32px; + margin-bottom: 14px; + color: var(--muted); +} + +.download-icon svg { + width: 100%; + height: 100%; + display: block; +} + +.status { + margin-bottom: 18px; + padding: 5px 10px; + border-radius: 14px; + background: var(--status-available-bg); + color: var(--success); + font-size: 0.78rem; + font-weight: 850; +} + +.status.muted { + background: var(--status-planned-bg); + color: var(--warning); +} + +.download-link { + margin-top: auto; + background: var(--primary); + color: var(--on-primary); +} + +.planned { + background: var(--surface-container-high); +} + +.source-section { + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + background: #001b3f; + color: #ffffff; +} + +.source-section .eyebrow, +.source-section p { + color: #d7e3ff; +} + +.source-section div { + max-width: 820px; +} + +.footer { + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + gap: 16px; + padding: 28px clamp(20px, 5vw, 72px); + background: #001533; + color: #d7e3ff; + font-size: 0.92rem; +} + +.footer span:nth-child(2) { + text-align: center; +} + +.footer span:last-child { + text-align: right; +} + +@media (max-width: 900px) { + .topbar { + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + } + + .hamburger { + display: flex; + } + + .nav { + display: none; + width: 100%; + flex-direction: column; + gap: 2px; + padding: 8px 0 4px; + border-top: 1px solid var(--topbar-border); + margin-top: 10px; + } + + .nav.open { + display: flex; + } + + .nav a { + width: 100%; + padding: 12px 16px; + border-radius: 14px; + font-size: 1rem; + } + + .nav-cta { + margin-left: 0 !important; + margin-top: 6px; + text-align: center; + } + + .hero { + grid-template-columns: 1fr; + min-height: auto; + } + + .architecture-grid, + .download-grid { + grid-template-columns: 1fr 1fr; + } + + .stats-grid { + grid-template-columns: repeat(2, 1fr); + } + + .source-section { + align-items: flex-start; + flex-direction: column; + } +} + +@media (max-width: 640px) { + .topbar { + padding: 10px 16px; + } + + .hero, + .section { + padding-right: 16px; + padding-left: 16px; + } + + .hero { + padding-top: 32px; + padding-bottom: 32px; + gap: 24px; + } + + h1 { + font-size: clamp(2.8rem, 10vw, 4rem); + } + + h2 { + font-size: clamp(1.6rem, 5vw, 2.4rem); + } + + .lead { + font-size: 1rem; + margin-top: 16px; + } + + .hero-panel { + width: 100%; + } + + .device-window { + width: 100%; + border-radius: 20px; + } + + .stream-preview { + min-height: 180px; + } + + .play-symbol { + width: 60px; + height: 60px; + } + + .architecture-grid, + .download-grid, + .feature-list { + grid-template-columns: 1fr; + } + + .architecture-card, + .download-card { + padding: 20px; + border-radius: 18px; + } + + .feature-item { + padding: 20px; + } + + .actions { + flex-direction: column; + } + + .button, + .download-link { + width: 100%; + justify-content: center; + } + + .nav a { + min-height: 48px; + padding: 14px 16px; + font-size: 1.05rem; + } + + .nav-cta { + min-height: 50px; + font-size: 1.05rem; + } + + .footer { + grid-template-columns: 1fr; + gap: 8px; + padding: 24px 16px; + } + + .footer-hide-mobile { + display: none; + } +}