https://d226lax1qjow5r.cloudfront.net/blog/blogposts/create-custom-ar-filters-with-vonage-video-api-and-deepar/Blog_DeepAR_VideoAPI-2_1200x600.png

Créez des filtres de RA personnalisés avec l'API Video de Vonage et DeepAR

Publié le November 19, 2020

Temps de lecture : 13 minutes

L'augmentation à l'aide de l'IA est l'avenir des appels vidéo. Elle nous aidera à briser la glace (virtuelle), à naviguer dans les cas d'utilisation émergents de la vidéo interactive, comme le shopping et l'assistance à distance, et à créer des expériences entièrement nouvelles. Les futurs inventeurs de ces expériences sont probablement "assis" dans une salle de classe virtuelle, façonnés par la vidéo virtuelle comme aucune génération avant eux.

En tant que développeurs de l'API Video de Vonage, vous pouvez intégrer notre API Video avec le SDK DeepAR pour enrichir l'expérience d'engagement vidéo de vos utilisateurs.

Vous pouvez rendre les appels vidéo plus professionnels en faisant abstraction de l'arrière-plan - en remplaçant, en brouillant ou en pixellisant les objets - ou améliorer l'expérience de l'utilisateur en améliorant l'éclairage et en créant des effets subtils de teintes de peau.

Vous pouvez aussi vous amuser avec une grande variété de filtres animés de DeepAR.

Augmented Reality filters in actionAugmented Reality filters in action

La réalité augmentée dans notre vie quotidienne

Il y a de fortes chances que vous ayez déjà participé à une réunion Video, qu'il s'agisse d'une réunion de travail, d'une consultation médicale ou d'une réunion de famille.

Dans ce nouveau paradigme de réunions axées sur la vidéo, de nombreuses nouvelles Applications peuvent ajouter de la valeur à la communication vidéo. Passons en revue quelques façons courantes d'utiliser l'augmentation pour améliorer l'expérience des utilisateurs et nous aider à être plus efficaces dans nos interactions à distance :

Abstraction de l'arrière-plan

L'une des améliorations apportées à la communication Video consiste à faire abstraction de tout ce qui se trouve à l'arrière-plan de l'utilisateur grâce à une simple fonction de flou, de pixellisation ou de remplacement de l'arrière-plan. Les avantages sont les suivants :

  • activer la confidentialité de l'appelant

  • faciliter l'engagement des téléspectateurs en éliminant les distractions

  • créer des expériences de marque

Augmentation du nombre de locuteurs

Un autre exemple pour faire passer les appels vidéo au niveau supérieur avec la RA est d'appliquer des filtres aux locuteurs de premier plan. La mise en œuvre de ce type de filtres permet à vos utilisateurs :

  • Détendez-vous lors de l'appel Video avec des filtres de lumière, de teint et de beauté

  • ravir et divertir avec des animojis amusants

  • interagir en temps réel avec des objets en 3D et même avec de la peinture faciale virtuelle

A dog face AR filter in useA dog face AR filter in use

La flexibilité de l'API Video de Vonage rend cela possible lors de l'intégration avec des partenaires de RA comme DeepAR. Dans cet article de blog, nous montrerons comment rendre les cas d'utilisation ci-dessus possibles en utilisant une combinaison des deux API.

Qu'est-ce que DeepAR ?

DeepAR est un moteur de réalité augmentée mobile et optimisé pour HTML5 pour la réalité augmentée, les filtres de visage, la segmentation de l'arrière-plan, le maquillage, les filtres de beauté et les animoji.

Le SDK DeepAR SDK permet aux développeurs d'accéder au moteur DeepAR, de gérer la prise en charge inter-appareils et s'accompagne d'un outil DeepAR Studio pour vous aider à créer des ressources de réalité augmentée.

Utilisation de DeepAR

