µStreamer é um servidor leve e muito rápido para transmitir vídeo MJPEG de qualquer dispositivo V4L2 para a rede. Todos os novos navegadores têm suporte nativo para este formato de vídeo, assim como a maioria dos reprodutores de vídeo, como mplayer, VLC etc. µStreamer faz parte do projeto PiKVM projetado para transmitir dados de hardware de screencast VGA e HDMI com a mais alta resolução e FPS possível.
µStreamer é muito semelhante ao mjpg-streamer com plug-ins input_uvc.so
e output_http.so
, no entanto, existem algumas diferenças importantes. Os principais são:
Recurso | µStreamer | streamer mjpg |
---|---|---|
Codificação JPEG multithread | ✔ | ✘ |
Codificação de imagem de hardware no Raspberry Pi | ✔ | ✘ |
Comportamento quando o dispositivo é desconectado durante a transmissão | ✔ Mostra uma tela preta sem NO SIGNAL neleaté reconectar | ✘ Interrompe a transmissão 1 |
Suporte para horários DV - a capacidade de alterar a resolução em tempo real pelo sinal da fonte | ✔ | ☹ Parcialmente sim 1 |
Opção para pular frames durante a transmissão imagens estáticas por HTTP para economizar o tráfego | ✔2 | ✘ |
Streaming via soquete de domínio UNIX | ✔ | ✘ |
Ativação do soquete Systemd | ✔ | ✘ |
Depurar logs sem recompilar, registro de estatísticas de desempenho, acesso aos parâmetros de streaming HTTP | ✔ | ✘ |
Opção para servir arquivos com um servidor HTTP integrado | ✔ | ☹ Somente arquivos regulares |
Sinalização sobre o estado do stream no GPIO usando libgpiod | ✔ | ✘ |
Acesso aos controles da webcam (foco, servos) e configurações como brilho via HTTP | ✘ | ✔ |
Compatibilidade com API do mjpg-streamer | ✔ | :) |
Notas de rodapé:
1
Muito antes do µStreamer, fiz um patch para adicionar suporte a tempos de DV ao mjpg-streamer e evitar que ele desligasse ao desconectar o dispositivo. Infelizmente, o patch está longe de ser perfeito e não posso garantir que funcionará sempre - o código-fonte do mjpg-streamer é muito complicado e sua estrutura é difícil de entender. Com isso em mente, além de precisar de multithreading e aceleração de hardware JPEG no futuro, decidi criar meu próprio servidor de stream do zero, em vez de oferecer suporte a código legado.
2
Este recurso permite reduzir várias vezes o tráfego de saída ao transmitir HDMI, mas aumenta um pouco o uso da CPU. A ideia é que o HDMI seja uma interface totalmente digital e cada quadro capturado possa ser idêntico ao anterior em termos de bytes. Não há necessidade de transmitir a mesma imagem pela rede várias vezes por segundo. Com a opção --drop-same-frames=20
habilitada, o µStreamer irá descartar todos os frames correspondentes (com um limite de 20 seguidos). Cada novo quadro é combinado com o anterior primeiro por comprimento e depois usando memcmp()
.
Se você for transmitir ao vivo da webcam do seu quintal e precisar controlá-la, use mjpg-streamer. Se você precisa de uma imagem de alta qualidade com FPS alto - µStreamer para a vitória.
Você precisa baixar o µStreamer em seu sistema e construí-lo a partir das fontes.
Você precisará make
, gcc
, libevent
com suporte pthreads
, libjpeg9
/ libjpeg-turbo
e libbsd
(somente para Linux).
sudo pacman -S libevent libjpeg-turbo libutil-linux libbsd
.sudo apt install libevent-dev libjpeg62-turbo libbsd-dev
. Adicione libgpiod-dev
para WITH_GPIO=1
e libsystemd-dev
para WITH_SYSTEMD=1
e libasound2-dev libspeex-dev libspeexdsp-dev libopus-dev
para WITH_JANUS=1
.libjpeg62-turbo
por libjpeg62-turbo-dev
.sudo apt install build-essential libevent-dev libjpeg-dev libbsd-dev
.sudo apk add libevent-dev libbsd-dev libjpeg-turbo-dev musl-dev
. Construa com WITH_PTHREAD_NP=0
. Para ativar o suporte GPIO, instale libgpiod e passe a opção WITH_GPIO=1
. Se o compilador relatar uma função ausente pthread_get_name_np()
(ou similar), adicione a opção WITH_PTHREAD_NP=0
(está habilitada por padrão). Para o erro semelhante com setproctitle()
adicione a opção WITH_SETPROCTITLE=0
.
O processo mais conveniente é clonar o repositório µStreamer Git em seu sistema. Se você não tem o Git instalado e também não deseja instalá-lo, você pode baixar e descompactar os fontes do GitHub usando wget https://github.com/pikvm/ustreamer/archive/refs/heads/master.zip
.
$ git clone --depth=1 https://github.com/pikvm/ustreamer
$ cd ustreamer
$ make
$ ./ustreamer --help
Supondo que você tenha um clone do µStreamer conforme discutido acima, você pode atualizar o µStreamer da seguinte maneira.
$ cd ustreamer
$ git pull
$ make clean
$ make
Para codificação de hardware M2M no Raspberry Pi, você precisa de pelo menos o kernel 5.15.32. O suporte OpenMAX e MMAL em kernels mais antigos está obsoleto e removido.
Sem argumentos, ustreamer
tentará abrir /dev/video0
com resolução de 640x480 e iniciar o streaming em http://127.0.0.1:8080
. Você pode substituir esse comportamento usando os parâmetros --device
, --host
e --port
. Por exemplo, para transmitir para o mundo, execute:
# ./ustreamer --device=/dev/video1 --host=0.0.0.0 --port=80
❗ Observe que desde que as solicitações entre domínios do µStreamer v2.0 foram desativadas por padrão por motivos de segurança. Para ativar o comportamento antigo, use a opção --allow-origin=*
.
A maneira recomendada de executar o µStreamer com dispositivo de captura baseado em TC358743 no Raspberry Pi:
$ ./ustreamer
--format=uyvy # Device input format
--encoder=m2m-image # Hardware encoding on V4L2 M2M driver
--workers=3 # Workers number
--persistent # Suppress repetitive signal source errors (for example when HDMI cable was disconnected)
--dv-timings # Use DV-timings
--drop-same-frames=30 # Save the traffic
❗ Observe que para usar --drop-same-frames
para navegadores diferentes você precisa usar alguns parâmetros de URL /stream
específicos (veja URL /
para detalhes).
Você sempre pode ver a lista completa de opções com ustreamer --help
.
Adicione as seguintes linhas a /boot/firmware/usercfg.txt:
gpu_mem=128
dtoverlay=tc358743
Verifique o tamanho do CMA:
$ dmesg | grep cma-reserved
[ 0.000000] Memory: 7700524K/8244224K available (11772K kernel code, 1278K rwdata, 4320K rodata, 4096K init, 1077K bss, 281556K reserved, 262144K cma-reserved)
Se for menor que 128M, adicione o seguinte a /boot/firmware/cmdline.txt:
cma=128M
Salve as alterações e reinicie.
Iniciar contêiner:
$ docker run --device /dev/video0:/dev/video0 -e EDID=1 -p 8080:8080 pikvm/ustreamer:latest
Em seguida, acesse a interface web na porta 8080 (por exemplo, http://raspberrypi.local:8080).
$ docker run --rm pikvm/ustreamer:latest
--format=uyvy
--workers=3
--persistent
--dv-timings
--drop-same-frames=30
Adicione -e EDID=1
para definir HDMI EDID antes de iniciar o ustreamer. Use junto com -e EDID_HEX=xx
para especificar dados EDID personalizados.
Exemplo de uso para a câmera Raspberry Pi v3 ( libcamerify
necessário, localizado em libcamera-tools
e libcamera-v4l2
(instale ambos) no Raspbian):
$ sudo modprobe bcm2835-v4l2
$ libcamerify ./ustreamer --host :: --encoder=m2m-image
Para a câmera v2, você pode usar o mesmo truque com libcamerify
, mas ativar o modo de câmera legado em raspi-config
.
Exemplo de uso da câmera Raspberry Pi v1:
$ sudo modprobe bcm2835-v4l2
$ ./ustreamer --host :: -m jpeg --device-timeout=5 --buffers=3 -r 2592x1944
❗ Observe que os modelos de câmeras mais recentes têm uma resolução máxima diferente. Você pode ver as resoluções suportadas na documentação do PiCamera.
❗ Se você obtiver uma taxa de quadros baixa, pode ser que a câmera esteja no modo foto, o que produz uma taxa de quadros baixa (mas uma imagem de qualidade superior). Isso ocorre porque bcm2835-v4l2
muda para o modo foto em resoluções superiores a 1280x720
. Para contornar isso, passe os parâmetros do módulo max_video_width
e max_video_height
assim:
$ modprobe bcm2835-v4l2 max_video_width=2592 max_video_height=1944
µStreamer oferece suporte a streaming com eficiência de largura de banda usando compactação H.264 e o servidor Janus WebRTC. Consulte o guia de integração do Janus para obter detalhes completos.
Quando o uStreamer está atrás de um proxy Nginx, seu comportamento de buffer introduz latência no stream de vídeo. É possível desabilitar o buffer do Nginx para eliminar a latência adicional:
location /stream {
postpone_output 0;
proxy_buffering off ;
proxy_ignore_headers X-Accel-Buffering;
proxy_pass http://ustreamer;
}
Os utilitários v4l2 fornecem as ferramentas para gerenciar configurações e informações da webcam USB. Os scripts podem ser usados para fazer ajustes e executar manualmente ou com cron. Executar no cron, por exemplo, para alterar as configurações de exposição em determinados horários do dia. O pacote está disponível em todas as distribuições Linux e geralmente é chamado de v4l-utils
.
v4l2-ctl --list-devices
.v4l2-ctl -d /dev/video0 --list-ctrls
.v4l2-ctl -d /dev/video0 --list-formats-ext
.v4l2-ctl -d /dev/video0 --get-ctrl=exposure_auto
.v4l2-ctl -d /dev/video0 --set-ctrl=exposure_auto=1
. Aqui você pode encontrar mais exemplos. A documentação está disponível em man v4l2-ctl
.
Copyright (C) 2018-2024 por Maxim Devaev [email protected]
Este programa é software livre: você pode redistribuí-lo e/ou modificá-lo sob os termos da Licença Pública Geral GNU conforme publicada pela Free Software Foundation, seja a versão 3 da Licença ou (a seu critério) qualquer versão posterior.
Este programa é distribuído na esperança de que seja útil, mas SEM QUALQUER GARANTIA; mesmo sem a garantia implícita de COMERCIALIZAÇÃO ou ADEQUAÇÃO A UM DETERMINADO FIM. Veja a Licença Pública Geral GNU para mais detalhes.
Você deverá ter recebido uma cópia da Licença Pública Geral GNU junto com este programa. Caso contrário, consulte https://www.gnu.org/licenses/.