Live Share コア機能

Teams 会議でアジャイル ポーカー ゲームをプレイしているユーザーの例を示すスクリーンショット。ライブ共有機能が示されています。

Live Share SDK は、最小限の労力で会議拡張機能の sidePanelmeetingStage コンテキストに追加できます。

この記事では、Live Share SDK をアプリに統合する方法と、SDK の主な機能を中心に説明します。

前提条件

JavaScript SDK をインストールする

Live Share SDK は npm で発行された JavaScript パッケージであり、npm または yarn を使用してダウンロードできます。 また、 と @fluidframework/azure-clientを含む fluid-framework Live Share ピアの依存関係もインストールする必要があります。 タブ アプリケーションで Live Share を使用している場合は、バージョン2.11.0以降もインストール@microsoft/teams-jsする必要があります。 ローカル ブラウザー開発に クラスをTestLiveShareHost使用する場合は、 に と パッケージをdevDependenciesインストール@fluidframework/test-client-utilsするstart-server-and-test必要があります。

npm

npm install @microsoft/live-share fluid-framework @fluidframework/azure-client --save
npm install @microsoft/teams-js --save
npm install @fluidframework/test-client-utils start-server-and-test --save-dev

yarn add @microsoft/live-share fluid-framework @fluidframework/azure-client
yarn add @microsoft/teams-js
yarn add @fluidframework/test-client-utils -dev

RSC アクセス許可を登録する

会議拡張機能で Live Share SDK を有効にするには、まずアプリ マニフェストに次の RSC アクセス許可を追加する必要があります。

{
  // ...rest of your manifest here
  "configurableTabs": [
    {
        "configurationUrl": "<<YOUR_CONFIGURATION_URL>>",
        "canUpdateConfiguration": true,
        "scopes": [
            "groupchat",
            "team"
        ],
        "context": [
            "meetingSidePanel",
            "meetingStage"
        ]
    }
  ],
  "validDomains": [
    "<<BASE_URI_ORIGIN>>"
  ],
  "authorization": {​
    "permissions": {​
      "resourceSpecific": [
        // ...other permissions here​
        {​
          "name": "LiveShareSession.ReadWrite.Chat",​
          "type": "Delegated"
        },
        {​
          "name": "LiveShareSession.ReadWrite.Group",​
          "type": "Delegated"
        },
        {​
          "name": "MeetingStage.Write.Chat",​
          "type": "Delegated"
        },
        {​
          "name": "ChannelMeetingStage.Write.Group",​
          "type": "Delegated"
        }
      ]​
    }​
  }​
}

会議セッションに参加する

次の手順に従って、ユーザーの会議に関連付けられているセッションに参加します。

  1. を初期化 LiveShareClientします。
  2. 同期する必要のあるデータ構造を定義します。 たとえば、LiveState および SharedMap が禁止となります。
  3. コンテナーに参加します。

例:

import { LiveShareClient, LiveState } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
import { SharedMap } from "fluid-framework";

// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
  initialObjects: {
    liveState: LiveState,
    sharedMap: SharedMap,
  },
};
const { container } = await liveShare.joinContainer(schema);

// ... ready to start app sync logic

たったこれだけで、コンテナーをセットアップし、会議のセッションに参加することができます。 ここで、Live Share SDK で使用できる分散データ構造の種類を確認しましょう。

ヒント

を呼び出す LiveShareHost.create()前に、Teams クライアント SDK が初期化されていることを確認します。

Live Share データ構造

Live Share SDK には、Fluid のクラスを拡張する新しい分散データ構造の DataObject セットが含まれており、新しい種類のステートフル オブジェクトとステートレス オブジェクトが提供されます。 Fluid データ構造とは異なり、Live Share の LiveDataObject クラスでは Fluid コンテナーに変更が書き込まれず、より高速な同期が可能になります。 さらに、これらのクラスは、Teams 会議での一般的な会議シナリオに対してゼロから設計されています。 一般的なシナリオとしては、発表者が表示しているコンテンツの同期、会議の各ユーザーのメタデータの表示、カウントダウン タイマーの表示などがあります。

