Jest cała kategoria stron, w których produktem jest ruch. DJ, sala weselna, studio produkcyjne, siłownia, zespół. Pokazujesz zdjęcie i opisujesz rzecz. Pokazujesz trzy sekundy sali i tą rzeczą jesteś.
Stąd ciągle wracająca prośba „dajmy wideo w hero" i stąd to, że w praktyce prawie zawsze kończy się źle. Typowy efekt to pierwszy ekran, na który każdy musi poczekać, słabe wyniki wydajności jako rachunek za to czekanie i najmocniejszy element serwisu w roli powodu, dla którego wszystko mieli się wolno. Rozwiązaniem nie jest mniejszy plik. Rozwiązaniem jest brak pliku.
Dlaczego jeden plik każe czekać wszystkim
Wrzucenie pojedynczego MP4 do hero oznacza, że jedno kodowanie odpowiada za wszystkich odwiedzających. To zadanie niewykonalne:
Zakoduj pod monitor na biurku, a średniej klasy Android na LTE w pociągu czeka, potem czeka jeszcze chwilę, a potem coś widzi.
Zakoduj pod telefon, a materiał wygląda blado na tych ekranach, na których miał największą szansę zadziałać.
W obu przypadkach przeglądarka musi zbuforować sensowny kawałek, zanim odtwarzanie ruszy płynnie, i pobiera go z początku pliku, w pełnej jakości, niezależnie od tego, czy łącze to udźwignie.
I to jest sedno sprawy. Przy jednym pliku moment, w którym odwiedzający zobaczy ruch, jest przesądzony na etapie kodowania, przez kogoś, kto nigdy nie widział jego łącza. Wszyscy płacą to samo wpisowe w sekundach, a najdłużej płacą je ci z najsłabszym zasięgiem.
Rozdzielczość, bitrate, długość: każde pokrętło, które można przekręcić przy pojedynczym pliku, jest wyborem między dwiema grupami odwiedzających. Strumieniowanie adaptacyjne nie rozstrzyga tego wyboru, tylko go usuwa.
Czym jest dostawa adaptacyjna
Zamiast jednego pliku przygotowujesz drabinę: ten sam materiał zakodowany kilka razy, od małej wersji o niskim bitrate po Full HD. Każdą wersję tniesz na kilkusekundowe segmenty, a plik playlisty, w HLS jest to .m3u8, opisuje, co istnieje.
Zbudowanie drabiny to zadanie dla FFmpega i jego miejsce jest w pipelinie kompilacji albo przetwarzania zasobów, a nie w obsłudze żądania: uruchamia się raz na materiał, nie raz na odwiedzającego. Dokładnie tak działa portfolio, które zrobiliśmy dla DJ-a Seweryna Durczoka: koduje własne szczeble przy wdrożeniu, z tych samych nagrań z imprez, którymi cała strona sprzedaje.
Podczas odtwarzania player robi coś, czego zwykły znacznik <video> nie potrafi: mierzy rzeczywistą przepustowość w miarę pobierania segmentów i na tej podstawie wybiera wersję dla kolejnego. Przy słabym łączu zachowanie to nie „buforowanie przez sześć sekund", tylko „zejście niżej i granie dalej".
Wynikają z tego trzy rzeczy:
Odtwarzanie startuje z niskiego szczebla, więc do pierwszej klatki jest blisko. Odwiedzający czeka na jeden krótki segment, a nie na plik. Jakość rośnie później, w miarę tego, jak player rozpoznaje możliwości łącza, i nikt nie zwraca uwagi na dwie pierwsze sekundy w niższej jakości tak, jak zwraca uwagę na hero, które jeszcze nie ruszyło.
Schodzi tak samo jak wchodzi. Pasmo w sieciach komórkowych jest nie tyle niskie, co nierówne. Player, który potrafi tylko wchodzić wyżej, zatnie się przy pierwszym wejściu do windy, a zacięcie w środku hero wygląda gorzej niż wolny start, bo strona zdążyła już obiecać ruch i zaraz go zabrała.
Pobierane są wyłącznie oglądane segmenty. Ktoś, kto przewija dalej po trzech sekundach, pobrał trzy sekundy, a nie początek źródła 1080p. Przed klatką, na której ci zależy, nie stoi w kolejce nic innego.
Obraz startowy odpowiada za pierwsze wyświetlenie
Strumień skraca drogę do pierwszej klatki, ale nie skróci jej do zera, bo nawet szybki pierwszy segment dzieli od widza jedna podróż po sieci. Hero potrzebuje obrazu startowego, który utrzyma ekran przez ten czas, a ten obraz jest niemal na pewno twoim elementem Largest Contentful Paint, czyli tym, na czym mierzy się szybkość strony. To nie jest zapychacz miejsca po wideo. Potraktuj go jak pierwsze wyświetlenie, którym jest:
Podaj go jako AVIF albo WebP z zapasowym JPEG, w rozmiarze dobranym do okna przeglądarki, a nie raz na najszerszy ekran, jaki obsługujesz.
Nie ładuj go leniwie. Jest nad linią zgięcia i jest kandydatem na LCP, a
loading="lazy"na nim to najczęstszy sposób, w jaki zespoły same przesuwają sobie LCP o sekundę.Leniwe niech zostanie samo wideo. Obraz się rysuje, strumień rusza, a przejęcie następuje w momencie, w którym pierwszy segment da się zdekodować.
Dopasuj obraz startowy do pierwszej klatki. Jeśli widocznie się różnią, przejęcie wygląda jak usterka, a nie jak początek odtwarzania.
Przy właściwej kolejności wideo przestaje rywalizować z Core Web Vitals, bo mierzonym elementem jest obraz, nad którym masz pełną kontrolę, a strumień dochodzi za nim, a nie przed nim. Odwiedzający dostaje obraz, potem ruch, zamiast niczego, a potem wszystkiego naraz.
Obraz startowy jest też całym hero dla dwóch grup odwiedzających, które z góry dały ci znać, że wideo sobie odpuszczą. Oba sygnały są tanie w obsłudze i notorycznie pomijane:
prefers-reduced-motionto prośba o dostępność, a nie przełącznik preferencji. Uszanuj ją, pokazując obraz startowy i nie odtwarzając materiału automatycznie.Save-Data, a tam, gdzie jest dostępna, również preferencja ograniczonego transferu, mówi ci, że odwiedzający jest na łączu albo pakiecie, przy którym twoje hero nie jest priorytetem. Za pobrane segmenty ktoś płaci, a osoba, która prosi, żeby nie zużywać jej pakietu, mówi to wprost. Pokaż obraz startowy, a odtworzenie zostaw jako świadomy wybór.
Safari i cała reszta
Safari i iOS odtwarzają HLS natywnie. Wystarczy podać elementowi <video> adres .m3u8 i działa, razem z własną logiką adaptacyjną platformy. Cała reszta potrzebuje playera w JavaScripcie, standardowo HLS.js, który przez Media Source Extensions sam podaje segmenty do elementu wideo.
Czyli: najpierw sprawdzasz natywne wsparcie dla HLS, używasz go tam, gdzie jest, a bibliotekę playera ładujesz tylko tam, gdzie go nie ma. Ładowanie jej bezwarunkowo to wysłanie paczki kodu do użytkowników iOS, których przeglądarka i tak by jej nie potrzebowała, i postawienie tej paczki na ścieżce krytycznej przed hero, którego cały sens polegał na tym, żeby ruszać szybko.
Kiedy warto
Nie zawsze. Trzysekundowa pętla abstrakcyjnego gradientu nie potrzebuje drabiny bitrate'ów, tylko mniejszego pliku albo animacji.
Warto wtedy, kiedy to materiał jest argumentem: kiedy osoba decydująca, czy cię zatrudnić, decyduje na podstawie tego, jak wygląda sala. Wideo nie jest wtedy ozdobą, która musi się obronić ze swojej wagi. Jest stroną, a jedyny dopuszczalny czas czekania na stronę to tyle, ile wymusza sieć, i ani sekundy więcej.
Warto nie znaczy jednak, że musisz zbudować to sam. Platforma wideo przygotuje i wyhostuje drabinę za ciebie, a wszystko powyżej, czyli obraz startowy, odroczony player i ścieżka dla ograniczonej animacji, i tak zostaje po twojej stronie. Tą drogą poszliśmy przy stronie iShots Wedding, gdzie showreel jest całą ofertą, a kodowanie nigdy nie miało być tym ciekawym fragmentem.