LW IT Solutions
« Przegląd bloga /Raspberry Pi/Tutorials / Lokalny serwer mediów bez opóźnień: Jellyfin na...
Ten artykuł w innych językach:

Lokalny serwer mediów bez opóźnień: Jellyfin na Raspberry Pi 5 z akceleracją sprzętową

Część 5 z 5 serii Homelab na Raspberry Pi

Lokalny serwer mediów bez opóźnień: Jellyfin na Raspberry Pi 5 z akceleracją sprzętową
Spis treści
  1. Przegląd architektury: Dekodowanie mediów na platformie Raspberry Pi 5
  2. Instrukcja wdrożenia krok po kroku
  3. Podsumowanie i mierzalna wartość dodana
  4. Pytania i odpowiedzi
  5. Źródła

Przegląd architektury: Dekodowanie mediów na platformie Raspberry Pi 5

Utrzymanie samodzielnie zarządzanego serwera strumieniowania wideo na komputerze Raspberry Pi tradycyjnie wiązało się z wąskimi gardłami wydajnościowymi w sytuacjach wymagających transkodowania w czasie rzeczywistym. Nieobsługiwane kodeki, niekompatybilne ścieżki dźwiękowe lub ograniczenia przepustowości sieci wymuszają na serwerze mediów dekodowanie i ponowne kodowanie klatek wideo w locie. Na uniwersalnych rdzeniach procesora ARM programowe transkodowanie materiałów HEVC (H.265) lub 4K o wysokiej przepływności błyskawicznie wyczerpuje zasoby CPU, prowadząc do dławienia termicznego i zacinania odtwarzanego obrazu.

Raspberry Pi 5 (wyposażony w układ SoC Broadcom BCM2712) dekoduje sprzętowo wyłącznie HEVC, a ten dekoder jest bezstanowy: obsługuje się go przez V4L2 Request API, a nie przez stanowe dekodery V4L2-M2M, takie jak hevc_v4l2m2m. Jellyfin z niego nie korzysta: opcja „Video4Linux2” używa wyłącznie koderów V4L2, takich jak h264_v4l2m2m, a koder w Raspberry Pi 5 nie istnieje; projekt wycofał ponadto obsługę V4L2 dla Raspberry Pi. Uruchomiony w kontenerze na Raspberry Pi 5 Jellyfin dekoduje i koduje więc programowo na czterech rdzeniach ARM Cortex-A76; niski pobór mocy dotyczy Direct Play, a nie transkodowania.

Trzywarstwowy diagram od klienta przez kontener Jellyfin do hosta Raspberry Pi, z ustawieniami, które muszą przekroczyć każdą granicę
Na Raspberry Pi 5 Jellyfin transkoduje programowo: V4L2 dla Raspberry Pi jest wycofane, akceleracja sprzętowa stoi na „Brak”, a z bezstanowego dekodera HEVC Jellyfin nie korzysta — szybkie i oszczędne pozostaje tylko Direct Play.

Instrukcja wdrożenia krok po kroku

Krok 1: Przygotowanie systemu operacyjnego i weryfikacja urządzeń DRM

Wymagana jest 64-bitowa instalacja systemu Raspberry Pi OS Lite, co gwarantuje kompatybilność z 64-bitowymi bibliotekami sprzętowymi FFmpeg; od października 2025 aktualne obrazy bazują na Debianie 13 (Trixie), a Debian 12 (Bookworm) stanowi wersję minimalną. Przed inicjalizacją środowiska kontenerowego obecność węzłów graficznych Direct Rendering Manager (DRM) musi zostać zweryfikowana z poziomu terminala:

ls -l /dev/dri

Prawidłowa odpowiedź systemu wyświetla węzły kart graficznych oraz renderowania (card0, card1, renderD128). W celu udostępnienia tych zasobów dla kontenerów Docker, należy sprawdzić i przypisać uprawnienia do grup systemowych:

sudo usermod -aG video,render "$USER"

Krok 2: Struktura katalogów i montowanie nośników NVMe