Live オブジェクト 説明
LivePresence どのユーザーがオンラインであるかを確認し、各ユーザーにカスタム プロパティを設定し、そのプレゼンスへの変更をブロードキャストします。
LiveState 任意の JSON シリアル化可能な値を state 同期します。
LiveTimer 特定の間隔のカウントダウン タイマーを同期します。
LiveEvent ペイロード内の任意のカスタム データ属性を持つ個々のイベントをブロードキャストします。
LiveFollowMode 特定のユーザーに従い、セッションのすべてのユーザーに提示し、中断を開始または終了します。

LivePresence の例

スクリーンショットは、Live Share プレゼンスを使用して sessionTeams で使用可能なユーザーを示す例を示しています。

クラスを LivePresence 使用すると、セッションに参加しているユーザーの追跡がこれまで以上に簡単になります。 または .updatePresence() メソッドを.initialize()呼び出すときに、プロファイル画像、表示しているコンテンツの識別子など、そのユーザーのカスタム メタデータを割り当てることができます。 イベントを presenceChanged リッスンすることで、各クライアントは最新 LivePresenceUser のオブジェクトを受け取り、すべてのプレゼンス更新を一意 userIdの ごとに 1 つのレコードに折りたたみます。

アプリケーションで LivePresence 使用できる例をいくつか次に示します。

  • セッション内の各ユーザーの Microsoft Teams userId、、 displayName、および roles を取得します。
  • プロファイル画像 URL など、セッションに接続されている各ユーザーに関するカスタム情報を表示する。
  • 各ユーザーのアバターが配置されている 3D シーンで座標を同期する。
  • テキスト ドキュメント内の各ユーザーのカーソル位置を報告します。
  • グループ アクティビティ中にアイス ブレーカーの質問に対する各ユーザーの回答を投稿する。
import {
  LiveShareClient,
  LivePresence,
  PresenceState,
} from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";

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

// Register listener for changes to each user's presence.
// This should be done before calling `.initialize()`.
presence.on("presenceChanged", (user, local) => {
  console.log("A user presence changed:")
  console.log("- display name:", user.displayName);
  console.log("- state:", user.state);
  console.log("- custom data:", user.data);
  console.log("- change from local client", local);
  console.log("- change impacts local user", user.isLocalUser);
});

// Define the initial custom data for the local user (optional).
const customUserData = {
  picture: "DEFAULT_PROFILE_PICTURE_URL",
  readyToStart: false,
};
// Start receiving incoming presence updates from the session.
// This will also broadcast the user's `customUserData` to others in the session.
await presence.initialize(customUserData);

// Send a presence update, in this case once a user is ready to start an activity.
// If using role verification, this will throw an error if the user doesn't have the required role.
await presence.update({
  ...customUserData,
  readyToStart: true,
});

1 つのデバイスからセッションに参加するユーザーは、すべてのデバイスと共有される 1 つの LivePresenceUser レコードを持っています。 最新dataの接続にアクセスしstate、それぞれのアクティブな接続にアクセスするには、 クラスの API をLivePresenceUsergetConnections()使用します。 これにより、オブジェクトの一覧が LivePresenceConnection 返されます。 プロパティを使用してisLocalConnection、特定LivePresenceConnectionのインスタンスがローカル デバイスから存在するかどうかを確認できます。

LivePresenceUserインスタンスと LivePresenceConnection インスタンスにはstate、 プロパティがあります。プロパティは、、offline、または awayのいずれかonlineです。 ユーザーの presenceChanged 状態が変化すると、イベントが生成されます。 たとえば、ユーザーが会議を離れた場合、その状態は に offline変わります。

注:

会議を終了した後、's LivePresenceUserstate が に更新offlineされるまでに最大 20 秒かかる場合があります。

LiveState の例

