Streamowanie z Raspberry Pi do YouTube’a ale tylko wtedy gdy ktoś ogląda [Out Of the box Project]

Wstęp

W tym projekcie pokażę jak streamować obraz z kamery USB podpiętej do Raspberry Pi do YouTube’a. Streamowanie nie będzie ciągłe – kamera będzie włączona i streamowała do YouTube’a tylko wtedy, gdy ktoś otworzy stronę z oknem  YouTube’a.

 Co będzie potrzebne

  • Kamera USB – ja używam modelu A4Tech PK-910H – przed kupnem kamery należy sprawdzić czy będzie ona działała z Rasbianem
  • Raspberry Pi – ja używam RPI4 z 4GB Ramu, testowałem też na RPI3(poniżej screen z Rpi4  htop przy streamowaniu obrazu o rozdzielczości 1280x720   jak widać rdzenie procesora są wykorzystane w 36% na jednym rdzeniu)
  • Radiator na Procesor Raspberry Pi – streaming potrafi nieźle “zmęczyć” Raspberry Pi dlatego radiator jest potrzebny, ja używam Flirc Raspberry Pi 4 Case (Silver)

    jest to aluminiowa obudowa która pełni jednocześnie role radiatora. Przy jej wykorzystaniu temperatura procesora to około 45C przy temperaturze zewnętrznej 24C . Więcej o tej obudowanie na filmie Pana Andreas Spiessa    jedyne zastrzeżenie jakie mam do tej obudowy to takie, że brak jest wyprowadzenia na taśmę od kamery podpiętej bezpośrednio w płytkę RPI, oraz to aby wyprowadzić PINY taśmą 40pinową potrzebne jest spiłowanie boków wtyczki taśmy

Jak to będzie działać

Aby rozpocząć stream będzie uruchamiana komenda:

ffmpeg -threads 0 -f v4l2 -i /dev/video0 -ar 44100 -ac 2 -acodec pcm_s16le -f s16le -ac 2 -i /dev/zero -acodec aac -ab 128k -strict experimental -s 1280x720 -b 6000000 -aspect 16:9 -vcodec h264_omx -vb 820k -pix_fmt yuv420p -g 60 -r 30 -f flv rtmp://a.rtmp.youtube.com/live2/SECRET_KEY

oczywiście wcześniej trzeba zainstalować ffmpeg jeżeli nie mamy (sudo apt-get install ffmpeg )

skrypt ten będzie uruchamiany gdy nasza strona internetowa z ramką z YouTube’a będzie wyświetlana przez co najmniej jedną osobę, gdy strona zostanie zamknięta i nie zostanie ponownie otworzona w przeciągu 10 sekund skrypt zostanie ‘ubity’ kamerka się wyłączy i nie będzie streamować do YouTube’a.

Ponieważ tak naprawdę będziemy tworzyć za każdym razem nowy stream, iframe  z adresem streamu musi wskazywać nie na określony stream tylko na aktywny stream danego użytkownika czyli:

https://www.youtube.com/embed/live_stream?channel=CHANNEL_ID&autoplay=1

Wymusza to też żeby nasze streamy były publiczne

 

Do dzieła 🙂

tak naprawdę żeby uruchomić projekt wystarczy parę klików – ponieważ ten projekt jest już w zakładce quick projects (https://app.remoteme.org/en/#/app/quickstart)

klikamy “read more or build it” przy projekcie:

następnie w zakładce Build It :

uzupełniamy YouTube stream name/key, który pobieramy z YouTube’a pod adresem https://www.youtube.com/live_dashboard

będzie on miał postać podobną do : 7awp-w65c-zbas-61c9 -możecie jednak wpisać cokolwiek i potem uzupełnić na prawidłowy secret key w pliku youtuberun.sh

Gdy wcześniej nic nie streamowaliśmy musimy aktywować usługę – aktywacja trwa do 24h dopiero wtedy będziemy mogli zacząć streaming

Channel id pobieramy z adresu https://www.youtube.com/account_advanced

w moim przypadku to  ZCPuP7AKof_poZY664N4yJCA

po uzupełnieniu

następnie klikamy Next step – wybieramy albo dodajemy Raspberry Pi ( w razie problemów odsyłam do artykułu o RaspberryPi w RemoteMei o urządzeniach pythonowych w RemoteMe ) , następnie next step i zielony przycisk “build the project” i po poprawnym utworzeniu projektu zamykamy okno.

Co się stało

Została utworzona strona , dodany skrypt pythonowy:

stronę możemy otworzyć, żeby zobaczyć czy wszystko  działa:

po otwarciu zobaczymy stronę gdzie po chwili pojawi się obraz ze streamingu.

Jak to dokładnie działa (i co zrobić jak obraz się nie wyświetla)

Zacznijmy od omówienia plików w urządzeniu python script:

1) youtuberun.sh – po otwarciu widzimy polecenie ffmpeg:

ffmpeg -threads 0 -f v4l2 -i /dev/video0 -ar 44100 -ac 2 -acodec pcm_s16le -f s16le -ac 2 -i /dev/zero -acodec aac -ab 128k -strict experimental -s 1280x720 -b 6000000 -aspect 16:9 -vcodec h264_omx -vb 820k -pix_fmt yuv420p -g 60 -r 30 -f flv rtmp://a.rtmp.youtube.com/live2/SECRET_KEY

