STREAMING ACELERADO POR GPU USANDO WEBRTC


Neste documento, descrevemos e discutimos os componentes de uma solução de streaming interativo baseada na Web para cargas de trabalho com muitos gráficos. Use essa solução de streaming para criar apps de área de trabalho remota de uso geral ou fazer streaming de apps separados.

Este documento é um complemento de Como orquestrar apps de streaming acelerados por GPU usando WebRTC. Ele é destinado a um público técnico com responsabilidades que incluem criação, escalonamento e implantação de soluções personalizadas com base em streaming. Para este documento, consideramos que você já conheça os conceitos básicos de streaming e área de trabalho remota, sem precisar ser um especialista.

Introdução

Normalmente, as cargas de trabalho com muitos gráficos não são executadas sem problemas em plataformas com baixo consumo de energia, CPU e GPU. Uma solução para esse problema é fazer streaming do conteúdo para um navegador da Web usando o WebRTC e o GStreamer (em inglês) para acessar as GPUs disponíveis para codificação de hardware ou decodificação de streams em tempo real.

Veja alguns exemplos de casos de uso:

  • Configuradores de produtos renderizados em tempo real para os setores de varejo e automotivo
  • Visualização remota interativa de grandes conjuntos de dados para setores científicos
  • Streaming de jogos acelerado para um navegador da Web
  • Estações de trabalho virtuais leves e de baixo custo para criadores de conteúdo VFX, animação ou design

O problema

A tecnologia de streaming de código aberto não observou um grande aumento em desempenho em vários anos. Ferramentas como Virtual Network Computing (VNC) e Remote Desktop Protocol (RDP) ainda são muito usadas para a maioria das soluções de área de trabalho remota pela Internet. Infelizmente, esses protocolos não são adequados para o navegador da Web moderno, exigem que os usuários façam o download de um cliente e são difíceis de proteger e configurar em redes protegidas por firewall.

As soluções como Guacamole e noVNC (links em inglês) oferecem experiência baseada na Web para VNC e RDP, mas elas não atendem ao desempenho e requisitos de latência de cargas de trabalho com uso intensivo de gráficos, como renderização em 3D, visualização de dados e jogos. A maioria desses aplicativos tem uma expectativa de utilização de pelo menos 30 fps com 1080p, o que é difícil de conseguir sem suporte à GPU. Muitas GPUs modernas conseguem codificar um stream em tempo real no hardware. Isso pode melhorar muito o desempenho de tecnologias de streaming, reduzindo o uso de CPU e a largura de banda necessária para fornecer conteúdo. Infelizmente, a maioria das soluções de código aberto baseadas nos protocolos VNC e RDP não são compatíveis com a codificação de hardware.

Veja na tabela a seguir uma comparação dos recursos mais comuns de streaming de código aberto.

SoluçãoCom base na WebCodificação de hardwareDecodificação de hardware
VNCNãoNãoNão
RDPNãoNãoNão
GuacamoleSimNãoTela HTML5
NoVNCSimNãoTela HTML5

Existem ferramentas de área de trabalho remota disponíveis no mercado, como PCoIP da Teradici ou HDX da Citrix (links em inglês), mas, neste artigo, exploramos uma solução de código aberto baseada na Web que pode ser personalizada conforme seu caso de uso específico.

A solução

O WebRTC é um conjunto moderno de protocolos projetados para streaming seguro de baixa latência de vídeo, áudio e dados arbitrários. Navegadores e plataformas da Web modernos podem decodificar streams de vídeo H.264 sem plug-ins extras. Se o cliente tiver uma GPU local com decodificação de vídeo de hardware, o WebRTC usará automaticamente a GPU para acelerar a decodificação do stream, o que descarrega o trabalho da CPU e melhora os frame rates. O elemento de vídeo (em inglês) HTML5 é o único elemento de marcação necessário e permite streaming de conteúdo in-line com os sites atuais, streaming de um único app ou casos de uso de área de trabalho remota em tela cheia.

O WebRTC inclui os seguintes recursos principais:

  • Suporte a navegadores nativos
  • Formatos acelerados por hardware
  • Criptografia integrada por padrão
  • Comunicação ponto a ponto
  • Capacidade de transferir gateways e firewalls NAT

O WebRTC é muito mais complexo que as soluções VNC e RDP, mas ele é uma das únicas opções atualmente disponíveis que permitem um frame rate elevado e um streaming de largura de banda baixa em um navegador da Web.

As tecnologias de exemplo que usam WebRTC incluem o seguinte:

O GStreamer é uma ferramenta de código aberto para a criação de pipelines de streaming. Ele é compatível com muitas fontes, formatos e coletores e inclui suporte para WebRTC. Neste documento, mostramos como usar a ferramenta GStreamer e o codificador de vídeo de hardware da NVIDIA (NVENC, na sigla em inglês) para fazer streaming de cargas de trabalho aceleradas a um navegador da Web.

Arquitetura de referência

É possível implantar uma pilha de streaming WebRTC de uso geral no Google Cloud e disponibilizá-la para usuários individuais. Use o Identity-Aware Proxy (IAP) para autenticar usuários no Cloud Load Balancing. As solicitações autenticadas são enviadas a um agente de instâncias, que atribui os usuários a uma instância do Compute Engine que está executando a pilha de streaming WebRTC na região mais próxima deles. Depois que a sessão de sinalização autenticada é estabelecida, os usuários se conectam diretamente à instância WebRTC e aos servidores STUN/TURN (links em inglês) usando a conexão ponto a ponto.

Pilha de streaming do WebRTC de uso geral implantada no Google Cloud.

O vídeo a seguir mostra uma comparação lado a lado do mesmo servidor X11 sendo transmitido com WebRTC e noVNC por uma conexão de Internet de banda larga. O vídeo mostra uma diferença perceptível no frame rate e no desempenho. Neste exemplo, a resolução de streaming é 1920 x 1080 (1080p), e o NVENC está codificando para H.264 a 8 Mbps, e o noVNC envia imagens PNG compostas em um elemento de tela HTML5 sobre um WebSocket.https://www.youtube.com/embed/XWqb3iTs1Iw?hl=pt-br

Quando usar o WebRTC

O WebRTC é melhor quando a latência do navegador da Web do cliente é essencial para o aplicativo. O chat por vídeo e o software de conferências são alguns dos casos de uso mais comuns. WebRTC é menos eficaz para streaming tolerante a latência, como envio de conteúdo de vídeo pré-gravado ou renderizado. O perfil H.264 para WebRTC não é compatível com a codificação sem perdas. Se você precisar de formatos sem perdas, pense em outras soluções, como PCoIP da Teradici.

