Fonctionnalités média de Live Share

La vidéo et l’audio sont des parties instrumentales du monde moderne et du lieu de travail. Nous avons entendu de nombreux commentaires sur le fait que nous pouvons faire davantage pour améliorer la qualité, l’accessibilité et la protection des licences de regarder des vidéos ensemble dans les réunions.

Le Kit de développement logiciel (SDK) Live Share permet une synchronisation multimédia robuste pour n’importe quel élément HTML <video> et <audio> avec seulement quelques lignes de code. En synchronisant le multimédia à l’état du lecteur et de la couche de contrôles de transport, vous pouvez attribuer individuellement des vues et des licences, tout en fournissant la qualité la plus élevée possible disponible via votre application.

Installer

Le média Live Share est un package JavaScript publié sur npm, que vous pouvez télécharger via npm ou yarn. Vous devez également installer ses dépendances homologues, notamment @microsoft/live-share, fluid-framework et @fluidframework/azure-client. Si vous utilisez Live Share dans votre application d’onglet, vous devez également installer @microsoft/teams-js la version ou une version 2.11.0 ultérieure.

npm install @microsoft/live-share @microsoft/live-share-media fluid-framework @fluidframework/azure-client --save
npm install @microsoft/teams-js --save

OR

Pour ajouter la dernière version du Kit de développement logiciel (SDK) à votre application à l’aide de Yarn :

yarn add @microsoft/live-share @microsoft/live-share-media fluid-framework @fluidframework/azure-client
yarn add @microsoft/teams-js

Vue d’ensemble de la synchronisation des multimédias

Le Kit de développement logiciel (SDK) Live Share a deux classes principales liées à la synchronisation des multimédias :

Classes Description
LiveMediaSession Objet dynamique personnalisé conçu pour coordonner les contrôles de transport multimédia et l’état de lecture dans des flux multimédias indépendants.
MediaPlayerSynchronizer Synchronise tout objet qui implémente l’interface IMediaPlayer , y compris HTML5 <video> et <audio> - à l’aide LiveMediaSessionde .

Exemple :

<body>
  <video id="player">
    <source src="YOUR_VIDEO_SRC" type="video/mp4" />
  </video>
</body>
import {
  LiveShareClient,
  UserMeetingRole,
  MediaPlayerSynchronizerEvents,
} from "@microsoft/live-share";
import { LiveMediaSession } from "@microsoft/live-share-media";
import { LiveShareHost } from "@microsoft/teams-js";

// Setup the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
  initialObjects: { mediaSession: LiveMediaSession },
};
const { container } = await liveShare.joinContainer(schema);
const { mediaSession } = container.initialObjects;

// Get the player from your document and create synchronizer
const player = document.getElementById("player");
const synchronizer = mediaSession.synchronize(player);

// Listen for groupaction events (optional)
synchronizer.addEventListener(MediaPlayerSynchronizerEvents.groupaction, async (evt) => {
  // See which user made the change (e.g., to display a notification)
  const clientInfo = await synchronizer.mediaSession.getClientInfo(evt.details.clientId);
});

// Define roles you want to allow playback control and start sync
const allowedRoles = [UserMeetingRole.organizer, UserMeetingRole.presenter];
await mediaSession.initialize(allowedRoles);

écoute LiveMediaSession automatiquement les modifications apportées à l’état de lecture du groupe. MediaPlayerSynchronizer écoute les modifications d’état émises par LiveMediaSession et les applique à l’objet fourni IMediaPlayer , tel qu’un élément HTML5 <video> ou <audio> un élément . Pour éviter les modifications d’état de lecture qu’un utilisateur n’a pas intentionnellement initiées, telles qu’un événement de mémoire tampon, nous devons appeler des contrôles de transport via le synchronisateur, plutôt que directement par le lecteur.

Exemple :

<body>
  <video id="player">
    <source src="YOUR_VIDEO_SRC" type="video/mp4" />
  </video>
  <div class="player-controls">
    <button id="play-button">Play</button>
    <button id="pause-button">Pause</button>
    <button id="restart-button">Restart</button>
    <button id="change-track-button">Change track</button>
  </div>
</body>
// ...

document.getElementById("play-button").onclick = async () => {
  // Will play for all users in the session.
  // If using role verification, this will throw an error if the user doesn't have the required role.
  await synchronizer.play();
};

document.getElementById("pause-button").onclick = async () => {
  // Will pause for all users in the session.
  // If using role verification, this will throw an error if the user doesn't have the required role.
  await synchronizer.pause();
};

document.getElementById("restart-button").onclick = async () => {
  // Will seek for all users in the session.
  // If using role verification, this will throw an error if the user doesn't have the required role.
  await synchronizer.seekTo(0);
};

