HDMI Viewer
Ein schlanker Qt6/C++ HDMI-Viewer für Arch Linux mit V4L2 (Video) und ALSA (Audio). Gedacht als Companion zu OBS Studio: Anzeigen ohne Aufnehmen.
Features
- Live-Vorschau vom HDMI-Grabber via V4L2, mit automatischer Formatpriorität MJPEG → YUYV → NV12 (MJPEG braucht deutlich weniger USB-Bandbreite und erlaubt so höhere Auflösungen/Framerates)
- ALSA-Audio direkt vom Grabber-Gerät (Capture → Wiedergabe, per Thread)
- Gerät-Auswahl beim Start (Video, Audio, Ziel-Framerate), alle Einstellungen werden gespeichert und beim nächsten Start vorausgewählt
- F → Vollbild / F oder Esc im Vollbild → Fenstermodus
- Esc im Fenstermodus → zurück zur Gerät-Auswahl (Device wird sauber freigegeben)
- Seitenverhältnis immer bewahrt (Letterbox/Pillarbox)
- Titelleiste und Statusleiste zeigen tatsächliche Auflösung, FPS und Pixelformat
- GPU-Rendering per OpenGL 3.3 (kein Ruckeln durch CPU-seitiges Skalieren)
- Bildglättung (standardmäßig an, Taste S): GPU-Shader trennt Luma/Chroma und behandelt sie getrennt – Chroma wird stärker weichgezeichnet (killt Dot-Crawl/Farbrauschen billiger Composite→HDMI-Scaler), Luma wird leicht geglättet und dezent gegengeschärft (nimmt harte Scaler-Kanten raus, ohne matschig zu wirken). Keine Optik-Spielerei, sondern eine echte Bildverbesserung.
- Retro-Optik (standardmäßig aus, Taste C): separater Nostalgie-Look – Scanlines, Phosphor-/Aperture-Grille-Maske, leichte Wölbung wie bei einem alten Röhrenfernseher. Lässt sich mit der Bildglättung kombinieren.
- Nachschärfen (Unsharp Mask, Taste X zum Umschalten, +/- zum Fein-Justieren): unabhängig von der Bildglättung, live einstellbar und persistiert.
- Hardware-Helligkeit/-Kontrast/-Sättigung (Tasten ,/., 1/2,
3/4): steuert die entsprechenden V4L2-Regler direkt am
Grabber-Chip, also VOR der JPEG-Kompression – das rettet tatsächlich
Schattendetails, statt nur nachträglich am fertig komprimierten Bild zu
strecken (was sichtbare Artefakte/Banding erzeugt). Beim Start wird der
jeweilige Ausgangswert des Chips ausgelesen und gemerkt; beim Beenden wird
er exakt wiederhergestellt, sodass der Grabber für andere Programme
unverändert bleibt. Im Startdialog lassen sich für alle drei Regler feste
Zielwerte vorgeben (
unverändert= Regler beim Start gar nicht anfassen). - Studio-/Full-Range-Korrektur: Das fertig dekodierte Bild wird von einem komprimierten Kontrastumfang (Schwarzpunkt niedrig angesetzt, Weißpunkt ≈235/255) auf den vollen 0–255-Kontrastumfang gedehnt. Ohne diese Korrektur wirkt das Bild dumpf, kontrastarm und zu dunkel – viele billige HDMI-Grabber liefern (oder kodieren, auch bei MJPEG) genau in diesem komprimierten Bereich. Greift direkt im GPU-Shader auf dem fertigen RGB-Bild, also unabhängig vom Pixelformat.
- Roh-Modus (Taste R): Diagnose-Umschalter, der sämtliche Verarbeitung (Bildglättung, Retro-Optik, Studio-Range-Korrektur, Kontrast-/ Sättigungs-Punch, Gamma) umgeht und das Bild 1:1 anzeigt. Zusätzlich werden die Hardware-Regler am Grabber-Chip auf ihren beim Start gemerkten Ausgangswert zurückgesetzt; beim Ausschalten gelten wieder die gespeicherten Werte bzw. das aktive Profil.
- Live-Vergleich (Taste V): zeigt links das rohe und rechts das bearbeitete Bild nebeneinander – praktisch zum Fein-Tunen der Hardware-Regler.
- Profile (Menü „Profile“, Tasten F1–F9): speichert die aktuelle Kombination aus Bildglättung, Retro-Optik, Nachschärfen und den drei Hardware-Reglern unter einem Namen (z. B. „PlayStation“, „PS3“). Beim Umschalten werden Filter und Grabber-Regler sofort gesetzt; „unverändert“ bei einem Hardware-Regler setzt ihn auf den Ausgangswert des Chips zurück. Speichern/Löschen geht im Menü „Profile“ und im Startdialog, dort lädt die Auswahl die Werte in die Felder. Ein Häkchen markiert das Profil, das zu den aktuellen Einstellungen passt. F1–F9 folgen der alphabetischen Reihenfolge im Menü.
- Screenshot (Taste P): speichert das aktuell angezeigte (bearbeitete) Frame als PNG im Home-Verzeichnis.
- Frame-Dump (Taste D, nur bei MJPEG): speichert das nächste rohe, unveränderte MJPEG-Frame direkt vom Chip als JPEG – nützlich, um zu prüfen, ob Abweichungen schon in den Rohdaten liegen oder erst bei der eigenen Verarbeitung entstehen.
- Programm-Icon und Startmenü-Eintrag: Icon als SVG (
assets/hdmi-viewer.svg), dazu eine.desktop-Datei. Beides wird beicmake --installbzw. über das Paket installiert; das Fenster-Icon ist zusätzlich ins Programm eingebettet.
Abhängigkeiten (Arch Linux)
sudo pacman -S qt6-base qt6-svg cmake alsa-lib base-devel
qt6-base bringt auf Arch bereits die benötigten Qt6OpenGL- und
Qt6OpenGLWidgets-Module mit. qt6-svg wird für das SVG-Programm-Icon
benötigt. linux/videodev2.h ist Teil von
linux-api-headers, das über die base-Gruppe ohnehin installiert ist.
Installation über AUR
yay -S hdmi-viewer
# oder mit einem anderen AUR-Helper, bzw. manuell:
git clone https://aur.archlinux.org/hdmi-viewer.git
cd hdmi-viewer
makepkg -si
Quellcode
git clone https://git.projekt-hirnfrei.de/diabolus/hdmiviewer.git
Manuell bauen
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
Optional systemweit installieren (inkl. Startmenü-Eintrag und Icon):
sudo cmake --install . --prefix /usr/local
Starten
./hdmi-viewer
Tastenkürzel
| Taste | Funktion |
|---|---|
| F | Vollbild ein/aus |
| S | Bildglättung ein/aus |
| C | Retro-Optik (Scanlines/Maske) ein/aus |
| X | Nachschärfen ein/aus (letzter Wert ↔ aus) |
| + / - | Nachschärfen stärker / schwächer |
| , / . | Hardware-Helligkeit dunkler / heller |
| 1 / 2 | Hardware-Kontrast runter / hoch |
| 3 / 4 | Hardware-Sättigung runter / hoch |
| R | Roh-Modus (Diagnose, alle Filter + HW-Regler aus) ein/aus |
| F1–F9 | Profil 1–9 laden (alphabetisch, siehe Menü „Profile“) |
| V | Live-Vergleich (links roh, rechts bearbeitet) ein/aus |
| P | Screenshot speichern (PNG) |
| D | Rohes MJPEG-Frame dumpen (Diagnose) |
| Esc | Vollbild verlassen ODER zurück zum Gerätedialog |
Hilfsprogramme
tools/colormatch.py vergleicht zwei Screenshots (z. B. dasselbe Bild in einem
Referenzprogramm und in HDMI Viewer) und ermittelt pro Farbkanal Gain, Offset
und Gamma, die das Testbild an die Referenz angleichen – inklusive fertiger
GLSL-Zeile. Mit --palette werden zusätzlich die häufigsten Flächenfarben
beider Bilder ausgegeben. Benötigt python-numpy und python-pillow.
python3 tools/colormatch.py referenz.png test.png --palette
Beide Bilder müssen auf demselben Weg entstanden sein (z. B. beide als Desktop-Screenshot des laufenden Programms).
Einstellungen
Werden gespeichert in: ~/.config/hdmi-viewer/HDMIViewer.conf
(Standard XDG-Pfad, kein manuelles Anlegen nötig). Profile liegen in
derselben Datei im Abschnitt [profiles].
Audio-Gerät finden
# Alle ALSA-Capture-Geräte auflisten
arecord -l
# Testen (hw:X,Y aus arecord -l, z.B. hw:2,0)
arecord -D hw:2,0 -f S16_LE -r 48000 -c 2 /tmp/test.wav
aplay /tmp/test.wav
Das Gerät dann im Dialog so eingeben: z.B. hw:2,0 oder plughw:2,0
(plughw macht automatische Sample-Rate-Konvertierung, falls nötig)
Änderungen
1.1.0
- Profile: Kombinationen aus Bildglättung, Retro-Optik, Nachschärfen und Hardware-Reglern speichern, laden und per F1–F9 umschalten (Menü und Startdialog)
- Fix: Das Bild wurde in der Anzeige auf etwa die Hälfte der Helligkeit
abgedunkelt (Weiß 255 → 128), auch im Roh-Modus. Ursache war OpenGL-Zustand
(u. a. Blending), den der
QPainterder „Kein Signal“-Anzeige zurückließ. Der Zustand wird jetzt vor dem Zeichnen des Videobilds zurückgesetzt. - Roh-Modus (R) setzt zusätzlich die Hardware-Regler auf den Ausgangswert
- Neues Programm-Icon, Startmenü-Eintrag, neue Abhängigkeit
qt6-svg - Neues Hilfsprogramm
tools/colormatch.py
1.0.0
- Erste Version