https://d226lax1qjow5r.cloudfront.net/blog/blogposts/share-your-screen-with-the-vonage-video-api-dr/Blog_Share-Your-Screen_1200x600.png

Partagez votre écran avec l'API Video de Vonage

Publié le May 5, 2021

Temps de lecture : 5 minutes

Cette série de tutoriels explorera l'API vidéo de Vonage (anciennement TokBox OpenTok). Video API de Vonage (anciennement TokBox OpenTok) et ce que vous pouvez construire avec. L'API Video est très robuste et hautement personnalisable, et dans chaque article, nous montrerons comment mettre en œuvre une fonctionnalité spécifique à l'aide de l'API. Cette fois-ci, nous verrons comment ajouter le partage d'écran à votre chat audio-vidéo de base.

Comme cette application nécessitera un peu de code côté serveur, nous utiliserons Glitch pour faciliter l'installation. Vous pouvez également télécharger le code de ce projet Glitch et le déployer sur le serveur ou la plateforme d'hébergement de votre choix (il faudra probablement modifier la configuration en fonction des exigences de votre plateforme).

Nous n'utiliserons pas de frameworks frontaux pour cette série, mais uniquement du Javascript vanille, afin de nous concentrer sur l'API Video elle-même. À la fin de ce tutoriel, vous devriez être en mesure de partager votre écran avec la personne dans votre chat vidéo.

Screenshot of active screen-sharing

Le code final de cette application peut être trouvé dans ce dépôt GitHub ou remixé sur Glitch.

Conditions préalables

Avant de commencer, vous aurez besoin d'un compte Video API de Vonage, que vous pouvez créer gratuitement ici. Vous aurez également besoin de Node.js installé (si vous n'utilisez pas Glitch).

Ce tutoriel s'appuie sur le premier billet d'introduction de la série : Construire un chat vidéo de base. Si vous utilisez l'API Video pour la première fois, nous vous conseillons vivement de lire cet article car il couvre la configuration de base suivante :

  • Créer un projet Video API de Vonage

  • S'installer sur Glitch

  • Structure de base du projet

  • Initialiser une session OpenTok

  • Connexion à la session, abonnement et publication

  • Styles de mise en page de base pour un chat vidéo

Se préparer à de multiples flux de publications

Dans l'application précédente, votre navigateur se connectait à la session et publiait un seul flux (votre caméra). Cependant, avec l'ajout du partage d'écran, il se peut que vous publiiez deux flux dans la même session. Pour ce faire, dans public/client.jsdéplacez l'élément session dans une variable globale.

Avant :

function initializeSession(apiKey, sessionId, token) {
  const session = OT.initSession(apiKey, sessionId);
  // more code below
}

Après :

let session;
function initializeSession(apiKey, sessionId, token) {
  session = OT.initSession(apiKey, sessionId);
  // more code below
}

Dans views/index.htmlvous devez fournir un élément de remplacement pour la vidéo de partage d'écran à afficher et un bouton pour déclencher le partage. Créez également un bouton pour arrêter le partage d'écran, qui sera utilisé ultérieurement :

<main>
  <!-- This element is new -->
  <div id="screen" class="screen"></div>

  <!-- These two elements already exist from the first tutorial -->
  <div id="subscriber" class="subscriber"></div>
  <div id="publisher" class="publisher"></div>

  <!-- These are both new too -->
  <button id="startScreenShare" class="screen-share">Share Screen</button>
  <button id="stopScreenShare" class="screen-share hidden">Stop Sharing Screen</button>
</main>

Vérifier les possibilités de partage d'écran

Lorsque l'on appuie sur le bouton de partage, l'application doit d'abord vérifier qu'elle peut partager l'écran. Ajoutez ce code au bas de client.js:

const startShareBtn = document.getElementById("startScreenShare");
startShareBtn.addEventListener("click", event => {
  OT.checkScreenSharingCapability(response => {
    if (!response.supported || response.extensionRegistered === false) {
      alert("Screen sharing not supported");
    } else if (response.extensionInstalled === false) {
      alert("Browser requires extension");
    } else {
      // Share screen code
    }
  });
});

La méthode OT.checkScreenSharingCapability() renvoie des informations sur les capacités du navigateur actuel. Sur la base de ces informations, vous pouvez déterminer si le navigateur ne le prend pas en charge, s'il nécessite une extension dans les anciens navigateurs ou s'il peut partager en utilisant les API natives.

Dans Chrome 71 et les versions antérieures, Firefox 51 et les versions antérieures, et Opera 58 et les versions antérieures, l'utilisateur devra installer une extension pour partager son écran. Ce billet ne couvre pas les extensions, mais vous pouvez en savoir plus dans la documentation.

Partagez votre écran

Ajoutez le code suivant dans le bloc d'instructions else ci-dessus :