Use o WebRTC para qualquer uma das seguintes finalidades:

  • Entrega de áudio e vídeo de baixa latência em um navegador ou dispositivo móvel
  • Streaming de baixa latência de dados binários ou eventos, como entradas de teclado, mouse ou gamepad
  • Streaming de jogos para navegador ou dispositivo móvel

Não use o WebRTC para qualquer uma das seguintes finalidades:

  • Distribuição em grande escala de mídia pré-gravada ou renderizada
  • Streaming de formatos de vídeo não compatíveis com navegadores modernos
  • Compatibilidade com navegadores mais antigos

Principais conceitos

Nesta seção, apresentamos a terminologia útil e algumas informações sobre travessia de rede, handshakes de conexão e criptografia de conexão com DTLS.

Terminologia

Como ele consiste em vários protocolos e tecnologias, o WebRTC pode ser bastante complexo. Grande parte dessa complexidade é abstraída das APIs do navegador da Web. No entanto, recomendamos que você se familiarize com a terminologia a seguir.Datagram Transport Layer Security (DTLS) (em inglês)Uma implementação da especificação Transport Layer Security que pode ser usada com o protocolo de datagrama do usuário (UDP, na sigla em inglês). O WebRTC requer que todos os dados sejam criptografados em trânsito e use DTLS para proteger a transmissão de dados.Estabelecimento de conectividade interativa (ICE, na sigla em inglês)Método usado pelo WebRTC para descobrir a melhor maneira de criar uma conexão ponto a ponto. Os pares trocam candidatos ICE que são negociados e priorizados até que um método de conexão comum seja acordado.RTCPeerConnection (em inglês)O objeto JavaScript usado para criar uma conexão WebRTC. A fonte JavaScript do adaptador WebRTC (em inglês) oferece uma interface padrão para que você não precise criar código personalizado para cada implementação específica do navegador.Protocolo de descrição de sessões (SDP, na sigla em inglês)Configuração de mídia e conexão e recursos trocados por pares durante o estabelecimento da conexão.Utilitários de travessia de sessão para NAT (STUN, na sigla em inglês)Um serviço externo usado por pares para descobrir o endereço IP externo real se estiverem protegidos por um firewall ou gateway NAT.sinalização (em inglês)Um serviço externo usado por conexões de peering que não está incluído na especificação WebRTC, mas é necessário para o estabelecimento da conexão. Não há uma especificação formal para a sinalização, mas é comum usar o WebSocket ou o Extensible Messaging and Presence Protocol (XMPP) (links em inglês).Travessia por redirecionamentos via NAT (TURN, na sigla em inglês)Um serviço externo usado como redirecionamento por pares se nenhum método de conexão ponto a ponto direta puder ser descoberto durante a negociação de candidatos ICE.

Travessia de rede

O WebRTC usa a travessia de rede para criar conexões de peering entre gateways e firewalls NAT. O WebRTC tenta estabelecer uma conexão de peering usando os seguintes métodos:

  • Host: rede preferencial, rede local ou endereço IP externo conectado à Internet.
  • Servidor reflexivo: recebido por meio do protocolo STUN para descobrir o endereço IP externo real do par se o terminal estiver protegido por um firewall ou gateway NAT.
  • Redirecionamento: todo o tráfego entre pares é redirecionado por um servidor comum. Usado quando a conexão ponto a ponto direta por meio do método host ou servidor reflexivo falha.

Servidores STUN são leves e econômicos para operar. O Google tem vários servidores STUN públicos que não estão restritos para uso:

  • stun.l.google.com:19302
  • stun1.l.google.com:19302
  • stun2.l.google.com:19302
  • stun3.l.google.com:19302
  • stun4.l.google.com:19302

No entanto, esses servidores não têm garantia de disponibilidade ou tempo de atividade do serviço.

Embora o STUN funcione para a maioria do tráfego WebRTC, aproximadamente 30% das conexões exigem um servidor TURN (em inglês). Neste documento, usamos o projeto de código aberto coTURN (em inglês) para STUN e TURN. Por definição, todos os servidores TURN também funcionam como servidores STUN (em inglês).

Você precisa de um servidor TURN credenciado para usar o WebRTC no navegador com o objeto RTCPeerConnection. O coTURN oferece uma API REST integrada que usa credenciais de código de autenticação de mensagens baseado em hash (HMAC, na sigla em inglês) com tempo limitado que seguem a especificação IETF (em inglês).

O projeto coTURN não tem uma API JSON integrada para gerar a configuração RTCPeerConnection (em inglês):

{  "lifetimeDuration": "86400s",  "iceServers": [    {      "urls": [        "stun:1.2.3.4:3478"      ]    },    {      "urls": [        "turn:1.2.3.4:3478?transport=udp",        "turn:1.2.3.4:3478?transport=tcp"      ],      "username": "1562254295-webrtc",      "credential": "6JdlETxsKPBoWCPJSCwEeVHD6B8="    }  ],  "blockStatus": "NOT_BLOCKED",  "iceTransportPolicy": "all"}

É possível gerar a credencial HMAC e o arquivo de configuração JSON esperado gravando um serviço da Web simples usando a linguagem de programação Go e o módulo crypto/hmac (em inglês). A função makeCredentials usa um secret compartilhado ao gerar a credencial HMAC. Esse secret também é usado ao configurar o coTURN. É necessário definir o separador de API REST do coTURN como um caractere de traço “-” em vez dos dois pontos padrão “:” porque o GStreamer tem um problema na análise de URIs do servidor TURN que usam o separador dois pontos:images/gst-webrtc-app/main.pyVer no GitHub

# Fetch the turn server and credentialsstun_server, turn_server = fetch_coturn(    args.coturn_web_uri, args.coturn_web_username, args.coturn_auth_header_name)# Create instance of appapp = GSTWebRTCApp(stun_server, turn_server, args.enable_audio == "true", int(args.framerate))

Handshake de conexão

Quando você quiser criar uma conexão WebRTC, use um servidor de sinalização para trocar os SDP e os candidatos ICE necessários para estabelecer uma conexão de peering. Depois que a conexão de peering é estabelecida, o servidor de sinalização não é mais necessário. No diagrama a seguir, mostramos esse processo.

Configuração de um handshake de conexão.

Criptografia de conexão com DTLS