Pour ajouter le framework DeepAR SDK à votre application iOS, vous devez télécharger le fichier zip depuis leur site web, https://developer.deepar.ai/. Une fois que vous avez le fichier zip, vous devez le décompresser et faire glisser le fichier du framework dans votre projet Xcode.

XCode

N'oubliez pas de régler le paramètre embed du framework sur "Embed & Sign", sinon l'application risque de ne pas trouver la bibliothèque au moment de l'exécution.

Une fois ce réglage effectué, l'étape suivante consiste à se rendre à l'adresse suivante https://developer.deepar.ai/ et de créer un projet pour obtenir la clé d'application dont vous aurez besoin plus tard.

Ajout de lions à l'entrée vidéo capturée

Dans cet article de blog, nous allons créer une UIView où vous montrerez le contenu de votre caméra frontale, et votre visage, lorsqu'il sera détecté, sera augmenté d'un lion cool.

Si vous souhaitez voir tout le code de ce billet en un seul endroit, vous pouvez le trouver sur le site DeepAR GitHub.

Dans le code, vous aurez besoin de deux classes ; l'une est le CameraController du DeepAR SDK, cette classe est chargée d'accéder à la caméra de l'appareil et d'en récupérer les images. Une fois qu'elle dispose d'un flux vidéo, elle l'envoie à l'instance ARView, qui est l'autre classe que vous devez instancier.

ARView est chargé d'afficher le contenu de la caméra avec les filtres AR appliqués. ARView est un enfant UIView normal, vous devez donc l'ajouter à toute vue parentale dans la hiérarchie des vues de votre application.

Sachant cela, le code pourrait ressembler à ceci :

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()

Dans le code ci-dessus, vous créez d'abord le CameraController, puis vous créez l'instance ARView en l'utilisant comme cadre en plein écran puisque nous allons montrer qu'elle occupe tout l'écran.

Veuillez noter que nous attribuons à self en tant que délégué de l'ARView, vous devez donc mettre en œuvre le protocole ARViewDelegate et vous y conformer. Nous en aurons besoin plus tard.

Une fois que vous avez les deux instances, vous assignez la propriété ARView de l'instance CameraController à notre vue et l'insérez dans notre fichier parentView.

Il ne reste plus qu'à initialiser la vue et à capturer la vidéo à partir de la caméra en appelant startCamera.

Si vous exécutez votre code, vous remarquerez qu'il n'y a pas de 🦁 sur votre visage, et ce parce que nous n'avons pas encore activé l'effet.

Pour ce faire, vous devez implémenter didInitializeune méthode de l'ARViewDelegate, que nous appellerons une fois que l'ARView aura fini de s'initialiser, ce qui nous permettra d'activer le filtre lion.

func didInitialize() {
  deepARView.switchEffect(withSlot: "effect", path: Bundle.main.path(forResource: "lion", ofType: ""))
}

Pour que cela fonctionne, vous devez ajouter un fichier appelé "lion" à votre projet. Vous pouvez le trouver dans le pack de filtres gratuit que vous pouvez obtenir à l'adresse suivante https://developer.deepar.ai/downloads. Une fois que vous l'avez téléchargé, vous devez faire glisser le fichier "lion" vers le dossier racine du projet Xcode et vérifier qu'il a pour cible votre application, de sorte qu'il est regroupé avec elle.

XCodeXCode

Si vous exécutez l'application à ce stade, vous devriez voir votre visage avec une superposition de lion cool qui suit tous vos mouvements et gestes.

LionLion

OpenTok et pilotes vidéo personnalisés

La plupart des développeurs interagissent avec l'API Video de Vonage via le SDK OpenTok. L'une des caractéristiques les plus intéressantes du SDK est la possibilité de créer votre pilote vidéo pour envoyer n'importe quel type de contenu vidéo à la session OpenTok à laquelle votre éditeur est connecté.

