
Compartilhar:
Roberto is a Full Stack Engineer on the OpenTok Client SDK team. He loves learning new bits of Android, iOS, Linux, Windows, you name it! In his free time, he is very passionate about programming languages, computer graphics, and video game development for current and old platforms like ZX Spectrum and Commodore 64.
Crie filtros de RA personalizados com a Video API da Vonage e a DeepAR
Tempo de leitura: 12 minutos
O aprimoramento por meio da IA é o futuro das videochamadas. Ele nos ajudará a quebrar o gelo (virtual), facilitará a exploração de novos casos de uso em vídeo interativo, como compras e assistência remota, e criará experiências totalmente novas. Os futuros criadores dessas experiências provavelmente estão “sentados” em uma sala de aula virtual, sendo moldados pelo vídeo virtual como nenhuma geração antes deles.
Como desenvolvedores da Video API da Vonage, vocês podem integrar nossa Video API ao SDK do DeepAR para aprimorar a experiência de interação com Video dos seus usuários.
Você pode deixar as videochamadas com um aspecto mais profissional ao tratar o fundo — substituindo, desfocando ou pixelizando os objetos — ou melhorar a experiência do usuário aprimorando a iluminação e aplicando efeitos sutis no tom de pele.
Ou divirta-se ainda mais com uma grande variedade de filtros animados do DeepAR.
Augmented Reality filters in action
A Realidade Aumentada em Nossa Vida Cotidiana
É bem provável que você já tenha participado de uma videoconferência, seja uma reunião de trabalho, uma consulta médica ou uma reunião familiar.
Nesse novo paradigma de reuniões centradas em Video, muitos novos aplicativos podem agregar valor à comunicação por Video. Vamos examinar algumas formas comuns pelas quais a tecnologia de realce está sendo utilizada para melhorar a experiência do usuário e nos ajudar a ser mais eficazes em nossas interações remotas:
Resumo do contexto
Uma das melhorias para a comunicação por Video consiste em ocultar tudo o que aparece no fundo do usuário por meio de recursos simples de desfoque, pixelização ou substituição do fundo. Os benefícios incluem:
ativar a privacidade do chamador
facilitar o envolvimento do espectador, eliminando distrações
criando experiências de marca
Aprimoramentos do alto-falante
Outro exemplo de como levar as videochamadas a um novo patamar com a RA é a aplicação de filtros aos participantes em primeiro plano. A implementação desse tipo de filtro permite que seus usuários:
Relaxe durante a videochamada com filtros de luz, tom de pele e beleza
divirta e entrete com animojis engraçados
interagir em tempo real com objetos 3D e até mesmo com pinturas faciais virtuais
A dog face AR filter in use
A flexibilidade da Video API da Vonage torna isso possível ao integrar-se a parceiros de RA, como a DeepAR. Nesta postagem do blog, demonstraremos como viabilizar os casos de uso acima por meio da combinação das duas APIs.
O que é o DeepAR?
O DeepAR é um mecanismo de RA otimizado para dispositivos móveis e HTML5, destinado à realidade aumentada, filtros faciais, segmentação de fundo, maquiagem, filtros de beleza e animoji.
O DeepAR SDK oferece aos desenvolvedores acesso ao DeepAR Engine, gerencia o suporte a vários dispositivos e inclui a ferramenta DeepAR Studio para ajudá-lo a criar os recursos de RA.
Como usar o DeepAR
Para adicionar a estrutura do DeepAR SDK ao seu aplicativo iOS, você precisa baixar o arquivo zip do site deles, https://developer.deepar.ai/. Depois de baixar o arquivo zip, descompacte-o e arraste o arquivo da estrutura para o seu projeto no Xcode.