O WebRTC exige que todos os dados sejam criptografados em trânsito. O protocolo Transport Layer Security (TLS) (em inglês) requer TCP e não pode ser usado com WebRTC. Para resolver isso, o WebRTC usa o Datagram Transport Layer Security (DTLS) (em inglês), que é uma implementação da especificação TLS, mas compatível com UDP. A troca de certificados e o handshake de TLS são processados pela implementação do navegador do WebRTC. Protocolos anteriores, como VNC, não incluíam ou exigiam criptografia de conexão, e era responsabilidade do desenvolvedor e das operações implantar uma solução segura. O WebRTC resolve esse problema tornando-o obrigatório e incluindo uma solução integrada com o DTLS.

Pipeline do GStreamer

No diagrama a seguir, o GStreamer atua como mecanismo de streaming e estabelece interface com os componentes necessários, como captura de X11, sinalização, STUN/TURN, entradas dos usuários da interface da Web e GPU NVIDIA.

Arquitetura no nível do componente do app.

O GStreamer tem um modelo de processamento baseado em pipeline (em inglês). Cada elemento no pipeline pode atuar como uma origem ou um coletor. Os elementos têm pads que expõem recursos. Os pads são usados para negociar links entre elementos com base nos recursos deles. Os buffers são emitidos do pad de origem de um elemento para o pad de coletor de outro elemento.

O streaming da tela X11 para o navegador com WebRTC requer que vários elementos sejam vinculados ao elemento webrtcbin:

Elementos do pipeline do GStreamer e a função deles.

Os elementos do pipeline fazem o seguinte:

  • ximagesrc captura a tela X11 de um soquete Unix a 60 fps em um buffer no formato RGB.
  • videoconvert converte o buffer RGB em formato compatível com NVENC.
  • nvh26enc codifica o buffer para H.264 em uma GPU usando NVENC.
  • rtph26pay cria um payload de pacote RTP enviado por uma conexão de peering.
  • webrtcbin gerencia o handshake do WebRTC e a negociação do contrato.

Como examinar o pipeline do GStreamer

Nas seções a seguir, apresentamos uma análise detalhada dos principais elementos do pipeline, o que fazem e como são configurados. É possível alterar os valores reais para se adequarem à sua carga de trabalho de streaming.

Nas amostras de código a seguir, mostramos o pipeline completo usado neste exemplo:images/gst-webrtc-app/gstwebrtc_app.pyVer no GitHub

def build_webrtcbin_pipeline(self):    """Adds the webrtcbin elments to the pipeline.    The video and audio pipelines are linked to this in the        build_video_pipline() and build_audio_pipeline() methods.    """    # Create webrtcbin element named app    self.webrtcbin = Gst.ElementFactory.make("webrtcbin", "app")    # The bundle policy affects how the SDP is generated.    # This will ultimately determine how many tracks the browser receives.    # Setting this to max-compat will generate separate tracks for    # audio and video.    # See also: https://webrtcstandards.info/sdp-bundle/    self.webrtcbin.set_property("bundle-policy", "max-compat")    # Connect signal handlers    self.webrtcbin.connect(        'on-negotiation-needed', lambda webrtcbin: self.__on_negotiation_needed(webrtcbin))    self.webrtcbin.connect('on-ice-candidate', lambda webrtcbin, mlineindex,                           candidate: self.__send_ice(webrtcbin, mlineindex, candidate))    # Add STUN server    if self.stun_server:        self.webrtcbin.set_property("stun-server", self.stun_server)    # Add TURN server    if self.turn_server:        logger.info("adding TURN server: %s" % self.turn_server)        self.webrtcbin.emit("add-turn-server", self.turn_server)    # Add element to the pipeline.    self.pipeline.add(self.webrtcbin)

images/gst-webrtc-app/gstwebrtc_app.pyVer no GitHub