W celu zapewnienia natychmiastowego indeksowania biblioteki oraz stabilnego odczytu plików o wysokim bitrate, archiwa wideo powinny znajdować się na dysku SSD NVMe podłączonym magistralą PCIe 2.0/3.0 lub na macierzy USB 3.0 obsługującej protokół UASP. W ścieżce /opt/containers/jellyfin/ tworzy się przejrzistą hierarchię katalogów:

mkdir -p /opt/containers/jellyfin/{config,cache}
mkdir -p /mnt/media/{movies,series}
chmod -R 755 /mnt/media

Krok 3: Konfiguracja deklaratywnego stosu Docker Compose

Orkiestracja kontenera jest definiowana w pliku /opt/containers/jellyfin/docker-compose.yml. Katalog /dev/dri hosta, którego wymagałaby akceleracja sprzętowa, jest mapowany wewnątrz kontenera, na Raspberry Pi 5 jedynie zapobiegawczo (zob. krok 4), proces kontenera działa pod stałym identyfikatorem użytkownika wskazanym w user, a numeryczne identyfikatory grup (GID) render oraz video z hosta są dopisywane przez group_add:

services:
  jellyfin:
    image: jellyfin/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    user: "1000:1000"
    group_add:
      - "44"  # Zastąpić numerycznym ID grupy 'video' na hoście
      - "109" # Zastąpić numerycznym ID grupy 'render' na hoście
    network_mode: "host"
    environment:
      - JELLYFIN_PublishedServerUrl=http://jellyfin.lukaswojcik.com
    volumes:
      - "/opt/containers/jellyfin/config:/config"
      - "/opt/containers/jellyfin/cache:/cache"
      - "/mnt/media:/media:ro"
    devices:
      - "/dev/dri:/dev/dri"
    security_opt:
      - no-new-privileges:true

Uwaga techniczna: Zastosowanie parametru network_mode: "host" maksymalizuje przepustowość sieciową i umożliwia automatyczne wykrywanie urządzeń w sieci lokalnej przez protokoły DLNA/UPnP bez konieczności przekierowywania portów.

Krok 4: Ustawienia transkodowania w panelu Jellyfin

Po uruchomieniu stosu poleceniem docker compose up -d transkodowanie jest ustawiane w interfejsie administracyjnym Jellyfin:

  1. Otworzyć interfejs webowy pod adresem http://<IP-Raspberry-Pi>:8096 i przejść do sekcji Kokpit → Odtwarzanie → Transkodowanie.
  2. W menu rozwijanym Akceleracja sprzętowa nie wybierać żadnej akceleracji. Video4Linux2 (V4L2) nic nie daje na Raspberry Pi 5: Jellyfin używa przez nią wyłącznie koderów V4L2, układ BCM2712 nie ma żadnego kodera wideo, a dokumentacja Jellyfin podaje V4L2 dla Raspberry Pi jako wycofane. Pozycja OpenMAX/OMX już nie istnieje: Jellyfin ją usunął, a z Raspberry Pi OS interfejs OMX zniknął wraz z wydaniem Bullseye.
  3. Pól wyboru dekodowania sprzętowego nie trzeba więc zaznaczać. Jedynego dekodera sprzętowego układu SoC, tego dla HEVC, Jellyfin nie używa, a bloków dekodera H.264, MPEG-2 i MPEG-4 znanych z Raspberry Pi 4 układ BCM2712 już nie zawiera — wszystkie formaty są dekodowane programowo na rdzeniach Cortex-A76.
  4. Wskazać Ścieżkę FFmpeg jako /usr/lib/jellyfin-ffmpeg/ffmpeg i zapisać ustawienia.

Krok 5: Kontrola jakości i audyt transkodowania w czasie rzeczywistym