ライブ共有状態の例を示すスクリーンショット。太陽系内の惑星が会議に積極的に提示されているかを同期します。

クラスを LiveState 使用すると、会議のすべてのユーザーに対して単純なアプリケーションの状態を同期できます。 LiveStateは 1 つのstate値を同期します。これにより、JSON シリアル化可能な値 (、 numberobjectなど) をstring同期できます。

アプリケーションで LiveState 使用できる例をいくつか次に示します。

  • 現在の発表者のユーザー識別子を設定して 、テイク コントロール 機能を構築します。
  • すべてのユーザーが同じページに表示されるように、アプリケーションの現在のルート パスを同期する。 たとえば、「 /whiteboard/:whiteboardId 」のように入力します。
  • 現在の発表者が表示しているコンテンツ識別子を維持する。 たとえば、 taskId タスク ボード上の 。
  • 複数ラウンド グループ アクティビティでの現在のステップの同期。 たとえば、アジャイル ポーカー ゲーム中の推測フェーズなどです。
  • フォローミー機能のスクロール位置を同期したままにします。

注:

とは異なりSharedMap、 のLiveStatestate値は、すべてのユーザーがセッションから切断した後にリセットされます。

例:

import { LiveShareClient, LiveState } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";

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

// Register listener for changes to the state.
// This should be done before calling `.initialize()`.
appState.on("stateChanged", (planetName, local, clientId) => {
  // Update app with newly selected planet.
  // See which user made the change (optional)
  const clientInfo = await appState.getClientInfo(clientId);
});

// Set a default value and start listening for changes.
// This default value will not override existing for others in the session.
const defaultState = "Mercury";
await appState.initialize(defaultState);

// `.set()` will change the state for everyone in the session.
// If using role verification, this will throw an error if the user doesn't have the required role.
await appState.set("Earth");

LiveEvent の例

イベントに変更がある場合に通知を表示する Teams クライアントの例を示すスクリーンショット。

LiveEvent は、配信時にのみ必要な会議で他のクライアントに簡単なイベントを送信するための優れた方法です。 これは、セッション通知の送信やカスタムリアクションの実装などのシナリオに役立ちます。

import { LiveEvent, LiveShareClient } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";

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

// Register listener to receive events sent through this object.
// This should be done before calling `.initialize()`.
customReactionEvent.on("received", async (kudosReaction, local, clientId) => {
  console.log("Received reaction:", kudosReaction, "from clientId", clientId);
  // See which user made the change (optional)
  const clientInfo = await customReactionEvent.getClientInfo(clientId);
  // Display notification in your UI
});

// Start listening for incoming events
await customReactionEvent.initialize();

// `.send()` will send your event value to everyone in the session.
// If using role verification, this will throw an error if the user doesn't have the required role.
const kudosReaction = {
  emoji: "❤️",
  forUserId: "SOME_OTHER_USER_ID",
};
await customReactionEvent.send(kudosReaction);

LiveTimer の例

残り 9 秒のカウントダウン タイマーの例を示すスクリーンショット。

LiveTimer は、会議のすべての参加者に同期されるシンプルなカウントダウン タイマーを提供します。 これは、グループ瞑想タイマーやゲームのラウンド タイマーなど、制限時間があるシナリオに役立ちます。 また、アラーム プロンプトの表示など、セッションのすべてのユーザーのタスクをスケジュールすることもできます。

import { LiveShareClient, LiveTimer } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";

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

// Register listeners for timer changes
// This should be done before calling `.initialize()`.

// Register listener for when the timer starts its countdown
timer.on("started", (config, local) => {
  // Update UI to show timer has started
});

// Register listener for when a paused timer has resumed
timer.on("played", (config, local) => {
  // Update UI to show timer has resumed
});

// Register listener for when a playing timer has paused
timer.on("paused", (config, local) => {
  // Update UI to show timer has paused
});

// Register listener for when a playing timer has finished
timer.on("finished", (config) => {
  // Update UI to show timer is finished
});