jak obraz nie streamuje się do YouTube polecam uruchomić to polecenie bezpośrednio w konsoli i sprawdzić logi może się okazać, że nie mamy zainstalowanego ffmpeg (wtedy instalujemy poprzez wywołanie sudo apt-get install ffmpeg ) albo nasza kamera jest pod innym adresem niż /dev/video0( wtedy edytujemy plik i zapisujemy ), w pliku tym możemy też zmienić parametry naszego strumienia wysyłanego do YouTube – podgląd streama znajduje się pod adresem : https://www.youtube.com/live_dashboard

2) python.py jest bardziej skomplikowany – żeby zrozumieć jak działa pamiętajcie, że nasza strona internetowa ma id 2:

oraz, że wartość zmiennej youtube_state (o zmiennych w RemoteMe ) przetrzymuje aktualny stan streamu YouTube’a i jest to:

-1:Youtube FAIL
0:Youtube OFF
1: Youtube ON
2:Youtube STARTING
3:Youtube CLOSING

omówię teraz poszczególne części kodu pliku python.py

ponieważ chcemy włączyć streaming wtedy jak nasza strona o deviceId=2 się podłączy – ustawiamy funkcję onDeviceConnectionChangedo wywołania jak jakiekolwiek urządzenie zmieni stan połączenia z platformą RemoteMe – a w samej funkcji filtrujemy tylko zmiany statusu dla urządzenia o id 2 (bo to deviceId naszej strony internetowej ), następnie aktualny stan zapisujemy do zmiennej globalnej receiveDeviceConnected

odczyt stanu zmiennej następuje w osobnym wątku którego kod wygląda następująco:

funkcja ma nieskończona pętle która sprawdza czy urządzenie jest podłączone i w zależności jaki był poprzedni stan włącza streaming albo po 10 sekundach od odłączenia strony internetowej zamyka streaming.

Streaming włącza funkcja

która uruchamia skrypt youtuberun.sh w osobnym wątku, a funkcja:
wywołuje polecenie pkill na naszym wątku – żeby go zakończyć wraz z jego wątkami “dziećmi” (wtedy kamerka się wyłącza i nic już nie streamujemy)

dodatkowo obie funkcje ustawiają zmienne youtube_state poprzez wywołanie funkcji:

wartość zmiennej youtube_state  jest odczytywana przez stronę internetową (omówione poniżej) i wyświetla odpowiedni komunikat użytkownikowi – wstrzykuje kod iframe’a z podglądem YouTube.

funkcją wartą omówienia jest też funkcja:

sprawdza ona poprzez skanowanie wyjścia skryptu youtuberun.sh czy pojawił się napis “speed=” w przeciągu 40s jeżeli tak oznacza to że nasz ffmpeg poprawnie nadaje streaming, jeżeli nie oznacza to, że coś poszło nie tak i ustawiana jest odpowiednia wartość zmiennej youtube_state

Dodatkowo python.py sprawdza temperaturę naszej malinki i ustawia zmienna cpu_temp która jest wyświetlana na stronie z transmisją.

Co się dzieje w stronie internetowej

tutaj znajdziecie dokładny opis czym jest strona internetowa w RemoteMe, a tutaj dodane komponenty RemoteMe

a dokładniej w pliky script.js bo jedynie on wymaga objaśnień:

w części:

sprawdzamy czy nasze RPI jest podłączone jeżeli tak wywołujemy funkcję

funkcja ta wyświetla użytkownikowi powiadomienia, oraz gdy YouTube jest aktywnie włączony wstrzykuje ramkę YouTube’a do htmla:

    $("#youtubeContainer").html(<iframe width="100%" height="100%" src="https://www.youtube.com/embed/live_stream?channel=CHANELID&autoplay=1" frameborder="0" allowfullscreen></iframe>);

dzieje się to jednak tylko wtedy gdy aktywny status transmisji jest pierwszym otrzymanym – w przeciwnym razie odświeżamy stronę po 10 sekundach ( z niewiadomych mi przyczyn takie rozwiązanie okazuje się lepsze niż po prostu wstrzyknięcie ramki YouTube) – wtedy pierwszym stanem otrzymanym jest własnie stan aktywny (ustawiony przez stronę przed odświeżeniem, a ponieważ Python czeka 10 sekund po odłączeniu strony nie zdąży wyłączyć transmisji) i  wstrzykujemy ramkę.

Problemy które zauważyłem

Niekiedy ( nie mogę określić dokładnego scenariusza ) ramka YouTube pokazuje nagranie poprzedniej transmisji – wtedy pomaga odświeżenie strony, lub trzeba usunąć nagrane transmisje bezpośrednio w YouTube. W funkcji stopYoutube w Python polecenie pkill jest wywoływane trzykrotnie – niekiedy pierwsze wywołanie nie uśmierca wątku.

Zakończenie

Mam nadzieję ze projekt okaże się przydatny, i dzięki niemu dacie wytchnąć Waszym kamerkom i łączom internetowym 🙂 . Jeżeli macie pomysł na ulepszenie skryptów piszcie na Facebooku projektu. Przypominam, że jest dokumentacja bilbiotek  remoteMe gdzie znajdziecie opis funkcji JavaScript, Python i ESP  z których korzystam w moich przykładach