Files
threadnet-call/docs/axion1337-fork.md
T
Thore Cimbal d13cce7337 docs: describe the automated publish, not the manual process it replaced
Section 4 still described a manual/local npm publish with an untracked .npmrc - obsolete since publish_npm landed in .gitlab-ci.yml on 2026-08-06. Documents the actual job: manual trigger, GITEA_NPM_TOKEN, the empty-package guard, and the threadnet dist-tag.
2026-08-09 12:00:00 +00:00

7.7 KiB

threadnet-call: Fork-Anpassungen für axion1337.chat

Dieses Dokument beschreibt alles, was dieser Fork gegenüber Upstream Element Call ändert. Die übrigen Dateien in docs/ sind unverändertes Upstream-Material.

1. Warum Fork von emmick4/element-call (Branch livekit)?

Nicht direkt von element-hq/element-call geforkt, sondern von emmick4/element-calls livekit-Branch, weil dieser bereits den noch nicht upstream gemergten PR element-hq/element-call#3736 enthält - config-driven media_quality. Ohne diesen PR wäre eigener Custom-Code nötig gewesen, um Video-/Audio-Qualitätslimits pro Deployment konfigurierbar zu machen.

2. media_quality-Defaults

Konfiguriert in vite-embedded.config.ts (im generateFile-Plugin-Aufruf, der media_quality in die zur Build-Zeit gebackene config.json des Embedded-Packages schreibt):

  • Kamera: 1440p / 60fps / ~8 Mbps (video.max_resolution/max_framerate/max_bitrate)
  • Screen-Share: 1440p / 30fps / ~6 Mbps
  • 720p-Zwischen-Simulcast-Layer (video.simulcast_layers) - ohne diesen fiel die Übertragung bei kleinsten Netzwerkschwankungen direkt von 1440p auf blockiges 360p
  • video_codec: "h264" (siehe Incident unten für die Begründung)

Das sind Startwerte, keine harten Limits - Nutzer können in den Call-Settings weiter hochdrehen.

3. VP9-Incident (2026-07-28) — ⚠️ nicht ohne Browser-Repro erneut versuchen

Erster Versuch setzte video_codec: "vp9" (Commit 83db5224). Das hat Calls live komplett kaputt gemacht (kein Bild/Ton), obwohl die LiveKit-SFU-Server-Logs den Codec-Regression-Fallback auf VP8 als scheinbar erfolgreich zeigten. Sofort zurückgerollt (Commit f845d81e). Vermutete Ursache: LiveKit nutzt für VP9/AV1 SVC statt klassischem Simulcast, aber buildPublishOptions() in diesem Fork setzt immer Simulcast-Layer - ein echter Code-Fix wäre nötig, um das aufzulösen. Root Cause nie abschließend isoliert (hätte einen Browser-Konsolen-/WebRTC-Internals-Repro gebraucht). Danach auf 720p-Zwischen-Layer + h264 (klassisches Simulcast, kein SVC-Risiko, oft hardwarebeschleunigt v.a. auf iOS) umgestellt - live verifiziert (7/8 Tracks nativ H.264, 1 sauberer VP8-Fallback).

Nicht erneut versuchen, ohne vorher einen echten Browser-Repro zu haben.

4. npm-Publish zu Gitea (@sorb/threadnet-call-embedded)

⚠️ Dieser Abschnitt beschrieb bis 2026-08-09 einen manuellen/lokalen Vorgang, der seit dem 2026-08-06 nicht mehr zutrifft — korrigiert bei einer Doku-Durchsicht.

Das Embedded-Package (embedded/web/package.json, aktuell 0.19.2-threadnet.7) wird zu Gitea's npm-Registry veröffentlicht (https://rohana.axion1337.de/api/packages/sorb/npm/, Scope @sorb). Der obere Versionierungs-Track hier (0.19.2-threadnet.N) ist unabhängig von den Docker-Image-Tags, unter denen das fertig gebaute Widget im gitops-Repo deployt wird (z.B. v0.2.3-elementcall-h264 als threadnet-web-Image-Tag) - zwei getrennte Versionsschemata für zwei verschiedene Artefakte (npm-Package vs. Docker-Image).