def build_video_pipeline(self):    """Adds the RTP video stream to the pipeline.    """    # Create ximagesrc element named x11    # Note that when using the ximagesrc plugin, ensure that the X11 server was    # started with shared memory support: '+extension MIT-SHM' to achieve    # full frame rates.    # You can check if XSHM is in use with the following command:    #   GST_DEBUG=default:5 gst-launch-1.0 ximagesrc ! fakesink num-buffers=1 2>&1 |grep -i xshm    ximagesrc = Gst.ElementFactory.make("ximagesrc", "x11")    # disables display of the pointer using the XFixes extension,    # common when building a remote desktop interface as the clients    # mouse pointer can be used to give the user perceived lower latency.    # This can be programmatically toggled after the pipeline is started    # for example if the user is viewing full screen in the browser,    # they may want to revert to seeing the remote cursor when the    # client side cursor disappears.    ximagesrc.set_property("show-pointer", 0)    # Tells GStreamer that you are using an X11 window manager or    # compositor with off-screen buffer. If you are not using a    # window manager this can be set to 0. It's also important to    # make sure that your X11 server is running with the XSHM extension    # to ensure direct memory access to frames which will reduce latency.    ximagesrc.set_property("remote", 1)    # Defines the size in bytes to read per buffer. Increasing this from    # the default of 4096 bytes helps performance when capturing high    # resolutions like 1080P, and 2K.    ximagesrc.set_property("blocksize", 16384)    # The X11 XDamage extension allows the X server to indicate when a    # regions of the screen has changed. While this can significantly    # reduce CPU usage when the screen is idle, it has little effect with    # constant motion. This can also have a negative consequences with H.264    # as the video stream can drop out and take several seconds to recover    # until a valid I-Frame is received.    # Set this to 0 for most streaming use cases.    ximagesrc.set_property("use-damage", 0)    # Create capabilities for videoconvert    videoconvert_caps = Gst.caps_from_string("video/x-raw")    # Setting the framerate=60/1 capability instructs the ximagesrc element    # to generate buffers at 60 frames per second (FPS).    # The higher the FPS, the lower the latency so this parameter is one    # way to set the overall target latency of the pipeline though keep in    # mind that the pipeline may not always perfom at the full 60 FPS.    videoconvert_caps.set_value("framerate", Gst.Fraction(self.framerate, 1))    # Create a capability filter for the videoconvert_caps    videoconvert_capsfilter = Gst.ElementFactory.make("capsfilter")    videoconvert_capsfilter.set_property("caps", videoconvert_caps)    # Upload buffers from ximagesrc directly to CUDA memory where    # the colorspace conversion will be performed.    cudaupload = Gst.ElementFactory.make("cudaupload")    # Convert the colorspace from BGRx to NVENC compatible format.    # This is performed with CUDA which reduces the overall CPU load    # compared to using the software videoconvert element.    cudaconvert = Gst.ElementFactory.make("cudaconvert")    # Convert ximagesrc BGRx format to I420 using cudaconvert.    # This is a more compatible format for client-side software decoders.    cudaconvert_caps = Gst.caps_from_string("video/x-raw(memory:CUDAMemory)")    cudaconvert_caps.set_value("format", "I420")    cudaconvert_capsfilter = Gst.ElementFactory.make("capsfilter")    cudaconvert_capsfilter.set_property("caps", cudaconvert_caps)    # Create the nvh264enc element named nvenc.    # This is the heart of the video pipeline that converts the raw    # frame buffers to an H.264 encoded byte-stream on the GPU.    nvh264enc = Gst.ElementFactory.make("nvh264enc", "nvenc")    # The initial bitrate of the encoder in bits per second.    # Setting this to 0 will use the bitrate from the NVENC preset.    # This parameter can be set while the pipeline is running using the    # set_video_bitrate() method. This helps to match the available    # bandwidth. If set too high, the cliend side jitter buffer will    # not be unable to lock on to the stream and it will fail to render.    nvh264enc.set_property("bitrate", 2000)    # Rate control mode tells the encoder how to compress the frames to    # reach the target bitrate. A Constant Bit Rate (CBR) setting is best    # for streaming use cases as bit rate is the most important factor.    # A Variable Bit Rate (VBR) setting tells the encoder to adjust the    # compression level based on scene complexity, something not needed    # when streaming in real-time.    nvh264enc.set_property("rc-mode", "cbr")    # Group of Pictures (GOP) size is the distance between I-Frames that    # contain the full frame data needed to render a whole frame.    # Infinite GOP is best for streaming because it reduces the number    # of large I-Frames being transmitted. At higher resolutions, these    # I-Frames can dominate the bandwidth and add additional latency.    # With infinite GOP, you can use a higher bit rate to increase quality    # without a linear increase in total bandwidth.    # A negative consequence when using infinite GOP size is that    # when packets are lost, it may take the decoder longer to recover.    # NVENC supports infinite GOP by setting this to -1.    nvh264enc.set_property("gop-size", -1)    # Instructs encoder to handle Quality of Service (QOS) events from    # the rest of the pipeline. Setting this to true increases    # encoder stability.    nvh264enc.set_property("qos", True)    # The NVENC encoder supports a limited nubmer of encoding presets.    # These presets are different than the open x264 standard.    # The presets control the picture coding technique, bitrate,    # and encoding quality.    # The low-latency-hq is the NVENC preset reccomended for streaming.    #    # See this link for details on each preset:    #   https://streamquality.report/docs/report.html#1080p60-nvenc-h264-picture-quality    nvh264enc.set_property("preset", "low-latency-hq")    # Set the capabilities for the nvh264enc element.    nvh264enc_caps = Gst.caps_from_string("video/x-h264")    # Sets the H.264 encoding profile to one compatible with WebRTC.    # The high profile is used for streaming HD video.    # Browsers only support specific H.264 profiles and they are    # coded in the RTP payload type set by the rtph264pay_caps below.    nvh264enc_caps.set_value("profile", "high")    # Create a capability filter for the nvh264enc_caps.    nvh264enc_capsfilter = Gst.ElementFactory.make("capsfilter")    nvh264enc_capsfilter.set_property("caps", nvh264enc_caps)    # Create the rtph264pay element to convert buffers into    # RTP packets that are sent over the connection transport.    rtph264pay = Gst.ElementFactory.make("rtph264pay")    # Set the capabilities for the rtph264pay element.    rtph264pay_caps = Gst.caps_from_string("application/x-rtp")    # Set the payload type to video.    rtph264pay_caps.set_value("media", "video")    # Set the video encoding name to match our encoded format.    rtph264pay_caps.set_value("encoding-name", "H264")    # Set the payload type to one that matches the encoding profile.    # Payload number 123 corresponds to H.264 encoding with the high profile.    # Other payloads can be derived using WebRTC specification:    #   https://tools.ietf.org/html/rfc6184#section-8.2.1    rtph264pay_caps.set_value("payload", 123)    # Create a capability filter for the rtph264pay_caps.    rtph264pay_capsfilter = Gst.ElementFactory.make("capsfilter")    rtph264pay_capsfilter.set_property("caps", rtph264pay_caps)    # Add all elements to the pipeline.    self.pipeline.add(ximagesrc)    self.pipeline.add(videoconvert_capsfilter)    self.pipeline.add(cudaupload)    self.pipeline.add(cudaconvert)    self.pipeline.add(cudaconvert_capsfilter)    self.pipeline.add(nvh264enc)    self.pipeline.add(nvh264enc_capsfilter)    self.pipeline.add(rtph264pay)    self.pipeline.add(rtph264pay_capsfilter)    # Link the pipeline elements and raise exception of linking fails    # due to incompatible element pad capabilities.    if not Gst.Element.link(ximagesrc, videoconvert_capsfilter):        raise GSTWebRTCAppError("Failed to link ximagesrc -> videoconvert")    if not Gst.Element.link(videoconvert_capsfilter, cudaupload):        raise GSTWebRTCAppError(            "Failed to link videoconvert_capsfilter -> cudaupload")    if not Gst.Element.link(cudaupload, cudaconvert):        raise GSTWebRTCAppError(            "Failed to link cudaupload -> cudaconvert")    if not Gst.Element.link(cudaconvert, cudaconvert_capsfilter):        raise GSTWebRTCAppError(            "Failed to link cudaconvert -> cudaconvert_capsfilter")    if not Gst.Element.link(cudaconvert_capsfilter, nvh264enc):        raise GSTWebRTCAppError(            "Failed to link cudaconvert_capsfilter -> nvh264enc")    if not Gst.Element.link(nvh264enc, nvh264enc_capsfilter):        raise GSTWebRTCAppError(            "Failed to link nvh264enc -> nvh264enc_capsfilter")    if not Gst.Element.link(nvh264enc_capsfilter, rtph264pay):        raise GSTWebRTCAppError(            "Failed to link nvh264enc_capsfilter -> rtph264pay")    if not Gst.Element.link(rtph264pay, rtph264pay_capsfilter):        raise GSTWebRTCAppError(            "Failed to link rtph264pay -> rtph264pay_capsfilter")    # Link the last element to the webrtcbin    if not Gst.Element.link(rtph264pay_capsfilter, self.webrtcbin):        raise GSTWebRTCAppError(            "Failed to link rtph264pay_capsfilter -> webrtcbin")