Jak mocno transkodowanie obciąża procesor i czy Jellyfin w ogóle koduje na nowo, pokazuje weryfikacja podczas aktywnego strumieniowania wideo:

  1. Uruchomienie transkodowanego strumienia: Otworzyć plik wideo HEVC (H.265) 10-bit w przeglądarce internetowej nieobsługującej natywnie formatu H.265, wymuszając na serwerze Jellyfin transkodowanie do formatu H.264. Dekodowanie i kodowanie odbywają się przy tym programowo: Jellyfin nie korzysta z dekodera HEVC Raspberry Pi 5, a układ BCM2712 nie zawiera żadnego enkodera wideo, więc kodowanie H.264 wykonuje libx264 na procesorze.
  2. Weryfikacja obciążenia CPU: W sesji SSH na Raspberry Pi uruchomić polecenie htop lub top. Ponieważ dekodowanie i kodowanie odbywają się programowo, wysokie obciążenie wszystkich czterech rdzeni jest w tym scenariuszu spodziewane i nie świadczy o błędnej konfiguracji. Niskie wartości pojawiają się dopiero bez ponownego kodowania, czyli przy Direct Play. To, że sam dekoder HEVC działa, pokazuje jedynie test samego dekodowania poza Jellyfin, z FFmpeg z Raspberry Pi OS na hoście, na przykład ffmpeg -hwaccel drm -i plik.mkv -f null -.
  3. Analiza logów transkodera: Sprawdzić pliki logów w ścieżce /opt/containers/jellyfin/config/log/ffmpeg-transcode-*.txt. Dekoder taki jak hevc_v4l2m2m się tam nie pojawi, bo Jellyfin nie ustawia dla V4L2 żadnego dekodera. Wymowny jest wpis po -codec:v:0: libx264 oznacza ponowne kodowanie obrazu, copy samo przepakowanie.

Podsumowanie i mierzalna wartość dodana

Co da się osiągnąć dzięki instrukcji: Wdrożenie kontenerowego, samodzielnie hostowanego serwera mediów Jellyfin na platformie Raspberry Pi 5, który wydaje pliki wideo w trybie Direct Play, a w razie potrzeby transkoduje je programowo.

Wynikająca z tego wartość dodana:

  • Płynne strumieniowanie bez opóźnień: Archiwa wideo o wysokim bitrate (w tym pliki HEVC/H.265) są odtwarzane natychmiast w trybie Direct Play na urządzeniach obsługujących ich kodek, bez buforowania i przycięć obrazu.
  • Niskie zużycie energii: Przy Direct Play serwer wydaje plik bez dekodowania, co pozwala utrzymać niski pobór mocy, umożliwiając cichą i ekonomiczną pracę 24/7; transkodowanie przez libx264 obciąża natomiast wszystkie cztery rdzenie i wymaga aktywnego chłodzenia.
  • Pełna prywatność danych i brak kosztów abonamentowych: Własna kolekcja mediów pozostaje w stu procentach w sieci lokalnej bez zależności od chmury publicznej, zewnętrznej telemetrii czy opłat subskrypcyjnych.

Pytania i odpowiedzi

Dlaczego Jellyfin transkoduje, choć urządzenie odtwarzające obsługuje HEVC?

Bo serwer sprawdza nie tylko kodek wideo. Ponowne kodowanie obrazu staje się konieczne także wtedy, gdy inna część pliku nie pasuje do urządzenia, a na Raspberry Pi 5 każde takie kodowanie odbywa się programowo. Częste przyczyny to:

  1. Napisy w formatach graficznych, takich jak PGS, których urządzenie nie wyświetla samo. Zostają wtopione w obraz, a do tego wideo musi zostać zakodowane na nowo. Napisy tekstowe, takie jak SRT, da się natomiast zwykle dostarczyć osobno.
  2. Limit przepływności w odtwarzaczu niższy niż przepływność pliku. Serwer przelicza wtedy materiał na mniejszą przepływność, nawet jeśli kodek pasuje.
  3. Ścieżka dźwiękowa, której urządzenie nie obsługuje. Tu często wystarczy przekonwertować sam dźwięk, co obciąża CPU znacznie mniej niż ponowne kodowanie obrazu.

