diff --git a/.gitignore b/.gitignore index 8a6a7f3..d5386bd 100644 --- a/.gitignore +++ b/.gitignore @@ -35,5 +35,8 @@ video-konverter/app/cfg/ .DS_Store Thumbs.db +# Tizen Studio Workspace +workspace/ + # Claude .claude/ diff --git a/tizen-app/INSTALL.md b/tizen-app/INSTALL.md index 7bf1af3..8e2c5d1 100644 --- a/tizen-app/INSTALL.md +++ b/tizen-app/INSTALL.md @@ -4,7 +4,7 @@ Die VideoKonverter TV-App auf einem Samsung Smart TV (Tizen) installieren. ## Voraussetzungen -- Samsung Smart TV mit Tizen OS (ab 2017) +- Samsung Smart TV mit Tizen OS (ab 2017, getestet: Tizen 9.0) - PC und TV im gleichen Netzwerk - Samsung Developer Account (kostenlos): https://developer.samsung.com/ - Tizen Studio auf dem PC @@ -20,105 +20,131 @@ Download: https://developer.tizen.org/development/tizen-studio/download chmod +x web-ide_Tizen_Studio_*.bin ./web-ide_Tizen_Studio_*.bin -# Nach Installation: Tools liegen unter ~/tizen-studio/ -# Package Manager oeffnen und installieren: -# - Tizen SDK Tools -# - Samsung TV Extensions (Extension SDK Tab) -# - Samsung Certificate Extension (Extension SDK Tab) +# Nach Installation: Package Manager CLI nutzen +~/tizen-studio/package-manager/package-manager-cli.bin install \ + --accept-license cert-add-on TV-SAMSUNG-Public + +# WICHTIG auf Manjaro/Arch: Fake-dpkg Wrapper anlegen +# (Tizen PM prueft dpkg Pakete die auf Arch nicht existieren) +mkdir -p /tmp/fake-dpkg +cat > /tmp/fake-dpkg/dpkg << 'EOF' +#!/bin/bash +if [[ "$*" == *"-l"* ]] || [[ "$*" == *"--list"* ]] || [[ "$*" == *"-s"* ]]; then + for pkg in "$@"; do + [[ "$pkg" != -* ]] && echo "ii $pkg 99.0 amd64 Fake" + done +fi +exit 0 +EOF +chmod +x /tmp/fake-dpkg/dpkg +# Dann mit PATH="/tmp/fake-dpkg:$PATH" den Package Manager starten ``` ### Wichtige Pfade nach Installation ``` -~/tizen-studio/tools/sdb # Smart Development Bridge (wie adb) -~/tizen-studio/tools/ide/bin/tizen # CLI-Tool -~/tizen-studio/ide/TizenStudio # IDE starten +~/tizen-studio/tools/sdb # Smart Development Bridge +~/tizen-studio/tools/ide/bin/tizen # CLI-Tool +~/tizen-studio/tools/certificate-manager/certificate-manager # Certificate Manager GUI ``` ## Schritt 2: Samsung Developer Zertifikat erstellen -Das Zertifikat signiert die App fuer deinen TV. Ohne Zertifikat verweigert der TV die Installation. +Das Zertifikat signiert die App fuer den TV. Samsung TVs akzeptieren NUR Samsung-signierte +Zertifikate (nicht Standard-Tizen!). -1. Tizen Studio IDE starten -2. **Tools > Certificate Manager** oeffnen -3. **"+" klicken** > **Samsung** waehlen (nicht Tizen!) -4. **TV** als Geraetetyp waehlen -5. Samsung Developer Account Daten eingeben -6. Zertifikat wird erstellt und gespeichert +### Voraussetzung: Samsung Certificate Extension installieren + +```bash +# MUSS installiert sein, sonst erscheint "Samsung" nicht als Option! +PATH="/tmp/fake-dpkg:$PATH" ~/tizen-studio/package-manager/package-manager-cli.bin \ + install --accept-license cert-add-on +``` + +### Zertifikat erstellen (Certificate Manager GUI) + +1. Certificate Manager starten: `~/tizen-studio/tools/certificate-manager/certificate-manager` +2. **"+" klicken** > **Samsung** waehlen (NICHT Tizen!) +3. **TV** als Geraetetyp waehlen +4. Author-Zertifikat: Key Filename + Author Name eingeben +5. Samsung Developer Account einloggen +6. Distributor-Zertifikat: DUID des TVs eintragen (siehe Schritt 3) +7. **Finish** - Zertifikat wird unter `~/SamsungCertificate//` gespeichert **WICHTIG:** Zertifikat sichern! Bei App-Updates muss das gleiche Zertifikat verwendet werden. +Backup liegt in `tizen-app/certs/`. ## Schritt 3: TV vorbereiten (Developer Mode) -### Ueber TV-Menue - 1. TV einschalten 2. **Apps** oeffnen (Home > Apps) -3. Im Apps-Bereich die Ziffern **12345** eingeben (bei neueren Fernbedienungen evtl. ueber das virtuelle Nummernfeld) +3. Ziffern **12345** eingeben (virtuelles Nummernfeld bei neueren Fernbedienungen) 4. Developer Mode **ON** schalten 5. **Host PC IP** eingeben (IP des PCs mit Tizen Studio) -6. TV neustarten +6. **TV neustarten** (wichtig!) -### Alternative (neuere TVs ab 2024/Tizen 8) +### DUID auslesen (fuer Zertifikat) -Falls der 12345-Trick nicht funktioniert: -- **Einstellungen > Allgemein > System-Manager** nach Developer Mode suchen -- Oder direkt ueber Tizen Studio Device Manager verbinden (siehe Schritt 4) +```bash +# Erst TV verbinden (Schritt 4), dann: +~/tizen-studio/tools/sdb shell 0 getduid +# Gibt z.B. zurueck: KLCDNTGIJS4OU +``` ## Schritt 4: TV verbinden -1. **TV-IP herausfinden:** TV > Einstellungen > Allgemein > Netzwerk > IP-Adresse -2. In Tizen Studio: **Tools > Device Manager** oeffnen -3. **Remote Device Manager** > TV-IP eingeben > Verbinden -4. TV sollte in der Geraete-Liste erscheinen -5. **Rechtsklick auf TV > "Permit to install applications"** - -### Oder per Kommandozeile - ```bash -# Verbinden +# Verbinden (Port 26101 muss offen sein) ~/tizen-studio/tools/sdb connect # Pruefen ~/tizen-studio/tools/sdb devices +# Zeigt: :26101 device ``` -## Schritt 5: App installieren +Falls Verbindung fehlschlaegt: +- Developer Mode aktiviert? PC-IP korrekt eingegeben? +- TV nach Aenderung des Developer Mode neugestartet? +- Port 26101 in Firewall offen? -### Option A: Ueber Tizen Studio IDE (empfohlen) +## Schritt 5: WGT bauen und installieren -1. Device Manager: TV ist verbunden -2. **Rechtsklick auf TV > "Install app"** -3. `VideoKonverter.wgt` auswaehlen -4. Installation laeuft automatisch - -### Option B: Per Kommandozeile +### WGT mit Samsung-Zertifikat signieren ```bash -cd /pfad/zu/tizen-app/ -~/tizen-studio/tools/ide/bin/tizen install -n VideoKonverter.wgt -t +# Sauberes Build-Verzeichnis erstellen (nur App-Dateien!) +mkdir -p /tmp/tizen-build +cp tizen-app/config.xml tizen-app/index.html tizen-app/icon.png /tmp/tizen-build/ + +# WGT mit Samsung Security Profile signieren +cd /tmp/tizen-build +~/tizen-studio/tools/ide/bin/tizen package -t wgt -s -- /tmp/tizen-build/ ``` -Der TV-Name wird mit `sdb devices` angezeigt. - -### Option C: Docker (ohne Tizen Studio) - -Falls Tizen Studio zu aufwaendig ist - das Georift Docker-Image hat alles drin: +### Auf TV installieren ```bash -# Generisches WGT installieren (ohne Tizen Studio auf dem PC) -docker run --rm -v $(pwd):/app georift/install-jellyfin-tizen \ - --wgt /app/VideoKonverter.wgt +# TV-Name mit sdb devices ermitteln +~/tizen-studio/tools/ide/bin/tizen install -n /tmp/tizen-build/VideoKonverter.wgt -t ``` -Siehe: https://github.com/Georift/install-jellyfin-tizen +Erfolgreiche Ausgabe: +``` +Tizen application is successfully installed. +``` + +### App deinstallieren (falls noetig) + +```bash +~/tizen-studio/tools/sdb shell 0 vd_appuninstall vkTVApp001.VideoKonverter +``` ## Schritt 6: App starten 1. App erscheint als **"VideoKonverter"** im Apps-Menue des TVs 2. Beim **ersten Start**: Server-IP eingeben (z.B. `192.168.155.12:8080`) 3. Die IP wird gespeichert - beim naechsten Start verbindet die App automatisch -4. Login mit TV-App Benutzerdaten (erstellt in der Admin-Oberflaeche) +4. Login mit TV-App Benutzerdaten (erstellt in der Admin-Oberflaeche unter `/admin`) ## Wie funktioniert die App? @@ -133,25 +159,37 @@ Die App auf dem TV muss NICHT neu installiert werden. ## Fehlerbehebung +### "Invalid certificate chain" bei Installation +- **Haeufigster Fehler!** Samsung TVs akzeptieren NUR Samsung-signierte Zertifikate +- Im Certificate Manager: "Samsung" waehlen, NICHT "Tizen" +- Samsung Certificate Extension (`cert-add-on`) muss installiert sein + ### TV wird nicht gefunden - Sind PC und TV im gleichen Netzwerk/VLAN? -- Ist Developer Mode auf dem TV aktiviert? -- Firewall auf dem PC deaktiviert/Port 26101 offen? +- Ist Developer Mode auf dem TV aktiviert + TV neugestartet? +- Firewall auf dem PC: Port 26101 offen? -### Installation schlaegt fehl -- Zertifikat korrekt erstellt? (Samsung, nicht Tizen) -- "Permit to install applications" ausgefuehrt? -- Alte Version erst deinstallieren: `sdb shell 0 vd_appuninstall vkTVApp001.VideoKonverter` +### Video startet langsam / nicht +- Server laeuft? `curl http://:8080/tv/` +- AV1-Videos brauchen einen TV mit AV1-Unterstuetzung (ab ~2020) +- Streaming nutzt fragmented MP4 (`frag_keyframe+empty_moov+default_base_moof`) ### App startet nicht / weisser Bildschirm -- Server laeuft? `curl http://:8080/tv/` -- Richtige IP eingegeben? -- Browser-Cache auf TV leeren: App deinstallieren und neu installieren +- Richtige Server-IP eingegeben? +- Browser-Cache leeren: App deinstallieren und neu installieren + +## Getestete Konfiguration + +| Komponente | Version | +|-----------|---------| +| Samsung TV | GQ65Q7FAAUXZG (Tizen 9.0) | +| Tizen Studio | 6.0+ | +| sdb | 4.2.36 | +| tizen CLI | 2.5.25 | +| Host OS | Manjaro Linux (KDE) | ## Links - Samsung Developer Portal: https://developer.samsung.com/smarttv/develop - Tizen Studio Download: https://developer.tizen.org/development/tizen-studio/download - Samsung TV Quick-Start Guide: https://developer.samsung.com/smarttv/develop/getting-started/quick-start-guide.html -- Jellyfin Tizen (aehnliches Projekt): https://github.com/jellyfin/jellyfin-tizen -- Samsung-Jellyfin-Installer (GUI): https://github.com/Jellyfin2Samsung/Samsung-Jellyfin-Installer diff --git a/tizen-app/VideoKonverter.wgt b/tizen-app/VideoKonverter.wgt index 089f8bf..4af4ba2 100644 Binary files a/tizen-app/VideoKonverter.wgt and b/tizen-app/VideoKonverter.wgt differ diff --git a/tizen-app/certs/author.crt b/tizen-app/certs/author.crt new file mode 100644 index 0000000..a3abc31 --- /dev/null +++ b/tizen-app/certs/author.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEfTCCAmWgAwIBAgIIV7LKnb5BWxEwDQYJKoZIhvcNAQELBQAwgZIxCzAJBgNV +BAYTAktSMRowGAYDVQQIDBFSZXB1YmxpYyBvZiBLb3JlYTETMBEGA1UEBwwKU3V3 +b24gQ2l0eTEmMCQGA1UECgwdU2Ftc3VuZyBFbGVjdHJvbmljcyBDby4sIEx0ZC4x +CzAJBgNVBAsMAlZEMR0wGwYDVQQDDBRTYW1zdW5nIFZEIEF1dGhvciBDQTAeFw0y +NjAyMjgyMTEwMDhaFw0yNzAyMjgyMTEwMDhaME4xCTAHBgNVBAYTADEJMAcGA1UE +CBMAMQkwBwYDVQQHEwAxCTAHBgNVBAoTADEJMAcGA1UECxMAMRUwEwYDVQQDEwxF +ZHVhcmQgV2lzY2gwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCPuf5J +A+94c9QTqtm8rF6zPOCRjXZGZ+CoZLaJ1NMWLEwyTasEf08qkbiwzlmH3EAlyh4e +EmEBTqb5n6wCaakUtxwBYOb79yFSpoUU254XhjNilRW6F4x0loY+l6SaDpfkRjMx +PSLUZn2wXOXsVIgH39EFK3V1098hS5dBU++eBKhGFabvXo6cwC8a/f7CaE6JFZxe +v+F2zZW4nYWEAl6QTrgBWrGrzZQHbGjID8ZOcx/I2xQP0yD2oNsxMxWppUxCJjZS +k97hRA+XN/j1AVIRokXJDcOfifsNMNp6y0HV029X+57KN/zlGzZBJIXaRqqQS5JW +gHH9Oyn210Cj9iylAgMBAAGjGjAYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgeAMA0G +CSqGSIb3DQEBCwUAA4ICAQBfaijH6HNNoUEBxXgGX6cxhoyVwhRQHIdkjBvmSi3G +Yf9E3agFM2SFo/TiFgQzEssiQiXabHKiYohUlDxjGp88UqilMyVflq54Uzw7EpBM +XxHlxTWIMdnUWXTRBbbxSFnvcde2dcH2hFk5TeiddaXOwcvErl6ewDytkBgL/MVT +zqUoiN7ATMwx1R3D5Kp7sog14UwkiKHLOdven+leURhRkl6rxJ9dD5X1ETisXhF5 +QFazYXm/Hm3cAMfzqZVZGAXn0YZg2cP+iwroFGXxXONDaJAYNleUXZvZqhfXIN81 +zqeIVL2fotl8pUiLkTihbBjd1bvzK+aAHPHeJHKbBBjGfH6l5d5d5xj9RU7o92bv +CiUe+lwN4IBcox8w1zFPqGv/8MFwcK/hoNh001rsAOoU3PQPag/7cvReqaKHbNNr +b8wUAlieTZktyrs4Ey9bd0eSJer5YfyLuQi1CiiLRcth2h5O9Xj4UEZfFE1DoIiQ +S1d/HQ1+MyFd2RszNqLqORL0PfgT909GSN+g0FIO/4uOvJUikAnhNT1QD62p6DvS +XJtlDE2KeYEzwoAxpX7RDf8AXuvFe9VG2rrmGJjXu+iPv6ez3+TnrXnUovxeoJZw +avbvaMDa93lcnTqzxhzXmJAC9kN+6L0ocN+XZIanxEABXm7+cOLkjRNRjg6n9unB +jQ== +-----END CERTIFICATE----- diff --git a/tizen-app/certs/author.p12 b/tizen-app/certs/author.p12 new file mode 100644 index 0000000..166cd13 Binary files /dev/null and b/tizen-app/certs/author.p12 differ diff --git a/tizen-app/certs/distributor.crt b/tizen-app/certs/distributor.crt new file mode 100644 index 0000000..9fb8346 --- /dev/null +++ b/tizen-app/certs/distributor.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEyjCCArKgAwIBAgIIHZzx6svX/q0wDQYJKoZIhvcNAQELBQAwgY8xCzAJBgNV +BAYTAktSMRQwEgYDVQQIDAtTb3V0aCBLb3JlYTEOMAwGA1UEBwwFU3V3b24xJjAk +BgNVBAoMHVNhbXN1bmcgRWxlY3Ryb25pY3MgQ28uLCBMdGQuMQswCQYDVQQLDAJW +RDElMCMGA1UEAwwcVkQgREVWRUxPUEVSIFB1YmxpYyBDQSBDbGFzczAeFw0yNjAy +MjgyMTExMzJaFw0yNzAyMjgyMTExMzJaMHMxETAPBgNVBAMMCFRpemVuU0RLMQkw +BwYDVQQLDAAxCTAHBgNVBAoMADEJMAcGA1UEBwwAMQkwBwYDVQQIDAAxCTAHBgNV +BAYTADEnMCUGCSqGSIb3DQEJARYYZGF0YUBkYXRhLWl0LXNvbHV0aW9uLmRlMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsIsx/nP0lNgrK5726AEUxgeo +Qjc4K/O6QvdGdquoGKUgy+cLVVF4COKNPM/PrcEFI36yXH8fAoSmd0+6QGRi8VB4 +ZUhJDiuSEy8GD+VXEPB3sFKl4sR0AtD8K5nEaioegE6ldJmLYtROysgFAsFLWv9I +L00OkMSDR5+mxtbT9wf2XJG8q+GToGJ0/UBEp/AMkfZ6M8DdhUZRFlfsASfRuOfa +aQ2joKqDR7Lq4mZdU1esJfN2HsuCBdT4e104QZOtelMW10f8KarWV8nFIkDIsq+B +3Y1zbinH/gYNwOrzqwnH7KgiBvjRc+KCfuFd5BUaV/6igl7dEluFb1zWoFNKrQID +AQABo0UwQzBBBgNVHREEOjA4hhRVUk46dGl6ZW46cGFja2FnZWlkPYYgVVJOOnRp +emVuOmRldmljZWlkPUtMQ0ROVEdJSlM0T1UwDQYJKoZIhvcNAQELBQADggIBAA8D +l3Unyxt/a0xv6Rq1FPvBdMhj4KtFDm18Rd+b6966Dun6VTEwSzbmywewZqcM2rNt +qB91AHUegVoRg0bCEBLA8mwqIPCvnSf/BuX7xtUpvdFVrF4EzgbryAT3HOfAphZ3 +lftMOD+NreXjpp2NGgZ7GeqYzwDZFK1kvhGzIix1lozA+q111+kNuZ87HGVgO1z2 +0MPtR9AxwCCNWZV9t/mNNWSuvyrUwkCMy4hwSYzWp0Q09g5MZdgaqvv0GE8cB1hO +85EKEqY64RHZlAUTIKNlm2veGRWMoHIooBa3kdAjB+GK9Krv+delcOvzeb5Ys9Xq +C58ouFD5VPovt0CfLJ8E1MOcwrCjdm0GYw5pyi1i8yVqwjQa6F60DEhQoWtF7XPo +IRRsHcZXNQCzTwVm3Xa71VR3JQL7RM6QRoOiUdaQh2hs5HqwgdsT/gFqThp/bMFZ +fSM5RZ+TqLbdXO9FWK7XsnIz3dlJdBjw/RCRpO94gjTWL+Adb9bzcAFULv8dMjKF ++9eSE81uFyaEuuyRhkBlw7f2RsUbpDeywuoXbCNv0FJO8buWRcPTjSeHLbSfyajN +T0MKY5L/68joIKByjd6e1npM4OLdZ6mq+wL8HIeISCcpJv2yZxjDLN8tVn6mX9ZC +IDvpfiuZx37W72DPJViYIXkcroSK1m9w6wIIoyg8 +-----END CERTIFICATE----- diff --git a/tizen-app/certs/distributor.p12 b/tizen-app/certs/distributor.p12 new file mode 100644 index 0000000..bfeb393 Binary files /dev/null and b/tizen-app/certs/distributor.p12 differ diff --git a/video-konverter/app/routes/library_api.py b/video-konverter/app/routes/library_api.py index 292573e..ef4e2e4 100644 --- a/video-konverter/app/routes/library_api.py +++ b/video-konverter/app/routes/library_api.py @@ -1359,16 +1359,22 @@ def setup_library_routes(app: web.Application, config: Config, seek_sec = float(request.query.get("t", "0")) # ffmpeg-Kommando: Video copy, Audio -> AAC Stereo, MP4-Container + # frag_keyframe: Fragment bei jedem Keyframe + # empty_moov: Leerer moov-Atom am Anfang (noetig fuer pipe) + # default_base_moof: Bessere Browser-Kompatibilitaet (Samsung TV etc.) + # frag_duration: Kleine Fragmente fuer schnellen Playback-Start cmd = [ "ffmpeg", "-hide_banner", "-loglevel", "error", ] if seek_sec > 0: + # -ss VOR -i fuer schnelles Seeking (Input-Seeking) cmd += ["-ss", str(seek_sec)] cmd += [ "-i", file_path, "-c:v", "copy", "-c:a", "aac", "-ac", "2", "-b:a", "192k", - "-movflags", "frag_keyframe+empty_moov+faststart", + "-movflags", "frag_keyframe+empty_moov+default_base_moof", + "-frag_duration", "1000000", "-f", "mp4", "pipe:1", ]