Como escolher o número de payload do H.264

O elemento rtph264pay (em inglês) encapsula o stream de vídeo em pacotes RTP. As propriedades definidas nesse elemento precisam corresponder a uma gerada pelo SDP do receptor.

Veja um exemplo de SDP e vários tipos de payload visitando a página de teste do WebRTC (em inglês) e executando o teste com a opção Require H.264 video marcada. A saída do SDP exibida durante o teste mostra os perfis compatíveis com seu navegador:

a=rtpmap:102 H264/90000
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:127 H264/90000
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:125 H264/90000
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:108 H264/90000
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtpmap:124 H264/90000
a=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d0032
a=rtpmap:123 H264/90000
a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032

Os parâmetros do SDP ajudam a identificar o número de payload a ser usado. Nesta tabela (em inglês), há uma descrição de como decodificar os IDs de nível do perfil. A especificação também indica que os decodificadores podem processar perfis diferentes daqueles passados no SDP. Por exemplo, se você codificar com o perfil high, mas enviar o tipo de payload baseline (102), o perfil provavelmente ainda será decodificado.

O primeiro byte hexadecimal de profile-level-id é usado para descrever o perfil que você deve usar no pipeline do GStreamer. Como o pipeline do GStreamer define o perfil do codificador como high, escolha payload=123.

Tipo de payloadID do nível de perfilModo de empacotamentoPerfil do GStreamer
10242001f1baseline
12742001f0baseline
12542e01f1baseline
10842e01f0baseline
1244d00321main
1236400321high

Pipeline de áudio

O envio de áudio por WebRTC também é possível com o GStreamer. Esta seção do pipeline se conecta ao servidor local PulseAudio por TCP, converte-o no formato Opus (em inglês) e faz streaming dele como RTP usando o número de payload do SDP. Esse processo requer que um servidor PulseAudio em execução esteja ouvindo no endereço 127.0.0.1 e que seu app envie áudio para o subsistema padrão do PulseAudio, como na maioria das vezes.images/gst-webrtc-app/gstwebrtc_app.pyVer no GitHub

def build_audio_pipeline(self):    """Adds the RTP audio stream to the pipeline.    """    # Create element for receiving audio from pulseaudio.    pulsesrc = Gst.ElementFactory.make("pulsesrc", "pulsesrc")    # Let the audio source provide the global clock.    # This is important when trying to keep the audio and video    # jitter buffers in sync. If there is skew between the video and audio    # buffers, features like NetEQ will continuously increase the size of the    # jitter buffer to catch up and will never recover.    pulsesrc.set_property("provide-clock", True)    # Apply stream time to buffers, this helps with pipeline synchronization.    pulsesrc.set_property("do-timestamp", True)    # Encode the raw pulseaudio stream to opus format which is the    # default packetized streaming format for the web.    opusenc = Gst.ElementFactory.make("opusenc", "opusenc")    # Set audio bitrate to 64kbps.    # This can be dynamically changed using set_audio_bitrate()    opusenc.set_property("bitrate", 64000)    # Create the rtpopuspay element to convert buffers into    # RTP packets that are sent over the connection transport.    rtpopuspay = Gst.ElementFactory.make("rtpopuspay")    # Insert a queue for the RTP packets.    rtpopuspay_queue = Gst.ElementFactory.make("queue", "rtpopuspay_queue")    # Make the queue leaky, so just drop packets if the queue is behind.    rtpopuspay_queue.set_property("leaky", True)    # Set the queue max time to 16ms (16000000ns)    # If the pipeline is behind by more than 1s, the packets    # will be dropped.    # This helps buffer out latency in the audio source.    rtpopuspay_queue.set_property("max-size-time", 16000000)    # Set the other queue sizes to 0 to make it only time-based.    rtpopuspay_queue.set_property("max-size-buffers", 0)    rtpopuspay_queue.set_property("max-size-bytes", 0)    # Set the capabilities for the rtpopuspay element.    rtpopuspay_caps = Gst.caps_from_string("application/x-rtp")    # Set the payload type to audio.    rtpopuspay_caps.set_value("media", "audio")    # Set the audio encoding name to match our encoded format.    rtpopuspay_caps.set_value("encoding-name", "OPUS")    # Set the payload type to match the encoding format.    # A value of 96 is the default that most browsers use for Opus.    # See the RFC for details:    #   https://tools.ietf.org/html/rfc4566#section-6    rtpopuspay_caps.set_value("payload", 96)    # Create a capability filter for the rtpopuspay_caps.    rtpopuspay_capsfilter = Gst.ElementFactory.make("capsfilter")    rtpopuspay_capsfilter.set_property("caps", rtpopuspay_caps)    # Add all elements to the pipeline.    self.pipeline.add(pulsesrc)    self.pipeline.add(opusenc)    self.pipeline.add(rtpopuspay)    self.pipeline.add(rtpopuspay_queue)    self.pipeline.add(rtpopuspay_capsfilter)    # Link the pipeline elements and raise exception of linking fails    # due to incompatible element pad capabilities.    if not Gst.Element.link(pulsesrc, opusenc):        raise GSTWebRTCAppError("Failed to link pulsesrc -> opusenc")    if not Gst.Element.link(opusenc, rtpopuspay):        raise GSTWebRTCAppError("Failed to link opusenc -> rtpopuspay")    if not Gst.Element.link(rtpopuspay, rtpopuspay_queue):        raise GSTWebRTCAppError("Failed to link rtpopuspay -> rtpopuspay_queue")    if not Gst.Element.link(rtpopuspay_queue, rtpopuspay_capsfilter):        raise GSTWebRTCAppError(            "Failed to link rtpopuspay_queue -> rtpopuspay_capsfilter")    # Link the last element to the webrtcbin    if not Gst.Element.link(rtpopuspay_capsfilter, self.webrtcbin):        raise GSTWebRTCAppError(            "Failed to link rtpopuspay_capsfilter -> webrtcbin")

Como gerenciar entradas

O streaming de eventos de teclado, mouse e gamepad para seu app torna-o interativo. O canal de dados RTCPeerConnection é um stream de dados arbitrário vinculado à conexão de peering que usa os mesmos métodos de conexão das faixas de vídeo e áudio. Os canais de dados usam o Stream Control Transmission Protocol (SCTP) para transportar dados pela conexão de peering. Quaisquer dados podem ser enviados por este canal e sua interface é semelhante à de um WebSocket. Os canais de dados são compatíveis com o GStreamer a partir da versão 1.16.

