Streamowanie z Lumix GH3

Dzisiejszy post jest super specyficzny do mojej sytuacji, ale może ktoś z niego skorzysta.

Problem: Chcę streamować, ale moja kamerka internetowa jest beznadziejna.

Rozwiązanie: Chcę użyć mojej profesjonalnej kamery.

Problem: Żeby podłączyć kamerę przez HDMI do komputera potrzebne jest specjalne urządzenie capture card, które kosztuje kilkaset złotych.

Rozwiązanie: Lumix GH3 ma funkcję AP, do którego może podłączyć się telefon i za pomocą aplikacji na Androida można sterować kamerą oraz mieć podgląd na żywo. Mądrzy ludzie zrobili hacka, który pozwala zasymulować komunikację [kamera - telefon] na komputerze.

I tak zaczęły się moje podboje.

Musiałem kupić sobie dodatkową kartę WiFi na USB, żeby jednocześnie móc się podłączyć do WiFi w kamerze i do internetu.

W skład hacka wchodzi aplikacja webowa, która pozwala na sterowanie kamerą oraz aplikacja w Javie wyświetlająca feed z kamery, który wysyłany jest po UDP na konkretny port. Feed jest w formie klatek JPG.

Początkowo próbowałem użyć OBS, aby streamować pulpit z okienkem Javowym. Mocno zacinało.

Pomyślałem więc “Hmm, a może by tak użyć wspomagania renderowania na GPU” i zacząłem się rozglądać czy OBS umie wykorzystać VA API.

Tak, ale w wersji beta. Więc musiałem zbudować OBS ze źródeł. Aczkolwiek to był jeden z najprzyjemniejszych buildów jakie miałem okazję zrobić, a na koniec aplikacja zarejestrowała się w dpkg.

Jednak był problem i czegoś brakowało.

Otóż brakowało mi sterownika do VA API, co było dziwne, bo mój edytor wideo z niego korzysta. Najwyraźniej mój edytor wideo ma swój własny sterownik.

Musiałem zainstalować paczkę i965-va-driver do mojego i5. Wtedy za pomocą vainfo można sprawdzić możliwości vaapi na naszej maszynie.

Jednak samo przejście z renderowania na procesorze do renderowania na GPU niewiele mi dało. Zacząłem się zastanawiać, czy problemem nie jest aby Java i to, że wyświetlam obrazki.

Więc sięgnąłem po inne rozwiązanie.

Znalazłem wirtualne urządzenie kamery zgodne z V4L2 o nazwie akvcam. Zbudowałem, zainstalowałem, skopiowałem domyślną konfigurację z wiki.

Załadowałem sterownik do kernela i utworzyły mi się urządzenia /dev/video1 i /dev/video2 - do pierwszego piszę, a drugi to wirtualna kamera.

A następnie zacząłem patrzeć jak mogę z Javy przerzucić te obrazy do urządzenia. No i wtedy odkryłem że dostaję JPGi. No i biorę tego JPGa i wrzucam go bezpośrednio na standardowe wyjście.

A tam pipe. I przesyłam te obrazki do uniwersalnego scyzoryka pod nazwą ffmpeg. Jeden z jego pluginów pozwala na sklejanie zdjęć do filmu.

java UDPServer2 | ffmpeg -framerate 25 -f image2pipe -i - -r 25 -f v4l2 -vcodec rawvideo -pix_fmt rgb24 /dev/video1

Serwuję 25 JPGów na sekundę w formacie image2pipe ze standardowego wejścia -i -, a następnie produkuję nieskompresowany obraz w formacie v4l2 i zapisuję do urządzenia kamerki.

Jeszcze musiałem zmienić konfigurację sterownika kamerki, żeby przyjmował 25 klatek na sekundę.

I śmiga… prawie.

No bo wszystko fajnie, ale jest opóźnienie wideo. Na szczęście OBS pozwolił mi opóźnić audio o 650ms, więc na streamie jest prawie zsynchronizowane.

Żeby jakość była jak najlepsza, to w ustawieniach OBS wybrałem bitrate 100000, co przekłada się na realny bitrate około 8Mbps.

I tak kończy się ta opowieść. Poniżej link do mojego forka źródeł i wideo z testem.

Lumix stream repo