Der Publish läuft über den publish_npm-Job in .gitlab-ci.yml, nicht mehr manuell: needs: build_embedded, ausgelöst per Tag oder auf main (when: manual, bewusst kein Automatismus - Veröffentlichen bleibt ein Akt). Bricht ab, wenn embedded/web/dist zu wenige Dateien enthält (Schutz gegen die leeren Pakete aus threadnet-call#4), und veröffentlicht mit --tag threadnet statt latest, weil unsere Versionen als npm-Prereleases gelten. Auth über die CI-Variable GITEA_NPM_TOKEN (Gitea-Token, Scope write:package) - die frühere lokale, untrackte .npmrc mit Klartext-Token ist damit hinfällig.

Das committete .github/workflows/publish-embedded-packages.yaml ist unbenutztes Upstream-Material (zielt weiterhin auf registry.npmjs.org/@element-hq) - Gitea Actions läuft hier nicht, siehe Repo-Topologie unten.

5. Bewusst keine Server-seitige ML-Rauschunterdrückung

Nur der client-seitige WebRTC-Standardtoggle (Echo/Noise/Gain-Suppression, aus derselben Upstream-PR-Linie) wurde übernommen. Bewusst kein LiveKit-Agents-basiertes Server-seitiges ML-Noise-Cancellation (z.B. selbst gehostetes DTLN/RNNoise) - LiveKits eigene Dokumentation beschreibt diesen Baustein als für AI-Voice-Agents gedacht, nicht für Mensch-zu-Mensch-Calls (kein unterstützter Weg, bereinigtes Audio an andere Teilnehmer weiterzuleiten).

6. Produktname im Widget (.env.production)

VITE_PRODUCT_NAME=aXion1337.Chat in .env.production — eine Zeile, keine Quelldatei angefasst. Upstream liest den Namen an jeder Stelle als import.meta.env.VITE_PRODUCT_NAME || "Element Call"; die Variable zu setzen ist deshalb die vollständige Umbenennung ohne Merge-Reibung.

Der Name folgt der Regel aus management/shared/branding.md: „in der Anwendung" heißt es aXion1337.Chat — und das Call-Widget läuft in der Anwendung.

Was dadurch tatsächlich umbenannt wird (Inventur 2026-08-06, embedded-Modus):

Stelle sichtbar wo
error.matrix_rtc_transport_missing Fehlermeldung „Der Server ist nicht für … konfiguriert"
error.open_elsewhere_description „… wurde in einem anderen Tab geöffnet"
DeveloperSettingsTab Versionszeile Einstellungen → Entwicklermodus
usePageTitledocument.title im iframe unsichtbar, der Vollständigkeit halber

Was im Embedded-Build ohnehin nie erscheint — und deshalb nicht angefasst wurde:

  • Die Logo-SVGs. Alle vier sind importiert und liegen im Bundle — gerendert wird im Widget aber keins, und zwar jeweils durch dieselbe Bedingung gesperrt:

    SVG gerendert von Sperre
    Logo Header.tsx (HeaderLogo) FullScreenView zeigt den Header nur bei header === "standard"
    LogoMark, LogoType CallFooter.tsx showLogo = headerStyle === HeaderStyle.Standard
    LogoLarge LoginPage, RegisterPage gibt es nur standalone

    HeaderStyle.Standard ist der Default für Nicht-Widget-Nutzung; als Widget ist der Header None (Desktop) oder AppBar (Web/Mobile) — siehe UrlParams.ts. Das gilt auch für Fehlerseiten: FullScreenView prüft dieselbe Bedingung, ein Absturz im Widget zeigt also kein Logo.

    ⚠️ Nicht danach greppen, ob ein Logo „irgendwo vorkommt" — im gebauten Bundle steht <desc>Element Call (Beta)</desc> aus Logo.svg drin, obwohl es nie gezeichnet wird. Maßgeblich ist die Render-Bedingung, nicht der Treffer.

  • header_label („Element Call-Startseite") und login_subheading. Startseite und Login gibt es nur im Standalone-Modus.

  • Die drei deutschen developer_mode.matrixRTCMode.*.description. Die reden über Gegenstellen („alle beteiligten Element Call Clients v0.17.0 oder neuer") — das ist eine Kompatibilitätsaussage über fremde Clients, keine Selbstbezeichnung. Sie umzubenennen wäre inhaltlich falsch.

⚠️ build:embedded:development läuft mit --mode development und lädt .env.production nicht — ein Dev-Build zeigt weiter „Element Call". Beabsichtigt; ausgeliefert wird der Produktions-Build.

Verifiziert am CI-Artefakt von Pipeline 189 (ac688d3), nicht am Quelltext: das gebaute Bundle enthält „aXion1337.Chat"; die verbliebenen „Element Call"-Treffer sind Source-Maps, die 22 Sprachdateien (header_label, standalone) und die <desc>-Zeile aus Logo.svg — keine davon im Widget sichtbar.

Repo-Topologie (seit 2026-07-31)

Kanonisch ist git.lab/axion1337.chat/threadnet-call (Homelab-GitLab) — die Kopie auf rohana.axion1337.de/sorb/threadnet-call ist ein automatischer Push-Mirror (Lesekopie, Issues, npm-Registry). Niemals direkt nach rohana pushen — der Mirror überschreibt divergente Stände.