const screenSharePublisher = OT.initPublisher(
  "screen",
  {
    insertMode: "append",
    width: "100%",
    height: "100%",
    videoSource: "screen",
    publishAudio: true
  },
  handleCallback
);
session.publish(screenSharePublisher, handleCallback);

Le premier paramètre est le id de l'élément HTML, que la vidéo de l'éditeur va remplir. Pour les navigateurs modernes, le partage d'un écran s'apparente au partage d'une caméra. En ajoutant videoSource: "screen" à vos options d'éditeur, le navigateur demandera les autorisations correctes en votre nom. publishAudio est facultatif.

Une fois le nouvel éditeur créé, vous pouvez le publier dans notre session.

Video application with screen sharing, but it is not displaying correctly

Cela fonctionne, mais comme vous l'avez peut-être remarqué, la vidéo de partage d'écran est repoussée sur le côté de la fenêtre et les boutons sont mal placés. Ajoutez ce qui suit à votre fichier public/style.css fichier :

.screen {
  width: 100%;
  height: 100%;
  display: flex;
}
.screen-share {
  position: absolute;
  bottom: 0;
  right: 0;
}
.hidden {
  display: none;
}

Arrêtez de partager votre écran

Pour arrêter le partage d'un flux publié, vous devez accéder à la variable à laquelle il est assigné. Au-dessus de l'écouteur d'événement, créez une variable screenSharePublisher vide :

let screenSharePublisher;

Dans l'écouteur d'événements, assignez OT.initPublisher(...) à la nouvelle variable en supprimant le mot-clé const en supprimant le mot-clé

En bas de client.js ajoutez un écouteur d'événements pour le bouton d'arrêt du partage :

const stopShareBtn = document.getElementById("stopScreenShare");
stopShareBtn.addEventListener("click", event => {
  screenSharePublisher.destroy();
});

Corriger les problèmes de mise en page restants

À ce stade, votre application devrait ressembler à ceci :

Slightly better but still somewhat broken layout

C'est un peu mieux que le début, mais cela semble toujours cassé. Réparons-le avec un peu de CSS et de Javascript (pour faire basculer les classes CSS requises).

Supprimons les styles originaux .screen de style.css:

/* We don't need these any more */
.screen {
  width: 100%;
  height: 100%;
  display: flex;
}

Modifier les styles de .subscriber dans le fichier style.css comme suit :

.subscriber,
.screen.pub-active,
.screen.sub-active {
  width: 100%;
  height: 100%;
  display: flex;
}
.screen.sub-active ~ .subscriber,
.screen.pub-active ~ .subscriber {
  position: absolute;
  width: 25vmin;
  height: 25vmin;
  min-width: 8em;
  min-height: 8em;
  align-self: flex-end;
  right: 0;
}

Ce que nous faisons ici, c'est que l'élément qui contient le flux de partage d'écran occupe toute la surface de la fenêtre lorsqu'il est actif, tandis que le flux de la caméra se trouve dans le coin inférieur droit de la fenêtre.

Ensuite, nous devons nous assurer que les bonnes classes sont ajoutées aux éléments appropriés lorsque le partage d'écran commence :

screenSharePublisher = OT.initPublisher(
  "screen",
  {
    insertMode: "append",
    width: "100%",
    height: "100%",
    videoSource: "screen",
    publishAudio: true
  },
  handleCallback
);
session.publish(screenSharePublisher, handleCallback);
// CSS classes when screen-sharing starts
startShareBtn.classList.toggle("hidden");
stopShareBtn.classList.toggle("hidden");
document.getElementById("screen").classList.add("pub-active");

L'inverse doit se produire lorsque le partage d'écran s'arrête :

stopShareBtn.addEventListener("click", event => {
  screenSharePublisher.destroy();
  
  // CSS classes when screen-sharing stops
  startShareBtn.classList.toggle("hidden");
  stopShareBtn.classList.toggle("hidden");
  document.getElementById("screen").classList.remove("pub-active");
});

Maintenant, tout se passe bien lorsque vous démarrez le partage d'écran. Mais pour la personne qui se trouve à l'autre bout de l'appel, la mise en page est encore un peu défectueuse.

layout is broken for the person viewing the screenshare

Pour y remédier, modifions l'écouteur d'événements streamCreated qui s'abonne aux flux nouvellement créés. Nous allons vérifier si le flux créé est un flux de caméra ou un flux de partage d'écran. S'il s'agit d'un partage d'écran, nous lui ajouterons la classe sub-active à la classe CSS.

Avant :

session.connect(token, error => {
  // Other code not included for brevity
  // Subscribe to a newly created stream
  session.on("streamCreated", event => {
    session.subscribe(
      event.stream,
      "subscriber",
      {
        insertMode: "append",
        width: "100%",
        height: "100%"
      },
      handleCallback
    );
  });
});

Après :