// Register listener for the timer progressed by 20 milliseconds
timer.on("onTick", (milliRemaining) => {
  // Update UI to show remaining time
});

// Start synchronizing timer events for users in session
await timer.initialize();

// Start a 60 second timer for users in the session.
// If using role verification, this will throw an error if the user doesn't have the required role.
const durationInMilliseconds = 1000 * 60;
await timer.start(durationInMilliseconds);

// Pause the timer for users in session
// If using role verification, this will throw an error if the user doesn't have the required role.
await timer.pause();

// Resume the timer for users in session
// If using role verification, this will throw an error if the user doesn't have the required role.
await timer.play();

LiveFollowMode の例

画像は、発表者、発表者に従うユーザー、発表者に戻るオプションを持つ独自のプライベート ビューを持つユーザーの 3 つの異なるビューを持つ 3 つのクライアントを示しています。

注:

LiveFollowMode はベータ版であり、プレビューとしてのみ提供されます。 運用環境ではこの API を使用しないでください。

クラスLivePresenceLiveFollowModeLiveState を 1 つのクラスにまとめ、フォロワー モードと発表者モードをアプリケーションに簡単に実装できます。 これにより、PowerPoint Live、Excel Live、Whiteboard などの一般的なコラボレーション アプリの使い慣れたパターンを実装できます。 画面共有とは異なり、 LiveFollowMode 高品質でアクセシビリティが向上し、パフォーマンスが向上したコンテンツをレンダリングできます。 ユーザーはプライベート ビューを簡単に切り替えて、他のユーザーに従うことができます。

関数を startPresenting() 使用して、セッション内の他のすべてのユーザーのアプリケーションを 制御 できます。 または、 関数を使用して followUser() 、ユーザーがフォローする特定のユーザーを個別に選択できるようにすることもできます。 どちらのシナリオでも、ユーザーは関数を使用してプライベート ビューを一時的に入力するか、関数を使用 beginSuspension() して発表者 endSuspension() に同期できます。 一方、 関数を update() 使用すると、ローカル ユーザーは、セッション内の他のクライアントに自分の個人 stateValueの を通知できます。 と同様に LivePresence、イベント リスナーを介して各ユーザーの stateValue 変更を presenceChanged リッスンできます。

LiveFollowMode また、ローカル ユーザーが state フォローしているユーザーに応じて動的に更新される オブジェクトも公開されます。 たとえば、ローカル ユーザーが誰もフォローしていない場合、state.valueプロパティは を介してupdate()ブロードキャストされたローカル ユーザーの最新stateValueのユーザーと一致します。 ただし、ローカル ユーザーが発表者をフォローしている場合、 state.value プロパティは発表者の最新 stateValueの と一致します。 と同様に LiveState、イベント リスナーを使用して値の state 変更を stateChanged リッスンできます。 オブジェクトの state 詳細については、「 IFollowModeState インターフェイス リファレンス」を参照してください

アプリケーションで使用 LiveFollowMode できる例を次に示します。

  • デザイン レビュー中に 3D シーン内のカメラの位置をコブロウズに同期します。
  • slideIdを更新してカルーセルで開き、生産性の高いプレゼンテーションやディスカッションを行います。
  • pathをブロードキャストして、アプリケーションのルーターで開きます。

例:

import {
  LiveShareClient,
  LiveFollowMode,
  FollowModeType,
} from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";

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

// As an example, we will assume there is a button in the application document
const button = document.getElementById("action-button");
// As an example, we will assume there is a div with text showing the follow state
const infoText = document.getElementById("info-text");