Les pilotes Video peuvent être divisés en deux parties différentes :

  • D'une part, nous avons le capteur vidéo qui, comme son nom l'indique, doit capturer la vidéo à partir de n'importe quelle source (ou produire la sienne d'une manière ou d'une autre) et fournir au SDK les images vidéo qui vont être envoyées.

  • De l'autre, nous avons le moteur de rendu vidéo, et comme vous l'avez probablement deviné, il est chargé de rendre les images vidéo qui arrivent à distance dans une session OpenTok par l'intermédiaire d'un abonné.

Si vous avez utilisé le SDK OpenTok, vous aurez probablement remarqué que vous n'avez pas besoin de vous occuper de ces classes dans un scénario typique. En effet, le SDK OpenTok est livré avec des capteurs et des moteurs de rendu par défaut qui capturent la vidéo à partir de la caméra système par défaut et rendent les images vidéo distantes à l'aide de la technologie graphique de chaque plateforme, qu'il s'agisse de Metal, d'OpenGL ou de DirectX.

Les pilotes vidéo sont très puissants. Vous pouvez créer un pilote vidéo pour envoyer n'importe quel contenu Video. Par exemple, vous pouvez capturer la sortie de n'importe quel moteur de jeu et envoyer ces images vidéo au SDK OpenTok, et vous diffuserez le contenu de votre jeu à n'importe quel participant d'une session OpenTok. Vous pouvez également appliquer n'importe quel filtre de rendu, comme le noir et blanc ou la détection des bords, afin que chaque abonné ait un aspect différent.

Création d'un capteur vidéo personnalisé OpenTok

Bien que la création d'un capteur vidéo personnalisé puisse sembler être une tâche compliquée, elle est probablement plus simple que vous ne l'imaginez.

Il suffit d'implémenter une interface, d'étendre une classe ou de se conformer à un protocole en fonction du langage et de la plateforme de votre choix. Bien que, comme vous l'avez vu ci-dessus, nous utilisons swift et iOS dans les exemples de code source de ce billet.

Dans cette classe, vous devrez implémenter ou remplacer certaines méthodes de base contrôlant le cycle de vie du capteur. Vous devrez implémenter init, startCapture, stopCapture, isCaptureStarted ainsi qu'une méthode pour spécifier les paramètres du capteur qui consiste à spécifier la hauteur, la largeur, la fréquence d'images et le format de pixels des images vidéo que le capteur va envoyer.

Une fois ces méthodes mises en œuvre, vous devrez alimenter le capteur en images. Selon la plateforme, cela peut être différent, mais en général, il suffit d'appeler une méthode avec les données de la trame vidéo.

Voyons à quoi pourrait ressembler une première mise en œuvre,

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
  }
}

Vous trouverez ci-dessus le code nécessaire à la création d'un capteur personnalisé. Comme vous pouvez le voir, vous devez implémenter le protocole OTVideoCapture, qui possède des méthodes qui seront appelées lorsque le capteur vidéo doit être initialisé, démarré ou arrêté. Il est très courant d'avoir un indicateur interne pour savoir quand la capture a commencé, et c'est ce que nous faisons dans cette implémentation de base. Nous mettrons à jour cet indicateur dans les méthodes de démarrage et d'arrêt.

Vous aurez remarqué que cette classe hérite de NSObjectcar ce n'est pas très courant dans les classes swift, qui héritent uniquement d'Object. La raison en est que le protocole OTVideoCapture hérite du protocole NSObject, principalement parce que la base de code de l'OpenTok SDK est principalement constituée d'Objective-C et que dans ce langage, tout hérite de NSObject.

Une fois que vous avez une telle classe, l'étape suivante consiste à indiquer à l'éditeur qu'au lieu d'utiliser le capteur par défaut, il doit utiliser notre classe. Le code pour cela ressemble à ceci :

let settings = OTPublisherSettings()
settings.name = UIDevice.current.name
settings.videoCapture = DeepARVideoCapturer()
otPublisher = OTPublisher(delegate: self, settings: settings)

