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.