Logi w /config/log, których artykuł używa do kontroli, pokazują, który przypadek zachodzi: jeśli dla wideo stoi tam copy zamiast libx264, plik jest tylko przepakowywany albo konwertowany jest jego dźwięk. Usunięcie przyczyn, na przykład przez napisy tekstowe albo wyższy limit przepływności w odtwarzaczu, prowadzi do Direct Play, a tym samym do niskich wartości CPU, które artykuł podaje dla tego przypadku.

Dlaczego w group_add stoją liczby, a nie nazwy grup video i render?

Jądro sprawdza uprawnienia do /dev/dri według numerycznego identyfikatora grupy, a nazwy video i render są powiązane z tymi numerami tylko w systemie hosta; w obrazie kontenera może ich nie być albo mogą mieć inne numery. Właściwe wartości podaje na hoście polecenie getent group video render. Natomiast usermod z kroku 1 działa tylko dla użytkownika na hoście, a nie dla procesu w kontenerze.

Czy Raspberry Pi 5 potrzebuje w tej konfiguracji aktywnego chłodzenia?

Jeśli ma transkodować, to tak. Ponieważ BCM2712 nie ma kodera wideo, przy każdym transkodowaniu libx264 obciąża wszystkie cztery rdzenie, i to przez cały czas trwania filmu. Bez aktywnego chłodzenia SoC osiąga temperaturę, przy której firmware obniża taktowanie, a właśnie to dławienie termiczne powoduje zacinanie, które artykuł opisuje przy transkodowaniu programowym.

Czy dławienie już wystąpiło, pokazuje na hoście polecenie vcgencmd get_throttled: wartość 0x0 oznacza, że od uruchomienia nie wystąpiło ani zbyt niskie napięcie, ani dławienie. Przy odtwarzaniu głównie w trybie Direct Play zwykle wystarcza chłodzenie pasywne, bo niczego nie trzeba wtedy ani dekodować, ani kodować.

Homelab na Raspberry Pi

  1. Raspberry Pi 4 i 5: uruchamianie systemu z dysku SSD przez zmianę bootloadera
  2. Zasilanie awaryjne (UPS) dla Raspberry Pi 4 i 5: Top 5 urządzeń do wymagających projektów
  3. Lokalny CI/CD dla Raspberry Pi: Automatyzacja wdrożeń Docker Compose
  4. Autonomiczny serwer domowy Docker-Compose z Traefik, SSL i Watchtower
  5. Lokalny serwer mediów bez opóźnień: Jellyfin na Raspberry Pi 5 z akceleracją sprzętową
Lukas Wójcik

Lukas Wójcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

Napisanie komentarza

Doświadczenia z innymi modelami i pytania o konfigurację są tu mile widziane.

Adres e-mail nie jest publikowany. Pola obowiązkowe oznaczono gwiazdką.

Artykuły i kategorie

CCTV

Śledź tę kategorię przez RSS

Cloud & AI

Wszystkie artykuły w tej kategorii (16) Śledź tę kategorię przez RSS

Data Privacy

Wszystkie artykuły w tej kategorii (18) Śledź tę kategorię przez RSS

Digital Analytics

Wszystkie artykuły w tej kategorii (58) Śledź tę kategorię przez RSS

Digital Marketing

Wszystkie artykuły w tej kategorii (37) Śledź tę kategorię przez RSS

IT & Networks

Wszystkie artykuły w tej kategorii (18) Śledź tę kategorię przez RSS

Music Production

Wszystkie artykuły w tej kategorii (17) Śledź tę kategorię przez RSS

Raspberry Pi

Śledź tę kategorię przez RSS

SaaS & Internet Earning

Śledź tę kategorię przez RSS

Smart Home

Wszystkie artykuły w tej kategorii (18) Śledź tę kategorię przez RSS

Tworzenie stron internetowych

Wszystkie artykuły w tej kategorii (11) Śledź tę kategorię przez RSS

Wtyczki i triki WordPress

Wszystkie artykuły w tej kategorii (13) Śledź tę kategorię przez RSS