Eventos de teclado e mouse são capturados usando seus manipuladores de eventos JavaScript nativos. Em seguida, eles são convertidos em comandos binários e enviados em um canal de dados em que os eventos são decodificados e transmitidos ao servidor X11. No diagrama a seguir, ilustramos os vários fluxos e formatos de e para um cliente receptor e um servidor de envio.

Vários fluxos e formatos para e de um cliente receptor e um servidor de envio.

Teclado

Quando você pressiona uma tecla, o navegador gera um evento do tipo keydown e, quando você libera uma chave, um evento keyup. Os eventos contêm o caractere da chave localizada, como asd ou f, e um código de chave JavaScript, como KeyAKeySKeyD ou KeyF. Os keysyms X11 são mapeamentos hexadecimais definidos na biblioteca Xlib (em inglês). Algumas bibliotecas JavaScript de código aberto, como a biblioteca de teclado do projeto Guacamole (em inglês), podem ser usadas para converter os códigos keysym de que o X11 precisa. Em seguida, o app receptor pode transmitir esses keysyms diretamente para a biblioteca Xlib.

Mouse

Os eventos do mouse são enviados para a tela X11 como posição absoluta ou como movimento relativo. Ao calcular a janela de visualização do cliente do navegador, o fator de dimensionamento de vídeo e os deslocamentos de página, é possível enviar o evento de mouse traduzido para a tela X11. A API PointerLock (em inglês) é útil ao tentar capturar o ponteiro do mouse e passar o movimento relativo (em vez de absoluto) do mouse, que é necessário ao fazer streaming de jogos, como atiradores em primeira pessoa.

Dados

Além dos eventos de entrada, o canal de dados RTC também pode ser usado para enviar mensagens de comando e controle ao pipeline como uma alternativa ao uso do servidor de sinalização. Por exemplo, é possível alterar dinamicamente a taxa de bits ou alternar a visibilidade do ponteiro do mouse. Em casos de uso mais avançados do WebRTC, o canal de dados SCTP é substituído por protocolos como a Conexão de Internet de UDP rápida (QUIC, na sigla em inglês).

Como programar o app GStreamer

Para usar o elemento webrtcbin do GStreamer, crie um app GStreamer usando uma das vinculações de linguagem compatíveis. O GStreamer é baseado no GLib Object System (GObject), projetado para interoperabilidade da linguagem e na programação orientada a objetos em C. A vinculação de linguagem Python para GStreamer é baseada na biblioteca PyGObject e é uma linguagem ideal de alto nível para programação com os protocolos e as interfaces modernos exigidos por um app WebRTC.

No diagrama a seguir, mostramos a arquitetura de um app WebRTC do GStreamer.

Arquitetura do app WebRTC do GStreamer.

App Python do remetente do GStreamer

Nesta seção, você aprende a criar o código do servidor de sinalização e do app GStreamer que envia o stream para o cliente do navegador.

O app Python do GStreamer conecta-se ao servidor de sinalização, implementa o app GStreamer e transmite a entrada do usuário do app da Web para o servidor X11. O app Python é dividido em vários arquivos, classes e métodos com base na função:

├── webrtc_signaling.py   # Signaling server interface
├── webrtc_input.py       # User input handling
├── gstwebrtc_app.py      # GStreamer pipeline
└── main.py               # Main method

Sinalização

Neste exemplo, você implementa uma classe Python que interage com o servidor de sinalização baseado em WebSocket do repositório gstwebrtc-demos. Essa classe abstrai a interface para sinalizar de maneira que seja possível intercambiar um servidor de sinalização diferente com mudança mínima no código:

├── webrtc_signaling.py
├───── class WebRTCSignaling()
├──────── connect()     # Connects to the signaling server
├──────── setup_call()  # Starts session with peer by ID
├──────── send_ice()    # Sends ICE candidate to peer
└──────── send_sdp()    # Sends SDP to peer

Gerenciamento de entradas

Nesse exemplo, a biblioteca Xlib do Python é usada para enviar eventos de pressionamento de tecla X11 e eventos de mouse recebidos pelo canal de dados WebRTC para o servidor X. O método on_message() está vinculado no método principal ao gerenciador de sinais on-message no app GStreamer.

├── webrtc_input.py
├───── class WebRTCInput()
├──────── connect()           # Connects to the X server
├──────── send_x11_keypress() # Sends keysyms to X server
├──────── send_x11_mouse()    # Sends mouse events to X server
└──────── on_message()        # Handles messages from data channel

App GStreamer

O código GStreamer Python é a parte central do app de streaming. Esse app cria o pipeline, processa os sinais emitidos pelo elemento webrtcbin e define o SDP remoto e os candidatos ICE do servidor de sinalização. Esse código também processa solicitações para alterar o pipeline em execução a fim de mudar a taxa de bits do codificador e alternar a visibilidade do ponteiro.

├── gstwebrtc_app.py
├───── class GSTWebRTCApp()
├──────── __on_negotiation_needed() # Handler for on-negotiation-needed signal
├──────── __on_offer_created()      # Handler for on-offer-created signal
├──────── __send_ice()              # Handler for on-ice-candidate signal
├──────── set_sdp()                 # Sets SDP from signaling
├──────── set_ice()                 # Sets ICE candidate from signaling
├──────── set_bitrate()             # Sets the bit rate on the NVENC element
├──────── set_pointer_visible()     # Toggles pointer on the ximagesrc element
└──────── start_pipeline()          # Builds the pipeline and starts it

Método principal

O método principal do app GStreamer busca as credenciais do TURN do servidor do serviço da Web do coTURN, conecta o gerenciador de entradas e também conecta o servidor de sinalização ao app WebRTC. O app é assíncrono e usa as corrotinas do Python 3 e o módulo asyncio para gerenciar as linhas de execução.

├── main.py
├───── fetch_coturn()
└───── main()

images/gst-webrtc-app/main.pyVer no GitHub

# Connect to the signalling server and process messages.loop = asyncio.get_event_loop()try:    metrics.start()    loop.run_until_complete(webrtc_input.connect())    loop.run_in_executor(None, lambda: webrtc_input.start_clipboard())    loop.run_in_executor(None, lambda: gpu_mon.start())    loop.run_until_complete(signalling.connect())    loop.run_until_complete(signalling.start())except Exception as e:    logging.error("Caught exception: %s" % e)    sys.exit(1)finally:    webrtc_input.stop_clipboard()    webrtc_input.disconnect()    gpu_mon.stop()    sys.exit(0)