// Register listener for changes to the `state` value to use in your app.
// This should be done before calling `.initialize()`.
followMode.on("stateChanged", (state, local, clientId) => {
  console.log("The state changed:");
  console.log("- state value:", state.value);
  console.log("- follow mode type:", state.type);
  console.log("- following user id:", state.followingUserId);
  console.log("- count of other users also following user", state.otherUsersCount);
  console.log("- state.value references local user's stateValue", state.isLocalValue);
  // Can optionally get the relevant user's presence object
  const followingUser = followMode.getUserForClient(clientId);
  switch (state.type) {
    case FollowModeType.local: {
        // Update app to reflect that the user is not currently following anyone and there is no presenter.
        infoText.innerHTML = "";
        // Show a "Start presenting" button in your app.
        button.innerHTML = "Start presenting";
        button.onclick = followMode.startPresenting;
        // Note: state.isLocalValue will be true.
        break;
    }
    case FollowModeType.activeFollowers: {
        // Update app to reflect that the local user is being followed by other users.
        infoText.innerHTML = `${state.otherUsersCount} users are following you`;
        // Does not mean that the local user is presenting to everyone, so you can still show the "Start presenting" button.
        button.innerHTML = "Present to all";
        button.onclick = followMode.startPresenting;
        // Note: state.isLocalValue will be true.
        break;
    }
    case FollowModeType.activePresenter: {
        // Update app to reflect that the local user is actively presenting to everyone.
        infoText.innerHTML = `You are actively presenting to everyone`;
        // Show a "Stop presenting" button in your app.
        button.innerHTML = "Stop presenting";
        button.onclick = followMode.stopPresenting;
        // Note: state.isLocalValue will be true.
        break;
    }
    case FollowModeType.followPresenter: {
        // The local user is following a remote presenter.
        infoText.innerHTML = `${followingUser?.displayName} is presenting to everyone`;
        // Show a "Take control" button in your app.
        button.innerHTML = "Take control";
        button.onclick = followMode.startPresenting;
        // Note: state.isLocalValue will be false.
        break;
    }
    case FollowModeType.suspendFollowPresenter: {
        // The local user is following a remote presenter but has an active suspension.
        infoText.innerHTML = `${followingUser?.displayName} is presenting to everyone`;
        // Show a "Sync to presenter" button in your app.
        button.innerHTML = "Sync to presenter";
        button.onclick = followMode.endSuspension;
        // Note: state.isLocalValue will be true.
        break;
    }
    case FollowModeType.followUser: {
        // The local user is following a specific remote user.
        infoText.innerHTML = `You are following ${followingUser?.displayName}`;
        // Show a "Stop following" button in your app.
        button.innerHTML = "Stop following";
        button.onclick = followMode.stopFollowing;
        // Note: state.isLocalValue will be false.
        break;
    }
    case FollowModeType.suspendFollowUser: {
        // The local user is following a specific remote user but has an active suspension.
        infoText.innerHTML = `You were following ${followingUser?.displayName}`;
        // Show a "Resume following" button in your app.
        button.innerHTML = "Resume following";
        button.onclick = followMode.endSuspension;
        // Note: state.isLocalValue will be true.
        break;
    }
    default: {
        break;
    }
  }
  const newCameraPosition = state.value;
  // TODO: apply new camera position
});

// Register listener for changes to each user's personal state updates.
// This should be done before calling `.initialize()`.
followMode.on("presenceChanged", (user, local) => {
  console.log("A user presence changed:");
  console.log("- display name:", user.displayName);
  console.log("- state value:", user.data?.stateValue);
  console.log("- user id user is following:", user.data?.followingUserId);
  console.log("- change from local client", local);
  console.log("- change impacts local user", user.isLocalUser);
  // As an example, we will assume there is a button for each user in the session.
  document.getElementById(`follow-user-${user.userId}-button`).onclick = () => {
    followMode.followUser(user.userId);
  };
  // Update 3D scene to reflect this user's camera position (e.g., orb + display name)
  const userCameraPosition = user.data?.stateValue;
});

// Define the initial stateValue for the local user (optional).
const startingCameraPosition = {
  x: 0,
  y: 0,
  z: 0,
};
// Start receiving incoming presence updates from the session.
// This will also broadcast the user's `startingCameraPosition` to others in the session.
await followMode.initialize(startingCameraPosition);