Não se esqueça de definir a embed configuração do framework para “Incorporar e Assinar”, caso contrário, o aplicativo poderá não encontrar a biblioteca durante a execução.
Depois de definir isso, o próximo passo é acessar https://developer.deepar.ai/ e criar um projeto para obter a chave do aplicativo de que você precisará mais tarde.
Adicionando leões à entrada de video capturada
Nesta postagem do blog, vamos criar uma UIView na qual você poderá exibir o que está sendo filmado pela câmera frontal e, quando seu rosto for detectado, ele será complementado com um leão bem legal.
Se você quiser ver todo o código desta postagem em um só lugar, pode encontrá-lo no GitHub do DeepAR.
No código, você precisará lidar com duas classes; uma delas é a `CameraController` do DeepAR SDK, que é responsável por acessar a câmera do dispositivo e obter imagens dela. Assim que receber o fluxo de Video, ela o envia para a instância da `ARView`, que é a outra classe que você precisa instanciar.
O ARView é responsável por exibir o conteúdo da câmera com os filtros de RA aplicados. O ARView é um elemento filho comum do UIView; portanto, você precisa adicioná-lo a qualquer vista pai dentro da hierarquia de vistas do seu aplicativo.
Sabendo disso, o código poderia ficar assim:
let deepARCameraController = CameraController()
let deepARView = ARView(frame: UIScreen.main.bounds)
deepARView.setLicenseKey(deepARLicense)
deepARView.delegate = self
deepARCameraController.arview = deepARView
parentView.insertSubview(deepARView, at: 0)
deepARView.initialize()
deepARCameraController?.startCamera()No código acima, você primeiro cria o CameraController e, em seguida, cria a instância do ARView usando-o como moldura para a tela cheia, já que vamos exibi-la ocupando toda a tela.
Observe que estamos atribuindo self como delegado do ARView, portanto, você precisará implementar/estar em conformidade com o protocolo ARViewDelegate. Precisaremos disso mais tarde.
Depois de ter as duas instâncias, você atribui a propriedade ARView da instância do CameraController à nossa visualização e a insere em nosso parentView.
Agora só falta inicializar a visualização e capturar o Video da câmera chamando startCamera.
Se você executar o código, vai perceber que não há nenhum 🦁 sobre o seu rosto, e isso ocorre porque ainda não ativamos o efeito.
Para isso, você precisa implementar didInitialize, um método do ARViewDelegate, que chamaremos assim que a ARView terminar de ser inicializada; então, poderemos ativar o filtro do leão.
func didInitialize() {
deepARView.switchEffect(withSlot: "effect", path: Bundle.main.path(forResource: "lion", ofType: ""))
}Para que isso funcione, você precisa adicionar um arquivo chamado “lion” ao seu projeto. Você pode encontrá-lo no pacote de filtros gratuito disponível em https://developer.deepar.ai/downloads. Depois de baixá-lo, você precisa arrastar o arquivo “lion” para a pasta raiz do projeto do Xcode e verificar se ele tem seu aplicativo como destino, para que seja incluído nele.
XCode
Se você executar o aplicativo neste momento, deverá ver seu rosto com uma sobreposição legal de um leão que acompanha todos os seus movimentos e gestos.
Lion
OpenTok e drivers de vídeo personalizados
A maioria dos desenvolvedores interage com a Video API da Vonage por meio do SDK do OpenTok. Um dos recursos mais interessantes do SDK é a possibilidade de criar seu próprio driver de vídeo para enviar qualquer tipo de conteúdo de vídeo para a sessão do OpenTok à qual seu editor está conectado.
Os drivers de vídeo podem ser divididos em duas partes distintas:
Por um lado, temos o capturador de vídeo, que, como o próprio nome indica, deve capturar o vídeo de qualquer fonte (ou produzi-lo de alguma forma) e fornecer ao SDK os quadros de vídeo que serão enviados.
Por outro lado, temos o renderizador de Video e, como você provavelmente já imaginou, ele é responsável por renderizar os quadros de Video que chegam remotamente por meio de uma sessão do OpenTok através de um assinante.
Se você já utilizou o SDK do OpenTok, provavelmente percebeu que não precisa lidar com essas classes em um cenário comum. Isso porque o SDK do OpenTok vem com capturadores e renderizadores padrão que capturam Video da câmera padrão do sistema e renderizam os quadros de Video remotos usando a tecnologia gráfica de cada plataforma, seja ela Metal, OpenGL ou DirectX.
Os drivers de vídeo são muito poderosos. Você pode criar um driver de vídeo para enviar qualquer conteúdo de vídeo. Por exemplo, você pode capturar a saída de qualquer motor de jogo e enviar esses quadros de vídeo para o SDK do OpenTok, transmitindo assim o conteúdo do seu jogo para qualquer participante de uma sessão do OpenTok. Você também pode aplicar qualquer filtro de renderização, como preto e branco ou detecção de bordas, para que cada assinante tenha uma aparência diferente.
Criação de um capturador de vídeo personalizado do OpenTok
Embora possa parecer que criar um capturador de vídeo personalizado seja uma tarefa complicada, provavelmente é mais simples do que você imagina.
Basta implementar uma interface, herdar de uma classe ou conformar-se a um protocolo, dependendo da linguagem e da plataforma de sua escolha. No entanto, como você viu acima, estamos usando Swift e iOS nos exemplos de código-fonte desta postagem.
Nessa classe, você precisará implementar ou sobrescrever alguns métodos básicos que controlam o ciclo de vida do capturador. Você precisará implementar init, startCapture, stopCapture, isCaptureStarted , bem como um método para definir as configurações do capturador, o que consiste em especificar a altura, a largura, a taxa de quadros e o formato de pixels dos quadros de vídeo que o capturador irá enviar.
Depois que esses métodos forem implementados, você precisará fornecer quadros ao capturador. Dependendo da plataforma, o procedimento pode variar, mas, geralmente, basta chamar um método com os dados do quadro de Video.
Vamos ver como poderia ser uma implementação inicial,
class DeepARVideoCapturer: NSObject, OTVideoCapture {
fileprivate var captureStarted = false
var videoCaptureConsumer: OTVideoCaptureConsumer?
func initCapture() {
}
func releaseCapture() {
}
func start() -> Int32 {
captureStarted = true
return 0
}
func stop() -> Int32 {
captureStarted = false
return 0
}
func isCaptureStarted() -> Bool {
return captureStarted
}
func captureSettings(_ videoFormat: OTVideoFormat) -> Int32 {
return 0
}
}
Acima está o código necessário para um capturador personalizado. Como você pode ver, é preciso implementar o protocolo OTVideoCapture, que possui métodos que serão chamados quando o capturador de vídeo precisar ser inicializado, iniciado ou parado. É muito comum ter um sinalizador interno para saber quando a captura foi iniciada, e é isso que fazemos nesta implementação básica. Atualizaremos esse sinalizador nos métodos de início e parada.
Você deve ter percebido que essa classe herda de NSObject, já que isso não é muito comum em classes do Swift, que geralmente herdam apenas de `Object`. A razão por trás disso é que o protocolo `OTVideoCapture` herda do protocolo `NSObject`, principalmente porque a base de código do SDK do OpenTok é, em grande parte, escrita em Objective-C e, nessa linguagem, tudo herda de `NSObject`.
Depois de criar uma classe como essa, o próximo passo é informar ao editor que, em vez de usar o capturador padrão, ele precisa usar a nossa classe. O código para isso fica assim:
let settings = OTPublisherSettings()
settings.name = UIDevice.current.name
settings.videoCapture = DeepARVideoCapturer()
otPublisher = OTPublisher(delegate: self, settings: settings)O capturador que criamos no trecho de código acima ainda não está enviando nada, pois contém apenas código de inicialização. Se você tentar usar o que temos até agora, ele deve funcionar, mas você estará publicando apenas quadros pretos. O próximo passo é aprender a enviar quadros.
Mas vamos adiar essa parte até termos alguns quadros para enviar, e esses quadros serão o resultado da nossa visualização do DeepAR.
Integração do DeepAR com o OpenTok
Chegamos à última parte desta postagem do blog. Na primeira parte, vimos como criar um capturador de vídeo básico; na segunda parte, vimos como usar o ARView do DeepAR com um filtro de RA de um leão substituindo o seu rosto. A única coisa que faltava no nosso capturador de vídeo personalizado era o envio de quadros de vídeo; portanto, parece que já temos tudo pronto para a etapa final.
Nesta etapa, vamos conectar os dois mundos; precisamos fazer algumas coisas. Primeiro, precisamos obter os quadros de vídeo que o ARView está gerando e, segundo, precisamos enviá-los usando o capturador de vídeo que criamos.
O primeiro passo consiste em obter uma imagem do ARView. Isso pode ser feito muito rapidamente definindo o delegado ou o ouvinte do ARView. O delegado ou a classe que implementa a interface do ouvinte receberá uma chamada ao seu método quando um quadro estiver disponível. Assim que isso acontecer, precisamos enviar esse quadro para o mundo do OpenTok.
Se você se lembra, já definimos o delegado do ARView e, no método didInitialize método ativamos o filtro do leão; agora precisamos informar ao ARView que queremos obter seus quadros de Video. Isso é feito usando o código abaixo:
func didInitialize() {
deepARView.switchEffect(withSlot: "effect", path: Bundle.main.path(forResource: "lion", ofType: ""))
deepARView.startFrameOutput(withOutputWidth: 640, outputHeight: 0, subframe: CGRect(x: 0, y: 0, width: 1, height: 1))
}A primeira linha é o que temos na primeira parte da postagem do blog, e com a segunda linha, estamos solicitando que o ARView chame outro método delegado com o conteúdo da AR View.
Depois de fazer isso, precisamos implementar o frameAvailable método, que será chamado sempre que um quadro de vídeo estiver pronto. Nesse método, enviaremos o conteúdo desse quadro para o capturador do OpenTok.
func frameAvailable(_ sampleBuffer: CMSampleBuffer!) {
autoreleasepool {
guard let pb = CMSampleBufferGetImageBuffer(sampleBuffer) else {
print("Invalid Image buffer")
return
}
deepARCapturer.pushFrame(pb)
}
}Você deve ter notado o pushFrame método na última linha; é nesse método que fazemos a ponte entre a visualização do DeepAR e o capturador de vídeo do OpenTok. Se você se lembra, deepARCapturer era o nome do capturador de vídeo personalizado que estávamos usando.
Essa é provavelmente a parte mais complicada deste post. Estamos utilizando as bibliotecas CoreImage e CoreVideo do iOS para obter as informações RGB do quadro.
Para que tudo funcione, precisamos implementar o método `pushFrame` no `DeepARVideoCapturer`, e ficará assim:
func pushFrame(_ pb: CVPixelBuffer) {
// 1
if otFrame == nil {
let otFormat = OTVideoFormat()
otFormat.pixelFormat = .ARGB
otFormat.imageWidth = UInt32(CVPixelBufferGetWidth(pb))
otFormat.imageHeight = UInt32(CVPixelBufferGetHeight(pb))
otFormat.bytesPerRow = [CVPixelBufferGetBytesPerRow(pb)]
otFrame = OTVideoFrame(format: otFormat)
}
guard let frame = otFrame else {
print("Error creating video frame")
return
}
// 2
CVPixelBufferLockBaseAddress(pb, .readOnly)
if let frameData = CVPixelBufferGetBaseAddress(pb) {
frame.orientation = .up
frame.clearPlanes()
frame.planes?.addPointer(frameData)
// 3
videoCaptureConsumer?.consumeFrame(frame)
}
CVPixelBufferUnlockBaseAddress(pb, .readOnly)
}Vamos, passo a passo, entender esse método. Como você pode ver, nós o dividimos em três seções.
Na Seção 1 (marcada com //1 acima), criamos uma nova instância de OTVideoFrame. Essa OTVideoFrame classe atua como um contêiner das informações do quadro de vídeo que usaremos mais tarde, quando enviarmos o quadro para o SDK do OpenTok. Normalmente, um quadro de vídeo contém informações sobre seu formato (RGB, YUV etc.), as dimensões, o número de bytes que uma linha do quadro ocupa e, obviamente, as informações do próprio quadro de vídeo.
Você pode se perguntar por que precisamos do tamanho em bytes por linha; os formatos de quadros de Video são complexos de explicar e existem diversos formatos, mas, geralmente, é útil saber qual é o tamanho do buffer de informações do quadro de Video. Basta multiplicar o número de bytes por linha pela altura da imagem para obter esse valor. Há casos em que o tamanho da linha não é calculado multiplicando-se o tamanho de um pixel pela largura da imagem, já que, às vezes, pixels vazios adicionais são inseridos como preenchimento.
Se esse último parágrafo estiver confuso para você, não se preocupe: você não precisa saber o que colocar ali, já que as funções do CoreVideo vão retornar o valor para você.
Voltando ao nosso código principal, como você pode ver, vamos reutilizar o “container” em cada quadro; leve em consideração que essa função será chamada cerca de 30 vezes por segundo.
Depois de criar uma instância do OTVideoFrame e preenchê-la com as informações que são constantes em todos os quadros de Video, podemos passar para a seção 2 (// 2).
Nesta seção, antes de fazer qualquer coisa, bloqueamos o conteúdo do quadro de Video para impedir que qualquer outra thread possa alterá-lo ou excluí-lo enquanto estamos acessando-o; podemos fazer isso chamando CVPixelBufferLockBaseAddress; depois disso, obtemos o ponteiro para as informações do quadro chamando CVPixelBufferGetBaseAddress e, por fim, adicionamos essas informações à nossa instância de OTVideoFrame.
Como mencionamos anteriormente, existem diferentes tipos de formatos de quadros de Video. Aqui, vamos usar o ARGB, que costuma ser chamado de formato de imagem por pixel. Isso significa que o buffer é composto por uma sucessão de informações de pixels codificadas com quatro valores: um para o canal alfa e os outros para R, G e B.
Existem outros formatos, como o YUV422, que é chamado de formato de imagem planar, e isso se deve ao fato de a imagem ser dividida em diferentes planos.
Estamos explicando isso para entender a frame.planes?.addPointer() chamada, já que estamos usando ARGB, e ele possui um plano; é assim que preenchemos nossa instância OTVideoFrame com os dados do quadro.
Por fim, já que temos uma instância completa do OTVideoFrame com as informações e o conteúdo do quadro de vídeo, basta enviá-la ao SDK do OpenTok para que seja transmitida pela rede aos demais participantes da sessão. E você faz isso na Seção 3 (// 3) com videoCaptureConsumer?.consumeFrame(frame) chamada.
videoCaptureConsumer é um membro do protocolo OTVideoCapture, e esse membro é definido quando o OTVideoCapturer é inicializado pelo SDK do OpenTok; sempre que você quiser enviar um quadro de vídeo para a sessão, é necessário chamar esse método.
Depois de todas essas etapas, você terá tudo pronto para criar um Publisher que enviará o conteúdo do DeepAR para uma sessão do OpenTok e impressionará a todos com sua aparência de leão.
Ainda estou começando
A equipe da Video API da Vonage está comprometida em investir em recursos de produtos de RA e em parcerias para garantir que nossos clientes tenham à disposição a melhor tecnologia e os melhores conhecimentos especializados ao criarem e aprimorarem experiências de vídeo interativas.
À medida que a Vonage expande nossa Video API, temos observado um aumento na demanda pelos serviços oferecidos por nossos parceiros. Estamos muito gratos por trabalhar com empresas fantásticas nas áreas de tecnologia, Applications e integração em todo o mundo. Com a Vonage, você pode aproveitar todo o leque de nossas APIs de comunicação e conquistar uma fatia maior do mercado.
Você também pode gostar de:
Tutorial: Como usar uma tela verde em JavaScript com o Vonage Video
Encontre um parceiro: Parceiros de APIs de comunicação
Compartilhar:
Roberto is a Full Stack Engineer on the OpenTok Client SDK team. He loves learning new bits of Android, iOS, Linux, Windows, you name it! In his free time, he is very passionate about programming languages, computer graphics, and video game development for current and old platforms like ZX Spectrum and Commodore 64.