document.getElementById("change-track-button").onclick = () => {
  // Will change the track for all users in the session.
  // If using role verification, this will throw an error if the user doesn't have the required role.
  synchronizer.setTrack({
    trackIdentifier: "SOME_OTHER_VIDEO_SRC",
  });
};

Remarque

Bien que vous puissiez utiliser l’objet LiveMediaSession pour synchroniser manuellement les médias, il est généralement recommandé d’utiliser le MediaPlayerSynchronizer. Selon le lecteur que vous utilisez dans votre application, vous devrez peut-être créer un shim délégué pour que l’interface de votre lecteur web corresponde à l’interface IMediaPlayer .

Suspensions et points d’attente

Capture d’écran montrant une synchronisation de suspension avec le présentateur.

Si vous souhaitez suspendre temporairement la synchronisation de l’objet LiveMediaSession, vous pouvez utiliser des suspensions. Un MediaSessionCoordinatorSuspension objet est local par défaut, ce qui peut être utile dans les cas où un utilisateur peut vouloir rattraper quelque chose qu’il a manqué, faire une pause, etc. Si l’utilisateur met fin à la suspension, la synchronisation reprend automatiquement.

// Suspend the media session coordinator
const suspension = mediaSession.coordinator.beginSuspension();

// End the suspension when ready
suspension.end();

Lorsque vous commencez une suspension, vous pouvez également inclure un paramètre CoordinationWaitPoint facultatif qui permet aux utilisateurs de définir les horodatages dans lesquels une suspension doit se produire pour tous les utilisateurs. La synchronisation ne reprend pas tant que tous les utilisateurs n’ont pas terminé la suspension de ce point d’attente.

Voici quelques scénarios où les points d’attente sont particulièrement utiles :

  • Ajout d’un questionnaire ou d’une enquête à certains moments de la vidéo.
  • Attendre que tout le monde charge correctement une vidéo avant son démarrage ou pendant la mise en mémoire tampon.
  • Autoriser un présentateur à choisir des points dans la vidéo pour la discussion de groupe.
// Suspend the media session coordinator
const waitPoint = {
  position: 0,
  reason: "ReadyUp", // Optional.
};
const suspension = mediaSession.coordinator.beginSuspension(waitPoint);
// End the suspension when the user readies up
document.getElementById("ready-up-button").onclick = () => {
  // Sync will resume when everyone has ended suspension
  suspension.end();
};

Abaissement audio

Le Kit de développement logiciel (SDK) Live Share prend en charge l’abaissement audio intelligent. Vous pouvez utiliser la fonctionnalité dans votre application en ajoutant ce qui suit à votre code :

import { meeting } from "@microsoft/teams-js";

// ... set up MediaPlayerSynchronizer

// Register speaking state change handler through Microsoft Teams JavaScript client library (TeamsJS)
let volumeTimer;
meeting.registerSpeakingStateChangeHandler((speakingState) => {
  if (speakingState.isSpeakingDetected && !volumeTimer) {
    // If someone in the meeting starts speaking, periodically
    // lower the volume using your MediaPlayerSynchronizer's
    // VolumeLimiter.
    synchronizer.volumeLimiter?.lowerVolume();
    volumeTimer = setInterval(() => {
      synchronizer.volumeLimiter?.lowerVolume();
    }, 250);
  } else if (volumeTimer) {
    // If everyone in the meeting stops speaking and the
    // interval timer is active, clear the interval.
    clearInterval(volumeTimer);
    volumeTimer = undefined;
  }
});

En outre, ajoutez les autorisations RSC suivantes dans votre manifeste d’application :

{
  // ...rest of your manifest here
  "authorization": {​
    "permissions": {​
      "resourceSpecific": [
        // ...other permissions here​
        {​
          "name": "OnlineMeetingIncomingAudio.Detect.Chat",​
          "type": "Delegated"
        },
        {​
          "name": "OnlineMeetingIncomingAudio.Detect.Group",​
          "type": "Delegated"​
        }​
      ]​
    }​
  }​
}

Remarque

L’API registerSpeakingStateChangeHandler utilisée pour le canardage audio fonctionne actuellement uniquement sur le bureau Microsoft Teams et dans les types de réunions planifiées et meet now.

Exemples de code

Exemple de nom Description JavaScript TypeScript
Vidéo React Exemple de base montrant comment l’objet LiveMediaSession fonctionne avec la vidéo HTML5. View N/A
Modèle multimédia React Permettre à tous les clients connectés de regarder ensemble des vidéos, de créer une playlist partagée, de transférer qui a le contrôle et d’effectuer des annotations sur la vidéo. View View

Étape suivante

Voir aussi