// Example of an event listener for a camera position changed event.
// For something like a camera change event, you should use a debounce function to prevent sending updates too frequently.
// Note: it helps to distinguish changes initiated by the local user (e.g., drag mouse) separately from other change events.
function onCameraPositionChanged(position, isUserAction) {
    // Broadcast change to other users so that they have their latest camera position
    followMode.update(position);
    // If the local user changed the position while following another user, we want to suspend.
    // Note: helps to distinguish changes initiated by the local user (e.g., drag mouse) separately from other change events.
    if (!isUserAction) return;
    switch (state.type) {
      case FollowModeType.followPresenter:
      case FollowModeType.followUser: {
        // This will trigger a "stateChanged" event update for the local user only.
        followMode.beginSuspension();
        break;
      }
      default: {
        // No need to suspend for other types
        break;
      }
    }
}

ライブ データ構造のロール検証

Teams の会議には、通話、オールハンズ会議、オンライン 教室が含まれます。 会議の参加者は、組織全体にまたがったり、異なる特権を持ったり、異なる目標を持つ場合があります。 そのため、会議中にさまざまなユーザー ロールの特権を尊重することが重要です。 ライブ オブジェクトは、ロールの検証をサポートするように設計されており、個々のライブ オブジェクトごとにメッセージを送信できるロールを定義できます。 たとえば、会議の発表者と開催者のみがビデオ再生を制御できるオプションを選択しました。 ただし、ゲストと出席者は引き続き次のビデオをwatchに要求できます。

発表者と開催者のみが制御できる次の例では、 LiveState アクティブな発表者であるユーザーを同期するために使用します。

import {
  LiveShareClient,
  LiveState,
  UserMeetingRole,
} from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";

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

// Register listener for changes to state
appState.on("stateChanged", (state, local) => {
  // Update local app state
});

// Set roles who can change state and start listening for changes
const initialState = {
  documentId: "INITIAL_DOCUMENT_ID",
};
const allowedRoles = [UserMeetingRole.organizer, UserMeetingRole.presenter];
await appState.initialize(initialState, allowedRoles);

async function onSelectEditMode(documentId) {
  try {
    await appState.set({
      documentId,
    });
  } catch (error) {
    console.error(error);
  }
}

async function onSelectPresentMode(documentId) {
  try {
    await appState.set({
      documentId,
      presentingUserId: "LOCAL_USER_ID",
    });
  } catch (error) {
    console.error(error);
  }
}

アプリに役割の検証を実装する前に、特に [開催者] の役割のシナリオを理解するために顧客の声を耳を傾けます。 会議の開催者が会議に出席する保証はありません。 一般的な経験則として、すべてのユーザーは、organization内で共同作業を行うときに開催者または発表者になります。 ユーザーが [出席者]の場合、通常は会議の開催者に代わって意図的に決定されます。

場合によっては、ユーザーに複数のロールが含まれる場合があります。 たとえば、 開催者発表者でもあります。 さらに、会議をホストしているテナントの外部にある会議参加者は ゲスト ロールを持ちますが、 発表者 特権を持つ場合もあります。 これにより、アプリケーションでロール検証を使用する方法の柔軟性が高くなります。

注:

Live Share SDK は、チャネル会議の ゲスト ユーザーではサポートされていません。

流動分散データ構造

Live Share SDK は、流動フレームワークに含まれる分散データ構造をサポートします。 これらの機能は、タスク リストのリアルタイム更新や HTML <textarea>内の共同編集テキストなど、堅牢なコラボレーション シナリオを構築するために使用できるプリミティブのセットとして機能します。

この記事で説明されている LiveDataObject クラスとは異なり、Fluid データ構造は、アプリケーションが閉じられた後にリセットされません。 これは、ユーザーが会議の他のタブ (チャットなど) を使用しながら、アプリを頻繁に閉じて再度開く会議側パネルなどのシナリオに最適です。

