In den Einstellungen (Gruppe "Audioausgabe", Felder "YouTube" und "YouTube Musik") laesst
sich getrennt waehlen, ueber welches Ausgabegeraet der Ton jedes Tabs laeuft - z.B. auf
getrennte Sonar-Kanaele. Die Auswahl gilt sofort, auch fuer bereits geoeffnete Seiten.
Warum ueber die Seite: QtWebEngine spielt beide Tabs ueber einen gemeinsamen Audio-Prozess
ab, Windows kann sie daher nicht einzeln routen. Chromium kann aber pro Medienelement ein
Geraet waehlen (setSinkId).
- audio_routing.py (neu): Router-Skript (findet das Geraet ueber seinen Namen, kennt den
Hardware-ID-Suffix von Chromium, behandelt dynamisch erzeugte Elemente, Zielwechsel,
Zuruecksetzen und fehlende Geraete), Geraeteliste (QMediaDevices), Freigabe der
Geraetenamen (Chromium blendet sie ohne Mikrofon-Berechtigung aus)
- Freigabe nur solange ein Tab ein eigenes Geraet nutzt, nur fuer die beiden YouTube-
Seiten, nur fuer die laufende Sitzung (Qt speichert sie nicht) - bei jedem Start und nach
jedem Seitenaufbau neu erteilt, weil sie auf der YouTube-Startseite sonst nicht greift
- browser: BrowserTab.set_audio_output (Skript pro Seite; ohne Auswahl wird die Seite gar
nicht angefasst)
- settings_tab: neue Gruppe, Hot-Plug-Aktualisierung, fehlendes Geraet bleibt als "nicht
verfuegbar" gespeichert, Discord-Anzeige nennt das bearbeitete Feld
- config: audio.youtube_output / audio.music_output (leer = Systemstandard)
- README: Abschnitt inkl. Hinweis, dass Windows weiter einen Eintrag "Playtube" zeigt
Anhand der neuen Debug-Logs (siehe vorheriger Commit) konnte der Bug endlich anhand
echter Daten diagnostiziert werden: video.currentTime/video.duration sind bei YouTube
Music beim Songwechsel NICHT verlaesslich - wegen nahtloser (gapless) Wiedergabe laeuft
darunter ein durchgehender Buffer, dessen currentTime/duration nicht pro Titel
zurueckgesetzt wird. Log-Beweis: beim Wechsel zu einem neuen Titel wurde die
verbleibende Spielzeit des VORHERIGEN Titels als Start-Offset des neuen uebernommen,
und die Dauer wuchs bei jedem Poll weiter statt konstant zu bleiben.
- media_probe.py: liest Fortschritt/Gesamtlaenge jetzt aus der sichtbar angezeigten
Fortschrittsanzeige (ARIA-Attribute des YT-Music-Sliders in Sekunden, sonst
Zeit-Text im Player; bei YouTube .ytp-time-current/.ytp-time-duration) statt aus den
unzuverlaessigen <video>-Eigenschaften - diese Anzeige MUSS pro Titel stimmen, weil
der Nutzer sie selbst so sieht.
- config.py/main.py: Cache (webprofile/cache) wird automatisch geleert, wenn seit dem
letzten Start ein Update installiert wurde - Login (webprofile/storage) bleibt
unangetastet.
- shortcuts.py/main.py: legt beim ersten Start der gepackten .exe automatisch eine
Windows-Startmenue-Verknuepfung an (Playtube wird als portables ZIP ohne Installer
ausgeliefert, haette sonst nie einen Startmenue-Eintrag).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
console=False im PyInstaller-Build bedeutet: print()/PLAYTUBE_DEBUG-Ausgaben
sind fuer den Nutzer komplett unsichtbar - alle bisherigen Fixes basierten
daher auf Symptombeschreibungen statt echten Daten. Schreibt jetzt bei jedem
RPC-Send (Titel, Thumbnail, large_image, start/end, Track-Wechsel-Erkennung)
eine Zeile in %APPDATA%/Playtube/logs/discord_rpc.log (auf 500 Zeilen
gekappt), damit sich das Bild-Problem anhand echter Daten diagnostizieren
laesst statt weiter zu raten.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Verhindert, dass ein lokaler Test-/Dev-Build (python main.py) sich Login-Profil und
Discord-Konfiguration mit einer installierten/gepackten Playtube.exe teilt - genau das
hatte zuletzt zur falschen Discord-Client-ID in der echten Installation gefuehrt.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Wurzelursache gefunden: page().runJavaScript() liefert bei einem direkt
zurueckgegebenen JS-Objekt in dieser PySide6/QtWebEngine-Version zuverlaessig nur
einen leeren String statt das Objekt (Zahlen/Strings funktionieren, Objekte nicht).
Dadurch schlug 'isinstance(result, dict)' in BrowserTab._on_media_probe_result IMMER
fehl, mediaInfoChanged wurde nie emittiert, MainWindow._on_media_info nie aufgerufen
und der DiscordRPCWorker damit nie mit echten Daten gefuettert (Warteschlange blieb
fuer immer leer, der Worker hat sich nie mal mit Discord verbunden).
Fix: media_probe.py gibt jetzt JSON.stringify(...) zurueck, browser.py parst den
String mit json.loads(). Per isoliertem Test verifiziert (Songtitel erscheint jetzt
korrekt im Fenstertitel, Discord-Update wird erfolgreich gesendet).
Ausserdem: PLAYTUBE_DEBUG=1 Env-Var fuer Debug-Logging in browser.py/discord_rpc.py,
Exceptions in discord_rpc.py werden jetzt sichtbar geloggt statt verschluckt,
neue Discord Client-ID.
Co-Authored-By: Claude Sonnet 5 <[email protected]>