Le capturer que nous avons construit dans le code snip ci-dessus n'envoie encore rien, puisqu'il ne contient que du code d'initialisation. Si vous essayez d'utiliser ce que nous avons maintenant, cela devrait fonctionner, mais vous ne publierez que des images noires. La prochaine étape est de savoir comment envoyer des images.

Mais nous allons retarder cette partie jusqu'à ce que nous ayons des images à envoyer, et ces images seront la sortie de notre vue DeepAR.

Intégrer DeepAR et OpenTok

Nous avons atteint la dernière partie de l'article de blog, dans la première partie, nous avons vu comment construire un capteur vidéo de base, dans la deuxième partie, nous avons vu comment comment l'ARView de DeepAR avec un filtre AR d'un lion remplaçant votre visage. La seule chose qui manquait à notre Video capturer personnalisé était l'envoi de trames vidéo, il semble donc que nous ayons tout en place pour la dernière étape.

Dans cette étape, nous allons relier les deux mondes ; nous devons faire deux choses. Tout d'abord, nous devons obtenir les images vidéo produites par ARView, et ensuite, nous devons les envoyer en utilisant le capteur vidéo que nous avons construit.

La première étape consiste à obtenir une image de l'ARView. Cela peut être fait très rapidement en définissant le délégué ou l'auditeur de l'ARView. Le délégué ou la classe implémentant l'interface d'écoute recevra un appel à sa méthode lorsqu'une image sera disponible. Une fois que cela se produit, nous devons envoyer cette image au monde OpenTok.

Si vous vous souvenez, nous avons déjà défini le délégué de ARView, et dans sa méthode didInitialize nous avons activé le filtre lion, nous devons maintenant indiquer à ARView que nous voulons obtenir ses images vidéo. Cela se fait à l'aide du code ci-dessous :

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))
}

La première ligne est ce que nous avons dans la première partie de l'article de blog, et avec la deuxième ligne, nous demandons à ARView d'appeler une autre méthode déléguée avec le contenu de l'AR View.

Après cela, nous devons implémenter la méthode frameAvailable qui sera appelée à chaque fois qu'une image vidéo sera prête. Dans cette méthode, nous enverrons le contenu de l'image au capteur OpenTok.

func frameAvailable(_ sampleBuffer: CMSampleBuffer!) {
  autoreleasepool {
    guard let pb = CMSampleBufferGetImageBuffer(sampleBuffer) else {
      print("Invalid Image buffer")
      return
    }
    deepARCapturer.pushFrame(pb)
  }
}

Vous avez peut-être remarqué la méthode pushFrame dans la dernière ligne, c'est dans cette méthode que nous faisons le lien entre la vue DeepAR et le capteur vidéo OpenTok, si vous vous souvenez, deepARCapturer était le nom du capteur vidéo personnalisé que nous utilisions.

C'est probablement la partie la plus compliquée de ce billet. Nous utilisons les frameworks iOS CoreImage et CoreVideo pour obtenir les informations RVB de l'image.

Pour que tout fonctionne, nous devons implémenter la fonction pushFrame dans le DeepARVideoCapturer, qui ressemblera à ceci :

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)
}

Allons-y pas à pas pour comprendre cette méthode. Comme vous pouvez le constater, nous l'avons divisée en trois sections.