App da Web para receber stream

O app de front-end do JavaScript é escrito em Vue.js. O app da Web busca as credenciais do servidor TURN, conecta-se ao servidor de sinalização, estabelece uma conexão de peering e captura as entradas do usuário. O único elemento HTML5 obrigatório é o video, que exibe o stream remoto. Como os navegadores podem ter implementações diferentes da especificação WebRTC, esse app usa o adaptador WebRTC para criar uma interface JavaScript padronizada.

├── index.html    # Vue app HTML
├── app.js        # Vue.js app code
├── input.js      # Input handling
├── signaling.js  # Interface to signaling server
└── webrtc.js     # WebRTC app code

A arquitetura do app de recebimento no lado do cliente é semelhante à do app Python no lado do servidor para interagir com o servidor de sinalização e STUN/TURN e tem o código para reproduzir o stream de vídeo recebido.

Arquitetura do app de recebimento no lado do cliente.

Sinalização

O objeto signaling abstrai as principais funções de um servidor de sinalização. Para este exemplo, a funcionalidade mínima necessária inclui estabelecer a sessão e trocar SDPs e candidatos ICE.

├── signaling.js
├───── class WebRTCDemoSignaling
├──────── _setSDP()         # Incoming SDP handler
├──────── _setICE()         # Incoming ICE candidate handler
├──────── sendICE()         # Send ICE candidate to peer
├──────── sendSDP()         # Send SDP to peer
└──────── connect()         # Connect to signaling server

Gerenciamento de entradas

A classe Input implementa os manipuladores de eventos para capturar, processar e enviar dados de entrada para o servidor usando o canal de dados RTC aberto.

É possível capturar eventos de teclado com os keysyms X11 convertidos ao usar uma biblioteca atual, como uma do projeto Guacamole. O keysym é codificado como CSV e enviado por meio do canal de dados de conexão do par.

Os eventos de mouse são mais complexos, porque é possível receber posições relativas ou coordenadas absolutas em eventos de mouse combinados com um ou mais pressionamentos de botão em um único evento. A conversão da posição do mouse também precisa ser calculada com base no tamanho da janela, nos deslocamentos de elemento e em qualquer dimensionamento aplicado ao elemento de vídeo. As posições x e y e as máscaras de botão são armazenadas como variáveis locais para que os últimos valores conhecidos possam ser enviados em eventos subsequentes. As mensagens enviadas ao canal de dados são processadas no lado do servidor por meio do código Python descrito anteriormente.

├── input.js
├───── class Input
├──────── _mouseButtonMovement() # Handle mouse events
├──────── _key()                 # Handle keyboard events
├──────── _pointerLock()         # Toggle pointer lock
├──────── _windowMath()          # Compute pointer translations
└──────── attach()               # Bind event handlers

Como buscar servidores STUN/TURN

O app da Web busca o endereço e as credenciais do servidor TURN antes de criar o objeto RTCPeerConnection. O endpoint para acessar as informações do servidor TURN está disponível apenas por uma rota autenticada para impedir que outras pessoas na Internet o utilizem.

App da Web

A função principal cria o objeto RTCPeerConnection e anexa os manipuladores de eventos às funções locais. Ele também anexa retornos de chamada e se conecta ao servidor de sinalização. Depois que o servidor de sinalização estiver conectado, ele aguardará que o servidor de envio inicie a chamada enviando o SDP da oferta.

├── webrtc.js
├───── class WebRTCDemo
├──────── _onSignalingICE()
├──────── _onPeerICE()
├──────── _onSDP()
├──────── _ontrack()
├──────── sendDataChannelMessage()
├──────── playVideo()
└──────── connect()

Como reproduzir o stream de vídeo

Quando o stream é recebido da conexão WebRTC, o objeto RTCPeerConnection emite um evento RTCTrackEvent que contém o objeto de stream de vídeo. Em seguida, esse objeto é adicionado ao elemento de vídeo HTML5 atribuindo-o à propriedade srcObject, que carrega automaticamente o stream. O navegador Chrome tem algumas políticas sobre conteúdo de mídia de reprodução automática, que, na maioria dos casos, exige que o usuário realize alguma interação DOM antes da reprodução do vídeo. Neste exemplo, se o vídeo não for reproduzido automaticamente, a IU exibirá um botão inicial que confirma a interação do usuário antes de reproduzir o stream de vídeo.images/gst-web/src/webrtc.jsVer no GitHub

playVideo() {    this.element.load();    var playPromise = this.element.play();    if (playPromise !== undefined) {        playPromise.then(() => {            this._setDebug("Video stream is playing.");        }).catch(() => {            if (this.onplayvideorequired !== null) {                this.onplayvideorequired();            } else {                this._setDebug("Video play failed and no onplayvideorequired was bound.");            }        });    }}

Como exibir estatísticas de conexão do WebRTC

Ao usar o Chrome, você vê as estatísticas RTCPeerConnection abrindo o URI chrome://webrtc-internals. Atualmente, há duas APIs de estatísticas, uma API padronizada baseada em promessa (em inglês) e uma API legada baseada em callback. Atualmente, apenas um subconjunto das estatísticas legadas está disponível na API padronizada. Por isso, este exemplo usa a API legada.

Captura de tela da interface da Web do WebRTC interno.

Essas APIs fornecem informações importantes ao criar uma solução baseada em WebRTC, por exemplo:

  • Tipo de conexão de mesmo nível determinado pelo ICE
  • Número de pacotes recebidos e perdidos
  • Latência de conexão
  • Desempenho do buffer de instabilidade
  • Taxa de bits do vídeo
  • Frame rate do vídeo

A captura de tela a seguir mostra gráficos de estatísticas da API padronizada.

Gráficos de estatísticas da API padronizada.

A captura de tela a seguir mostra gráficos de estatísticas da API legada.

Gráficos de estatísticas da API legada.

Latência

A latência é uma métrica importante para streaming e pode afetar significativamente a experiência do usuário. Como mostra o diagrama a seguir, há várias fontes de latência a serem consideradas, como latência de decodificação, latência de pipeline e atrasos de rede de e para regiões do Google Cloud.

Origens de latência.

Como medir a latência da rede

