Update-Quelle ist jetzt der eigene Gitea-Server, Release-Pipeline unter .gitea/workflows, Veroeffentlichen per packaging/publish_release.ps1.
294 lines
16 KiB
Markdown
294 lines
16 KiB
Markdown
# Playtube
|
||
|
||
Eigenständige Desktop-App für YouTube & YouTube Music (kein Browser-Fenster, keine
|
||
Erweiterung) mit:
|
||
|
||
- **Zwei Tabs** – YouTube und YouTube Music laufen parallel, Musik spielt im
|
||
Hintergrund weiter wenn du zu Videos wechselst.
|
||
- **Login/Premium** – eigenes, persistentes Profil (`%APPDATA%\Playtube`), einmal bei
|
||
Google anmelden reicht für beide Dienste.
|
||
- **Discord Rich Presence** – zeigt Titel, Kanal/Interpret, Fortschrittsbalken und
|
||
einen Link-Button in deinem Discord-Profil, sobald etwas läuft. Ist der
|
||
**Einstellungen-Tab** offen, steht dort stattdessen „In den Einstellungen“ und welches
|
||
Feld du gerade bearbeitest (z.B. „Discord Rich Presence › Client-ID“) - nur der
|
||
Feldname, nie der Inhalt. Das folgt der Option „Status anzeigen, wenn gerade nichts
|
||
läuft“ (aus = auch kein Einstellungs-Status). Discord übernimmt Änderungen höchstens
|
||
alle 15 Sekunden, die Anzeige hinkt dem Klicken also etwas hinterher.
|
||
- **Audioausgabe pro Tab** – YouTube und YouTube Musik lassen sich in den Einstellungen
|
||
auf verschiedene Ausgabegeräte legen (z.B. getrennte Sonar-Kanäle), siehe unten.
|
||
- **System-Tray** – Fenster schliessen minimiert nur (Musik läuft weiter), Rechtsklick
|
||
aufs Tray-Icon zum Beenden, Play/Pause/Skip direkt aus dem Menü.
|
||
- **Eigener Name** – erscheint als "Playtube" im Taskmanager, Fenstertitel, Alt-Tab
|
||
und (nach dem Packaging, siehe unten) im Lautstärkemixer statt als "python".
|
||
|
||
## Installation (Windows)
|
||
|
||
Lade auf der [Releases-Seite](https://git.fojadrachi.de/Fojadrachi/Playtube/releases)
|
||
`Playtube-Setup-vX.Y.Z.exe` herunter und starte sie. Der Installer
|
||
|
||
- installiert Playtube **pro Benutzer** nach `%LOCALAPPDATA%\Programs\Playtube` (keine
|
||
Admin-Rechte nötig) und legt Startmenü-Eintrag (optional Desktop-Verknüpfung) an,
|
||
- ersetzt bei jeder späteren Ausführung die vorhandene Installation **an Ort und
|
||
Stelle** (feste Installer-ID) - es gibt also immer genau EINE installierte Version, nie
|
||
mehrere nebeneinander,
|
||
- beendet dafür ein noch laufendes Playtube selbst und räumt den alten Programmordner
|
||
auf, damit keine Reste alter Versionen übrig bleiben,
|
||
- lässt Login und Einstellungen (`%APPDATA%\Playtube`) unangetastet; beim Deinstallieren
|
||
über "Apps & Features" wird gefragt, ob sie mitgelöscht werden sollen.
|
||
|
||
Ab dann aktualisiert sich Playtube selbst (siehe "Automatische Updates") - die
|
||
Setup-Datei wird dafür nicht erneut von Hand gebraucht. Das ZIP-Paket
|
||
(`Playtube-vX.Y.Z-win64.zip`) bleibt als portable Variante ohne Installation erhalten;
|
||
Playtube bietet einer portablen Kopie beim nächsten Update automatisch an, in die
|
||
reguläre Installation zu wechseln (danach kann der alte Ordner gelöscht werden).
|
||
|
||
## Schnellstart (Entwicklung)
|
||
|
||
```powershell
|
||
python -m venv .venv
|
||
.venv\Scripts\pip install -r requirements.txt
|
||
.venv\Scripts\python main.py
|
||
```
|
||
|
||
Beim ersten Start meldest du dich einmal in einem der beiden Tabs mit deinem
|
||
Google-Konto an (Symbol oben rechts auf youtube.com bzw. music.youtube.com) - der
|
||
Login bleibt danach dauerhaft gespeichert.
|
||
|
||
## Discord Rich Presence einrichten
|
||
|
||
Die Client-ID ist bereits in `config.json` eingetragen (`discord.client_id`). Falls du
|
||
sie ändern oder eine eigene Anwendung nutzen willst:
|
||
|
||
1. Auf https://discord.com/developers/applications eine neue Application anlegen.
|
||
2. Die **Application ID** in `config.json` unter `discord.client_id` eintragen.
|
||
3. Optional, für eigene Icons: unter *Rich Presence → Art Assets* zwei Bilder mit den
|
||
exakten Schlüsseln `youtube_logo` und `music_logo` hochladen (Playtube nutzt genau
|
||
diese Keys automatisch). Ohne hochgeladene Assets funktioniert die Presence trotzdem,
|
||
nur ohne Bild.
|
||
4. Discord muss auf demselben Rechner laufen, damit die Presence angezeigt wird.
|
||
|
||
In `config.json` lassen sich zudem `update_interval_seconds` (Mindestabstand zwischen
|
||
Updates) und `show_idle_presence` (Status anzeigen, wenn gerade nichts läuft) anpassen.
|
||
|
||
## Audioausgabe pro Tab (YouTube / YouTube Musik)
|
||
|
||
Im **Einstellungen-Tab** legst du unter „Audioausgabe“ getrennt fest, über welches
|
||
Ausgabegerät der Ton von **YouTube** und von **YouTube Musik** läuft (Standard:
|
||
Systemstandard). So kannst du z.B. YouTube auf „Sonar - Media“ und YouTube Musik auf
|
||
„Sonar - Aux“ legen und beide getrennt regeln. Nach „Speichern“ gilt die Auswahl sofort,
|
||
auch für bereits geöffnete Seiten (kein Neuladen nötig).
|
||
|
||
Wichtig zu wissen:
|
||
|
||
- **Windows zeigt weiterhin einen Eintrag „Playtube“.** Chromium (QtWebEngine) spielt den
|
||
Ton beider Tabs über *einen* gemeinsamen Audio-Prozess ab, deshalb kann Windows (auch
|
||
„App-Lautstärke und Geräteeinstellungen“) die Tabs nicht einzeln benennen oder routen.
|
||
Getrennt wird stattdessen über das **Gerät** - in Sonar & Co. also über den gewählten
|
||
Kanal/das gewählte Gerät.
|
||
- **Freigabe der Gerätenamen:** Chromium blendet Gerätenamen aus, solange die Seite keine
|
||
Mikrofon-Berechtigung hat. Damit die Seite das gewählte Gerät findet, erteilt Playtube
|
||
YouTube/YouTube Musik diese Freigabe - nur, solange mindestens ein Tab ein eigenes Gerät
|
||
nutzt, nur für diese beiden Seiten und nur für die laufende Sitzung (sie wird nicht
|
||
gespeichert und bei jedem Start neu erteilt). Es wird nichts aufgenommen.
|
||
- Ist das gewählte Gerät gerade nicht angeschlossen, bleibt die Auswahl (als „nicht
|
||
verfügbar“) gespeichert und der Ton läuft solange über den Systemstandard.
|
||
- Technik: [playtube/audio_routing.py](playtube/audio_routing.py) legt per
|
||
`HTMLMediaElement.setSinkId` die Medienelemente der Seite auf das Gerät (Suche über den
|
||
Gerätenamen). In der Konfiguration stehen die Namen unter `audio.youtube_output` und
|
||
`audio.music_output` (leer = Systemstandard).
|
||
|
||
## Fernsteuerung (Stream Dock)
|
||
|
||
Playtube lässt sich lokal fernsteuern, z.B. über das Stream-Dock-Plugin
|
||
`com.fojadrachi.playtube.sdPlugin` (Ajazz/Mirabox AKP153E & Co.). Dafür lauscht Playtube
|
||
auf einer Named Pipe (`\\.\pipe\Playtube.Remote.Playtube`, im Entwicklungsmodus
|
||
`...PlaytubeDev`). Es gibt keinen Netzwerk-Port, verbinden darf nur der angemeldete
|
||
Benutzer.
|
||
|
||
- Protokoll: eine JSON-Nachricht pro Zeile, z.B. `{"id":1,"cmd":"play_pause","target":"auto"}`,
|
||
Antwort `{"id":1,"ok":true}`. Details in [playtube/remote_control.py](playtube/remote_control.py).
|
||
- Befehle: `status`, `show`, `switch_tab`, `play_pause`, `play`, `pause`, `next`,
|
||
`previous`, `seek`, `volume_change`, `set_volume`, `mute_toggle`, `like`, `dislike`,
|
||
`shuffle`, `repeat`, `list_playlists`, `play_playlist`. Es gibt eine feste Whitelist;
|
||
beliebiges JavaScript oder URLs lassen sich nicht senden.
|
||
- `target: "auto"` steuert den Tab, der gerade abspielt, sonst den sichtbaren.
|
||
- Abschalten: in `config.json` `"remote_control": {"enabled": false}`.
|
||
- Tests: `.venv\Scripts\python -m unittest discover -s tests -v`
|
||
|
||
## App als eigenständige Playtube.exe packen
|
||
|
||
Für die volle Taskmanager-/Audiomixer-Markierung wird die App als eigene .exe gebaut
|
||
(ein via `python main.py` gestarteter Prozess heisst in Windows immer "python.exe" -
|
||
nur eine kompilierte .exe mit eigenem Namen und eigener Versionsinfo kann das ändern):
|
||
|
||
```powershell
|
||
.venv\Scripts\pip install pyinstaller
|
||
powershell -ExecutionPolicy Bypass -File packaging\build.ps1
|
||
```
|
||
|
||
Ergebnis liegt danach unter `dist\Playtube\Playtube.exe`. Ist
|
||
[Inno Setup 6](https://jrsoftware.org/isinfo.php) installiert
|
||
(`winget install --id JRSoftware.InnoSetup -e`), baut das Skript daraus ausserdem den
|
||
Installer `dist\installer\Playtube-Setup-vX.Y.Z.exe` (Skript:
|
||
[packaging/playtube.iss](packaging/playtube.iss); mit `-SkipInstaller` überspringbar).
|
||
Eine portable, nicht per Setup installierte `.exe` legt beim ersten Start automatisch eine
|
||
Verknüpfung im Windows-Startmenü an - eine per Setup installierte Kopie hat den
|
||
Eintrag bereits vom Installer.
|
||
|
||
Das Build-Skript benennt
|
||
zusätzlich den QtWebEngine-Hilfsprozess (der den eigentlichen Ton ausgibt) zu
|
||
`PlaytubeHelper.exe` um, damit er im Taskmanager nicht als `QtWebEngineProcess`
|
||
auftaucht. Für eine vollständige Umbenennung inkl. Icon/Versionsinfo dieses
|
||
Hilfsprozesses (relevant für den Lautstärkemixer) zusätzlich
|
||
[rcedit](https://github.com/electron/rcedit/releases) als `packaging\rcedit.exe`
|
||
ablegen - das Skript nutzt es automatisch, wenn vorhanden. Ohne rcedit funktioniert
|
||
alles genauso, nur zeigt der Lautstärkemixer für den Ton-Unterprozess je nach
|
||
Windows-Version eventuell weiterhin "QtWebEngineProcess" statt "Playtube" (rein
|
||
kosmetisch - Namensgebung von Chromium-Hilfsprozessen ist ein bekanntes,
|
||
Windows-versionsabhängiges Verhalten, das selbst grosse Electron-Apps nur mit rcedit
|
||
o.ä. umgehen).
|
||
|
||
## Automatische Updates
|
||
|
||
Playtube prüft beim Start und danach alle `updates.check_interval_hours` Stunden
|
||
(Standard 6, im **Einstellungen-Tab** oder in `config.json` einstellbar) die
|
||
[Releases](https://git.fojadrachi.de/Fojadrachi/Playtube/releases) auf dem eigenen Gitea-Server. Im
|
||
Einstellungen-Tab gibt es zusätzlich einen "Jetzt nach Updates suchen"-Button mit
|
||
Status-Anzeige und Fortschrittsbalken für den Download. Gibt es eine neuere Version,
|
||
fragt ein Dialog, ob sie installiert werden soll:
|
||
|
||
- **Windows, per Setup installiert** (siehe "Installation"): lädt bevorzugt das kleine
|
||
**Patch-Paket** herunter (nur die `Playtube.exe` mit unserem Anwendungscode, ca. 2-3 MB)
|
||
und überschreibt damit die Datei im Installationsordner - der riesige PySide6/
|
||
QtWebEngine-Laufzeitordner (`_internal/`) bleibt unangetastet, da er sich zwischen
|
||
normalen Patch-Releases nicht ändert. Die PySide6-Version steht im Dateinamen des
|
||
Patches (`...-pyside6.11.2-patch.play`); weicht sie von der installierten Laufzeit ab,
|
||
ist ein reines .exe-Patch nicht mehr passend und Playtube nimmt stattdessen den
|
||
**Setup-Installer**, der alles (auch die Laufzeit) an Ort und Stelle erneuert und
|
||
Playtube danach wieder startet. Der Versionseintrag in "Apps & Features" wird nach
|
||
einem Patch ebenfalls nachgezogen.
|
||
- **Windows, portable Kopie** (aus dem ZIP entpackt, z.B. in Downloads): lädt den
|
||
**Setup-Installer** und führt ihn still aus. Playtube liegt danach in der regulären
|
||
Installation - Startmenü-Eintrag und Dateizuordnung zeigen dorthin, die alte portable
|
||
Kopie ist nicht mehr nötig (und kann gelöscht werden). So entstehen nicht länger
|
||
versionierte Ordner nebeneinander. Gibt es (bei älteren Releases) keinen Installer,
|
||
wird wie früher das volle ZIP über den vorhandenen Ordner kopiert.
|
||
- **Linux** (`Playtube`-Binary): Patch-Paket (nur das Binary) bzw. volles `.tar.gz`.
|
||
Die App startet sich in allen Fällen danach selbst neu.
|
||
- **Entwicklungsmodus** (`python main.py`): führt `git pull` + `pip install -r
|
||
requirements.txt` aus und startet den Python-Prozess neu.
|
||
|
||
Auto-Update lässt sich im Einstellungen-Tab oder in `config.json` unter
|
||
`updates.enabled` deaktivieren.
|
||
|
||
Nach einem erkannten Update wird beim nächsten Start automatisch der QtWebEngine-
|
||
HTTP-Cache geleert (`webprofile/cache`) - alte Cache-Einträge können sonst nicht mehr
|
||
zum neuen Code passen (frühere Ursache für fehlende Icons). Der Login bleibt davon
|
||
unberührt, da Cookies/LocalStorage in einem komplett getrennten Ordner
|
||
(`webprofile/storage`) liegen.
|
||
|
||
### Patch-Dateien manuell installieren (`.play`)
|
||
|
||
Windows-Patch-Pakete tragen die eigene Dateiendung `.play` statt `.zip` (technisch
|
||
weiterhin ein ganz normales ZIP-Archiv). Playtube registriert `.play` beim ersten Start
|
||
automatisch als Windows-Dateizuordnung - eine manuell heruntergeladene
|
||
`Playtube-vX.Y.Z-win64-patch.play` (z.B. von der
|
||
[Releases-Seite](https://git.fojadrachi.de/Fojadrachi/Playtube/releases)) lässt sich also
|
||
einfach per Doppelklick installieren, ohne dass Playtube selbst etwas herunterladen
|
||
muss.
|
||
|
||
### Eine neue Version veröffentlichen
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File packaging\release.ps1 -Version 1.1.0
|
||
```
|
||
|
||
Das Skript setzt die Versionsnummer, committet, erstellt Git-Tag `v1.1.0` und pusht zu
|
||
`origin` (dein Gitea unter https://git.fojadrachi.de/Fojadrachi/Playtube). Der gepushte
|
||
Tag löst automatisch die Gitea-Actions-Pipeline
|
||
([.gitea/workflows/release.yml](.gitea/workflows/release.yml)) aus, die die
|
||
Windows-Pakete baut und als Release auf dem Gitea veröffentlicht - Fortschritt unter
|
||
https://git.fojadrachi.de/Fojadrachi/Playtube/actions.
|
||
|
||
#### Releases bauen (einmalige Einrichtung)
|
||
|
||
GitHub wird nirgends mehr benutzt. Die Pipeline braucht:
|
||
|
||
1. **Einen Gitea-Actions-Runner unter Windows** (`act_runner`, Label `windows`, Host-Modus)
|
||
mit Python 3.12, git, PowerShell und [Inno Setup 6](https://jrsoftware.org/isinfo.php).
|
||
Registrierung z. B.:
|
||
`act_runner register --instance https://git.fojadrachi.de --token <Runner-Token> --labels windows:host`
|
||
2. **Ein Secret `RELEASE_TOKEN`** im Repo (Einstellungen → Actions → Secrets): ein
|
||
Zugriffstoken (Gitea → Einstellungen → Anwendungen) mit Schreibrecht auf das Repo.
|
||
3. In Gitea **Actions für das Repo aktivieren** (Einstellungen → Erweitert → Repository-Einheiten).
|
||
|
||
**Ohne Runner** kannst du selbst bauen und veröffentlichen:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File packaging\build.ps1
|
||
$env:GITEA_TOKEN = "<Zugriffstoken>"
|
||
powershell -ExecutionPolicy Bypass -File packaging\publish_release.ps1 -Tag v1.1.0 `
|
||
-Files dist\installer\Playtube-Setup-v1.1.0.exe
|
||
```
|
||
|
||
Für Windows entstehen dabei drei Dateien: `Playtube-Setup-vX.Y.Z.exe` (Installer, für
|
||
Neueinsteiger und volle Updates), `Playtube-vX.Y.Z-win64.zip` (portabel) und das kleine
|
||
`...-pyside<Version>-patch.play` (schnelles Update). Der Installer bekommt seine
|
||
Versionsnummer aus `playtube/__init__.py` (das `release.ps1` vor dem Tag setzt).
|
||
|
||
Alle Nutzer mit einer laufenden Playtube-Installation (Windows oder Linux) bekommen die
|
||
neue Version danach automatisch angeboten.
|
||
|
||
## Native Linux-Version
|
||
|
||
Playtube läuft genauso unter Linux (gleicher Code, gleiches PySide6/QtWebEngine). Die
|
||
Pipeline auf dem Gitea baut derzeit nur Windows-Pakete; Linux-Pakete (`.tar.gz`) entstehen
|
||
nur, wenn du zusätzlich einen Linux-Runner einrichtest oder sie selbst mit PyInstaller baust
|
||
(`pyinstaller packaging/playtube.spec`).
|
||
|
||
**Fertiges Release installieren** (richtet Startmenü-Eintrag + Icon ein):
|
||
|
||
```sh
|
||
tar -xzf Playtube-vX.Y.Z-linux-x86_64.tar.gz
|
||
cd Playtube
|
||
sh install-linux.sh
|
||
```
|
||
|
||
Danach ist Playtube über das Anwendungsmenü oder den Befehl `playtube` startbar.
|
||
|
||
**Aus dem Quellcode starten:**
|
||
|
||
```sh
|
||
python3 -m venv .venv
|
||
.venv/bin/pip install -r requirements.txt
|
||
.venv/bin/python main.py
|
||
```
|
||
|
||
QtWebEngine benötigt unter Linux ein paar System-Bibliotheken (auf Debian/Ubuntu):
|
||
`sudo apt install libxkbcommon0 libegl1 libnss3 libxcomposite1 libxdamage1 libxrandr2 libgbm1 libasound2t64 libatk-bridge2.0-0 libcups2 libxtst6 libxcursor1 libatk1.0-0 libdbus-1-3 libdrm2 libpango-1.0-0 libpangocairo-1.0-0 libxfixes3 libxi6 libxext6 fonts-liberation`.
|
||
|
||
## Hinweise
|
||
|
||
- **"Dieser Browser ist unter Umständen nicht sicher" beim Google-Login:** Playtube
|
||
setzt einen echten Chrome-User-Agent inkl. passender `Sec-CH-UA`-Header, damit Google
|
||
das eingebettete Chromium (QtWebEngine) nicht als unsicheres WebView erkennt. Sollte
|
||
die Meldung dennoch erscheinen: alle Playtube-Fenster/-Prozesse schliessen und neu
|
||
starten (die Header greifen erst ab dem nächsten Prozessstart), notfalls einmal den
|
||
Profilordner `%APPDATA%\Playtube\webprofile` (bzw. `PlaytubeDev` im
|
||
Entwicklungsmodus) löschen und neu anmelden.
|
||
- **Auf YouTube/YouTube Music fehlen alle Icons (Play/Pause, Suche, Menü ...):** Fast
|
||
sicher laufen zwei Playtube-Prozesse gleichzeitig auf demselben Browser-Profil - die
|
||
zweite Instanz rendert dann keine Icons mehr. Passiert leicht, weil das Schliessen des
|
||
Fensters Playtube nur in den Tray minimiert: eine ältere Version läuft unsichtbar
|
||
weiter, während eine neu heruntergeladene zusätzlich gestartet wird. Abhilfe: alle
|
||
Playtube-Instanzen über das Tray-Icon (Rechtsklick -> Beenden) bzw. im Taskmanager
|
||
beenden und nur EINE neu starten. Ab der Version mit
|
||
[playtube/single_instance.py](playtube/single_instance.py) verhindert Playtube den
|
||
Doppelstart selbst (ein zweiter Start holt das laufende Fenster nach vorn); eine
|
||
ältere Instanz ohne diesen Schutz wird dabei nicht erkannt und muss einmalig manuell
|
||
beendet werden.
|
||
- 4K/Premium-Videoqualität kann eingeschränkt sein, da die Open-Source-Variante von
|
||
QtWebEngine kein Widevine-DRM mitbringt (Standard-Qualitäten funktionieren normal).
|
||
- Icon/Branding-Bilder liegen unter `assets/` und wurden mit `tools/generate_icon.py`
|
||
erzeugt (Pillow) - bei Bedarf einfach eigenes `icon.ico`/`icon.png` dort ersetzen.
|