Fluid Framework では、次の種類の分散データ構造が正式にサポートされています。

共有オブジェクト 説明
SharedMap 分散キー値ストア。 任意の JSON シリアル化可能なオブジェクトを指定されたキーに設定し、セッション内のすべてのユーザーにそのオブジェクトを同期させます。
SharedSegmentSequence 設定された位置にある一連の項目 (セグメントと呼ばれる) の集合体を格納するリスト状のデータ構造。
SharedString ドキュメントまたはテキスト領域のテキストを編集するために最適化された分散文字列シーケンス。

SharedMap のしくみを見てみましょう。 この例では、SharedMap を使用してプレイリスト機能を構築しています。

import { LiveShareClient } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
import { SharedMap } from "fluid-framework";

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

// Register listener for changes to values in the map
playlistMap.on("valueChanged", (changed, local) => {
  const video = playlistMap.get(changed.key);
  // Update UI with added video
});

function onClickAddToPlaylist(video) {
  // Add video to map
  playlistMap.set(video.id, video);
}

注:

コア流動フレームワーク DDS オブジェクトでは、会議の役割の検証はサポートされません。 会議のすべてのユーザーは、これらのオブジェクトを介して格納されているデータを変更できます。

ローカル ブラウザーのテスト

Teams にアプリをインストールせずに、 クラスを使用して TestLiveShareHost ブラウザーで Live Share SDK をローカルでテストできます。 これは、使い慣れた localhost 環境内でアプリケーションのコア コラボレーション機能をテストする場合に役立ちます。

例:

import { LiveShareClient, TestLiveShareHost, LiveState } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
import { SharedMap } from "fluid-framework";

/**
 * Detect whether you are in Teams or local environment using your preferred method.
 * Options for this include: environment variables, URL params, Teams FX, etc.
 */
const inTeams = process.env.IN_TEAMS;
// Join the Fluid container
const host = inTeams
  ? LiveShareHost.create()
  : TestLiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
  initialObjects: {
    liveState: LiveState,
    sharedMap: SharedMap,
  },
};
const { container } = await liveShare.joinContainer(schema);

// ... ready to start app sync logic

クラスは TestLiveShareHost 、運用環境の tinylicious Azure Fluid Relay サービスではなく、Fluid Framework のテスト サーバーを利用します。 これを行うには、いくつかのスクリプトを に追加して package.json テスト サーバーを起動する必要があります。 および パッケージを 内の @fluidframework/test-client-utilsstart-server-and-testpackage.jsondevDependencies追加する必要もあります。

{
    "scripts": {
        "start": "start-server-and-test start:server 7070 start:client",
        "start:client": "{YOUR START CLIENT COMMAND HERE}",
        "start:server": "npx tinylicious@latest"
    },
    "devDependencies": {
        "@fluidframework/test-client-utils": "^1.3.6",
        "start-server-and-test": "^2.0.0"
    }
}

この方法でアプリケーションを起動すると、 LiveShareClient URL が存在しない場合は URL に追加されます #{containerId} 。 その後、URL をコピーして新しいブラウザー ウィンドウに貼り付けて、同じ Fluid コンテナーに接続できます。

注:

既定では、接続TestLiveShareHostされているすべてのクライアントにロールと organizer ロールが含presenterまれます。

コード サンプル

サンプルの名前 説明 JavaScript TypeScript
Dice Roller 接続されているすべてのクライアントがサイコロをふり、結果を表示できるようにします。 表示 表示
アジャイル ポーカー 接続されているすべてのクライアントが Agile Poker をプレイできるようにします。 表示 該当なし
3D モデル 接続されているすべてのクライアントが 3D モデルを一緒に表示できるようにします。 該当なし 表示
Timer 接続されているすべてのクライアントがカウントダウン タイマーを表示できるようにします。 該当なし 表示
プレゼンス アバター 接続されているすべてのクライアントのプレゼンス アバターを表示します。 該当なし 表示

次の手順

関連項目