// Subscribe to a newly created stream
session.on("streamCreated", event => {
  const streamContainer =
    event.stream.videoType === "screen" ? "screen" : "subscriber";
  session.subscribe(
    event.stream,
    streamContainer,
    {
      insertMode: "append",
      width: "100%",
      height: "100%"
    },
    handleScreenShare(event.stream.videoType)
  );
});
// Function to handle screen share layout
function handleScreenShare(streamType, error) {
  if (error) {
    console.log("error: " + error.message);
  } else {
    if (streamType === "screen") {
      document.getElementById("screen").classList.add("sub-active");
    }
  }
}

Nous devrons également ajouter un récepteur d'événements pour l'arrêt du partage d'écran :

session.on("streamDestroyed", event => {
  document.getElementById("screen").classList.remove("sub-active");
});

Vous devriez obtenir quelque chose comme ceci pour la personne qui reçoit le partage d'écran :

No longer broken layout

Après tout cela, votre fichier client.js ressemblerait à ceci :

let session;
fetch(location.pathname, { method: "POST" })
  .then(res => {
    return res.json();
  })
  .then(res => {
    const apiKey = res.apiKey;
    const sessionId = res.sessionId;
    const token = res.token;
    initializeSession(apiKey, sessionId, token);
  })
  .catch(handleCallback);
function initializeSession(apiKey, sessionId, token) {
  // Create a session object with the sessionId
  session = OT.initSession(apiKey, sessionId);
  // Create a publisher
  const publisher = OT.initPublisher(
    "publisher",
    {
      insertMode: "append",
      width: "100%",
      height: "100%"
    },
    handleCallback
  );
  // Connect to the session
  session.connect(token, error => {
    // If the connection is successful, initialize the publisher and publish to the session
    if (error) {
      handleCallback(error);
    } else {
      session.publish(publisher, handleCallback);
    }
  });
  // Subscribe to a newly created stream
  session.on("streamCreated", event => {
    const streamContainer =
      event.stream.videoType === "screen" ? "screen" : "subscriber";
    session.subscribe(
      event.stream,
      streamContainer,
      {
        insertMode: "append",
        width: "100%",
        height: "100%"
      },
      handleScreenShare(event.stream.videoType)
    );
  });
  session.on("streamDestroyed", event => {
    document.getElementById("screen").classList.remove("sub-active");
  });
}
// Function to handle screenshare layout
function handleScreenShare(streamType, error) {
  if (error) {
    console.log("error: " + error.message);
  } else {
    if (streamType === "screen") {
      document.getElementById("screen").classList.add("sub-active");
    }
  }
}
// Callback handler
function handleCallback(error) {
  if (error) {
    console.log("error: " + error.message);
  } else {
    console.log("callback success");
  }
}
let screenSharePublisher;
const startShareBtn = document.getElementById("startScreenShare");
startShareBtn.addEventListener("click", event => {
  OT.checkScreenSharingCapability(response => {
    if (!response.supported || response.extensionRegistered === false) {
      alert("Screen sharing not supported");
    } else if (response.extensionInstalled === false) {
      alert("Browser requires extension");
    } else {
      screenSharePublisher = OT.initPublisher(
        "screen",
        {
          insertMode: "append",
          width: "100%",
          height: "100%",
          videoSource: "screen",
          publishAudio: true
        },
        handleCallback
      );
      session.publish(screenSharePublisher, handleCallback);
      startShareBtn.classList.toggle("hidden");
      stopShareBtn.classList.toggle("hidden");
      document.getElementById("screen").classList.add("pub-active");
    }
  });
});
const stopShareBtn = document.getElementById("stopScreenShare");
stopShareBtn.addEventListener("click", event => {
  screenSharePublisher.destroy();
  startShareBtn.classList.toggle("hidden");
  stopShareBtn.classList.toggle("hidden");
  document.getElementById("screen").classList.remove("pub-active");
});

Quelle est la prochaine étape ?

Le code final de Glitch et sur GitHub contient tout ce que nous avons couvert dans ce post assez long mais réorganisé, de sorte que le code est plus propre et plus facile à maintenir. N'hésitez pas à remixer ou cloner le code et à vous amuser avec.

Il existe d'autres fonctionnalités que nous pouvons créer avec l'API Video de Vonage, qui seront abordées dans de futurs tutoriels, mais en attendant, vous pouvez en savoir plus sur notre site de documentation complet. Si vous rencontrez des problèmes ou si vous avez des questions, contactez-nous sur notre Communauté Slack. Merci pour votre lecture !

Partager:

https://a.storyblok.com/f/270183/384x384/46621147f0/huijing.png
Hui Jing ChenAnciens de Vonage

Hui Jing est développeuse chez Nexmo. Elle a un amour immodéré pour le CSS et la typographie, et est généralement passionnée par tout ce qui touche au web.