É possível medir a latência de rede entre sua máquina local e uma região do Google Cloud com ferramentas como ping para medir a latência de ida e volta entre as máquinas e GCPing para medir a latência dos data centers do Google. Use essas informações para estimar a latência geral que sua implementação terá para os usuários. A escolha de uma região para hospedar sua carga de trabalho de streaming também depende da disponibilidade da GPU por região e zona.

Como medir a latência do pipeline

A latência do pipeline pode ser medida usando o rastreador InterLatency do plug-in GstShark. Essas métricas podem ajudar você a depurar e otimizar o pipeline identificando elementos lentos. Para ativar o rastreador, instale o plug-in e execute o pipeline com as variáveis de ambiente necessárias:

GST_DEBUG="GST_TRACER:7"GST_TRACERS="interlatency"

Quando o pipeline é interrompido com o sinal SIGINT, um diretório e arquivos de dados são criados:

gstshark_DATE_TIME/
├── datastream
└── metadata

Você transmite esse diretório como um argumento para o script gstshark-plot (em inglês) que gera um gráfico interativo usando o Octave (em inglês). O gráfico permite explorar a latência que foi medida enquanto o pipeline estava em execução. Observe que a primeira inicialização tem alta latência à medida que o pipeline é inicializado, mas chega ao estado estável. A latência de codificação também é um gerador significativo de latência. Neste exemplo, ela adiciona de 5 a 12 ms, como mostra as capturas de tela a seguir.

A primeira captura de tela mostra o gráfico entre as latências na primeira inicialização.

Gráfico entre latências que mostra a primeira inicialização.

Na captura de tela a seguir, veja o estado estável entre as latências de todos os elementos do pipeline.

Estado estável entre latências de todos os elementos do pipeline.

Por fim, a captura de tela a seguir mostra a codificação de vídeo e a conversão de formato entre as latências.

Codificação de vídeo e conversão de formato entre latências.

Como medir a latência do cliente no Chrome

O desempenho da conexão é melhor monitorado na página chrome://webrtc-internals. Ao usar o Google Chrome, veja a seguir algumas das principais métricas que afetam a latência:

  • googCurrentDelayMs de vídeo
  • googJitterBufferMs de vídeo
  • googFrameRateOutput de vídeo
  • googCurrentDelayMs de áudio
  • googJitterBufferMs de áudio

A captura de tela a seguir mostra a latência total percebida pelo usuário.

Latência total percebida pelo usuário.

A latência é uma combinação da latência de vídeo e áudio. Seu objetivo é reduzir ambos para criar a melhor experiência do usuário.

O WebRTC usa buffers de instabilidade para reter pacotes entre a chegada e a reprodução. Esses buffers são usados para reorganizar pacotes fora de ordem e atrasados. Quanto menor o buffer, menor a latência. O Chrome redimensiona dinamicamente os buffers de instabilidade usando o NetEQ (para áudio) para se adaptar às condições da rede. Se o servidor que envia o stream estiver lento ou tiver uma conexão de rede ruim, o buffer de instabilidade aumentará até atingir o tamanho máximo de cerca de 1.000 ms. Para reduzir esse efeito, o stream de envio pode remover amostras de áudio ou frames de vídeo para que os pacotes atrasados nunca sejam enviados.

Se o servidor de envio estiver com uma alta carga de CPU, isso também poderá tornar o pipeline lento e introduzir latência.

Solução de problemas

O WebRTC é um protocolo complexo que envolve muitas tecnologias que podem ser desafiadoras para depurar e rastrear problemas. O problema mais comum é a conectividade. O rastreamento de firewalls e redes de usuários é complicado e aumenta a complexidade de depuração de outros problemas com o pipeline do GStreamer. Nesta seção, listamos alguns dos problemas que podem surgir ao criar um app de streaming baseado em WebRTC e como depurá-los.

Rastreamento de conectividade

exemplo do ICE-Trickle (em inglês) criado pela equipe WebRTC é uma ferramenta útil para verificar a conectividade do seu navegador local com um servidor STUN ou TURN. Digite o endereço e as credenciais do seu servidor TURN e clique em Gather Candidates para verificar a conectividade. O endereço está na formato do URI passado para sua configuração RTCPeerConnection, por exemplo:

stun:5.4.3.2:3478turn:5.4.3.2:3478?transport=udp

Se a verificação for bem-sucedida, você verá uma entrada no registro do ICE que contém o endereço IP do servidor TURN. Se você não vir o endereço IP, é provável que haja um problema no firewall ou no servidor TURN.

TempoComponenteTipoFundaçãoProtocoloEndereçoPortaPrioridade
0,0021host619629460udp192.168.1.250589126 | 30 | 255
0,0471srflx842163049udp1.2.3.440326100 | 30 | 255
0,104Pronto
0,106

Rastreamento de handshake no Chrome

O handshake do WebRTC descrito anteriormente tem vários estados pelos quais precisa avançar antes que a conexão seja estabelecida. A página chrome://webrtc-internals é um dos melhores recursos para rastrear esse handshake. Embora muitas informações sejam exibidas, este artigo descreve como rastrear as chamadas de API.

A captura de tela a seguir mostra um exemplo de chamada de rastreamento da API WebRTC.

Exemplo de chamada de rastreamento da API WebRTC.

Exemplo de rastreamento da API WebRTC de chrome://webrtc-internals

Depuração de pipeline do GStreamer

O pipeline do GStreamer é criado com vários elementos distintos, cada um com seus próprios registros de depuração e níveis de registro.

É possível definir o nível de registro de todos os elementos definindo a variável shell GST_DEBUG antes de iniciar o pipeline. O valor dessa variável usa o seguinte formato:

GST_DEBUG=element:level

O exemplo de código a seguir define o nível de registro como 3 para todos os elementos:

GST_DEBUG=*:3

O nível 3 é bom para identificar informações importantes e erros fatais.

Para ver registros mais detalhados do elemento nvenc, execute o seguinte:

GST_DEBUG=nvenc:4

É possível executar qualquer seção do pipeline na linha de comando fora do app Python do GStreamer usando o comando gst-launch-1.0. O elemento fakesink é útil para depuração porque gera um coletor nulo. Essa ferramenta é útil para receber uma verificação de integridade rápida e verificar se as bibliotecas do GStreamer e os drivers NVIDIA estão instalados corretamente.

GST_DEBUG=ximagesrc,nvenc:4 \  gst-launch-1.0 \  ximagesrc use-damage=0 remote=1 ! \  videoconvert ! \  nvh264enc ! \  fakesink num-buffers=1

A seguir

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s