Dans la section 1 (marquée par //1 ci-dessus), nous construisons une nouvelle instance de OTVideoFrame. Cette classe OTVideoFrame sert de conteneur pour les informations relatives à la trame vidéo que nous utiliserons plus tard lorsque nous transmettrons la trame au SDK OpenTok. En règle générale, une image vidéo contient des informations sur son format (RVB, YUV, etc.), ses dimensions, le nombre d'octets que pèse une ligne de l'image vidéo et, bien entendu, les informations relatives à l'image vidéo.

Vous vous demandez peut-être pourquoi nous avons besoin de la taille de l'octet de la ligne, les formats de trame vidéo sont complexes à expliquer, et il existe différents formats, mais en général, il est utile de savoir quelle est la taille du tampon d'information de la trame vidéo. Vous pouvez multiplier le nombre d'octets par ligne par la hauteur de l'image, et vous l'aurez. Il arrive que la taille de la ligne ne soit pas calculée en multipliant la taille d'un pixel par la largeur de l'image, car des pixels vides supplémentaires sont parfois ajoutés en guise de remplissage.

Si ce dernier paragraphe vous semble confus, ne vous inquiétez pas, vous ne savez pas ce qu'il faut y mettre, car les fonctions de CoreVideo le renvoient pour vous.

Pour revenir à notre noyau, comme vous pouvez le voir, nous allons réutiliser le "container" dans chaque image, en tenant compte du fait que cette fonction sera appelée environ 30 fois par seconde.

Après avoir créé une instance de OTVideoFrame et l'avoir remplie avec les informations qui sont constantes dans toutes les images vidéo, nous pouvons passer à la section 2 (// 2).

Dans cette section, avant de faire quoi que ce soit, nous verrouillons le contenu de l'image Video pour éviter qu'un autre thread puisse le modifier ou le supprimer pendant que nous y accédons, nous pouvons le faire en appelant CVPixelBufferLockBaseAddressEnsuite, nous obtenons le pointeur sur les informations de l'image en appelant CVPixelBufferGetBaseAddress, et enfin, nous ajoutons ces informations à notre instance OTVideoFrame.

Comme nous l'avons dit précédemment, il existe différents types de formats d'image vidéo. Ici, nous allons utiliser le format ARGB, qui est généralement appelé format d'image pixel. Cela signifie que la mémoire tampon est composée d'une succession d'informations sur les pixels codées avec quatre valeurs, une pour le canal Alpha et d'autres pour R, G et B.

Il existe d'autres formats comme YUV422, qui est appelé format d'image planaire, parce que l'image est divisée en différents plans.

Nous expliquons cela pour comprendre l'appel frame.planes?.addPointer() puisque nous utilisons ARGB et qu'il n'y a qu'un seul plan, c'est ainsi que nous remplissons notre instance OTVideoFrame avec les données de la trame.

Enfin, ayant une instance OTVideoFrame complète avec les informations et le contenu de la trame vidéo, il nous suffit de l'envoyer au SDK OpenTok pour qu'elle soit transmise sur le réseau au reste des participants à la session. Et vous le faites dans la section 3 (// 3) avec videoCaptureConsumer?.consumeFrame(frame) appel.

videoCaptureConsumer est un membre du protocole OTVideoCapture, et ce membre est défini lorsque le protocole OTVideoCapture est initialisé par le SDK OpenTok. OTVideoCapturer est initialisé par le SDK OpenTok, chaque fois que vous souhaitez envoyer une image vidéo à la session, vous devez appeler cette méthode.

Après toutes ces étapes, vous avez tout ce qu'il faut pour construire un Publisher qui enverra le contenu de DeepAR magic vers une session OpenTok et impressionnera tout le monde avec votre apparence de lion.

Pour commencer

L'équipe Video API de Vonage s'est engagée à faire des investissements dans les fonctionnalités des produits AR et les partenariats pour s'assurer que nos clients disposent de la meilleure technologie et de la meilleure expertise lorsqu'ils construisent et améliorent des expériences vidéo interactives.

Au fur et à mesure que Vonage développe son Video API, nous avons constaté une augmentation de la demande pour les services fournis par nos partenaires. Nous sommes reconnaissants de travailler avec de fantastiques entreprises de technologie, d'application et d'intégration à travers le monde. Avec Vonage, vous pouvez tirer parti de l'ensemble de nos API de communication et obtenir une part plus importante du gâteau.

Vous pouvez aussi aimer :

Partager:

https://a.storyblok.com/f/270183/400x400/0444469466/roberto-perez-cubero.png
Roberto Perez Cubero

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.