https://d226lax1qjow5r.cloudfront.net/blog/blogposts/create-a-video-help-chat-with-node-js-and-svelte/blog_node-js_svelte_video_1200x600.png

Node.jsとSvelteでビデオヘルプチャットを作成する

最終更新日 December 16, 2020

所要時間:2 分

あなたのウェブサイトのためのビデオヘルプチャットのようなユースケースは、フロントエンドフレームワークのための素晴らしい議論になります。多分、サイトの残りの部分はビデオチャットとは何の関係もありません、または、複数の場所または複数の設定でチャットを使用したいかもしれません。様々な理由で、それはおそらくコンポーネントで構築したい種類のものです。

Svelteはフロントエンド・フレームワークの中では新しい方で、より親しみやすい選択かもしれない。まだフレームワークにコミットしていないのであれば、HTML、CSS、JavaScriptを使い慣れた方法で使うものから始めた方が早いかもしれない。また、Videoの制作にはさまざまな要素が必要なので、覚えることが少ないというのは、この例にとって便利な機能だ。

前提条件

新しいSvelteプロジェクトを始めるには 推奨を使うことだ。 デジットを使用することです。これは、アプリケーション・テンプレートのダウンロードと解凍をスムーズに行う便利なツールです。を使って、新しいSvelteプロジェクトを立ち上げることができます。 npx:

npx degit sveltejs/template video-help-chat

コピーができたら npm installを実行して依存関係をインストールする。

これで video-help-chatディレクトリに移動すると、新しいSvelteプロジェクトの足場が表示されます。コード自体に飛び込む前に、Videoチャットを動作させるために必要なものがいくつかあります:

  • a Video API開発者アカウント

  • ビデオセッションを管理するエクスプレス

  • ExpressとSvelteの同時実行

  • Dotenv を使えば、認証情報を .envファイル

Vonage Video APIアカウントをお持ちでない場合は、まず以下の手続きが必要です。 トライアルに申し込む.Video サーバーを作成するためのツールは、すべて npm からインストールできます:

npm -i opentok express concurrently dotenv

スベルトとエクスプレス、一緒に

同時に複数のコマンドを実行することができます。 scriptを実行できる。 package.json.Expressサーバーを起動しながら、何か変更があればRollupを実行してSvelteを再構築する、といった使い方ができる。すでに scriptsにはすでにSvelteを処理するコマンドがあるため、npmスクリプトをレイヤー化し、既存のスクリプトを実行する新しいスクリプトを追加することができます:

"scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w",
    "start": "sirv public",
    "serve": "concurrently \"node server.js\" \"npm run dev\""
  },

資格情報の設定

APIキーとシークレットの安全なホームをすぐに作成するのは良い習慣だ。APIキーとシークレットを保存する .envファイルを作成する。コードをコミットする前に、ファイルを必ず .gitignoreに追加してください。このコードを後でホスティングする場合、ホストはおそらく、ファイルを再投入する安全な方法を用意しているはずです。 .envファイルを再投入する安全な方法があるはずです。

今のところ .envVonage Video API キーとシークレットです。どちらも引用符で囲み、スペースを入れないようにします:

VONAGE_VIDEO_API_KEY="12345678" VONAGE_VIDEO_SECRET="12a3b4c567d89e0f1234567890ab12345678c901"

サーバー

サーバーは、提供された認証情報を使用してVonage Video APIクライアントを作成します。

Vonage Video APIは以前はOpenTokとして知られていました。この名前はまだいくつかのコードで使われており、古いチュートリアルに近いコードになるように、ここでも使い続けることにします。

まずExpressをインポートし、Expressアプリケーションを作成します。次に /chat.静的ページはExpressサーバーの先頭付近で処理されることが多いですが、ここではほぼ最後に処理します。これは、Svelte側のアプリケーションに返す責任を制限するためで、サーバーのエンドポイントを処理しようとすることはありません。最後に、ポート5000をリッスンするようにサーバーに指示します。

エンドポイントは /chatエンドポイントは、面白いことが起こる場所です。この関数は、フロントエンドでビデオチャットを作成するために必要な認証情報を返します。また、非常に基本的な方法でビデオチャットセッションを管理し、既存のセッションを返したり、セッションがない場合は新しいセッションを作成します。

require('dotenv').config();
const express = require('express');
const app = express();
app.use(express.json());

let sessionId;

app.get('/chat', function(request, response) {
  if (sessionId) {
    response.send({
      apiKey: process.env.VONAGE_VIDEO_API_KEY,
      sessionId: sessionId,
      token: opentok.generateToken(sessionId)
    });
  } else {
    opentok.createSession(function(err, session) {
      sessionId = session.sessionId;
      
      response.send({
        apiKey: process.env.VONAGE_VIDEO_API_KEY,
        sessionId: sessionId,
        token: opentok.generateToken(sessionId)
      });
    });
  } 
});

app.use(express.static('public'));
app.get('/', function(request, response) {
  response.sendFile(__dirname + '/public/index.html');
});

app.listen(5000);

この例を実際のサイトに組み込むには、上記の変数 sessionId変数がエントリーポイントになります。エンドポイントから新しいセッションを作成し /chatエンドポイントから新しいセッションを作成し、IDをスタックに追加することができます。ビデオチャットに応答するチームは、待機中の呼び出しに参加するために、これらのセッションIDにアクセスすることができます。

クライアント

テンプレート・アプリケーションには App.svelteファイルが含まれていなければなりません。 /public/src.ターミナルで次のように入力すれば、今すぐ実行し、テストすることができるはずだ:

npm run serve

ブラウザーを開いて「localhost:5000」にアクセスすると、Svelteのhello worldページが表示されるはずだ。

開いている間に App.svelteを開いている間に、次に作成するコンポーネントへの参照を追加しておこう。まず、コンポーネントをインポートする。 Chat.svelte:

<script>
	export let name;

	import Chat from './Chat.svelte';
</script>

ページ下部の <style>タグの上に、コンポーネントそのものを追加します:

<main>
	<h1>Hello {name}!</h1>
	<p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>

<Chat/>

チャット・コンポーネント

実行中のアプリケーションに不満があるかもしれない。 Chat.svelteファイルを /public/src.を追加してください。 ChatButton.svelteVideoChat.svelteファイルを追加することもできます。

Chat コンポーネントは、2つの状態を持つチャットのコンテナになります。最初に、ユーザーにはチャットを開始するためのリンクが表示されます。リンクをクリックすると、Video チャットに入ります。Chat コンポーネントは、2つの間の切り替えを管理し、それぞれのコンポーネントにカプセル化されます。

Svelteコンポーネントをあまり扱ったことがないのであれば、この最小限のコンポーネントを見るのがよいだろう。JavaScript、HTML、CSSだけであることがわかるだろう。コンテンツとメタ情報を除けば、静的なHTMLページのように見えます:

<script>
  export let collapsed = true;

  import ChatButton from './ChatButton.svelte';
  import Conversation from './VideoChat.svelte';
</script>


<div class="chatContainer" class:expanded="{!collapsed}">
  {#if collapsed}
    <ChatButton bind:showButton={collapsed}/>
  {:else}
    <Conversation/>
  {/if}
</div>

<style>
  .chatContainer {
    position: fixed;
    bottom: 2em;
    right: 2em;
  }
  .expanded {
    width: auto;
    left: 2em;
    min-height: 10em;
  }
</style>

このコンポーネントは状態のコンテナに過ぎないので、コンポーネントが1つのプロパティを持つことは理にかなっている、 collapsed.他の2つのコンポーネントをインポートし、マークアップ内の条件構造を使って表示するコンポーネントを決定する。最後に、いくつかのCSSがコンテナを右下に固定します。チャットが開いている場合、条件付き CSS クラスはコンテナを伸ばします。

チャットボタン機能

ChatButtonコンポーネントのほとんどは、小さな吹き出しのように見せるための装飾的なCSSです。しかし、これはSvelteがどのようにイベントを処理し、コンポーネント間の通信を行うかの例でもあります。

このコンポーネントは1つのプロパティだけをエクスポートする、 showButton.これはコンポーネント内では使われず、その親で使われる。プロパティにバインドされています。 collapsedプロパティにバインドされています:

    <ChatButton bind:showButton={collapsed}/>

ボタンがクリックされると openChat関数が呼び出され showButtonの値をfalseに反転し、その結果 collapsedをfalseに設定します。これにより、チャットUIが開きます。

<script>
  export let showButton = true;

  function openChat() {
    showButton = false;
  }
</script>

<button on:click={openChat}>Chat now</button>

<style>
  button {
    position: relative;
    background: #ac57c8;
    border: none;
    border-radius: 10px;
    padding: 20px;
    color: #fff;
    font-weight: bold;
    cursor: pointer;
    box-shadow: 5px 15px 10px rgba(0,0,0,.5);
  }
  button:hover, button:active {
    color: #83C4F1;
  }
  button:after {
    content: '';
    position: absolute;
    right: 0;
    top: 60%;
    width: 0;
    height: 0;
    border: 20px solid transparent;
    border-left-color: #ac57c8;
    border-right: 0;
    border-bottom: 0;
    margin-top: -10px;
    margin-right: -20px;
  }
</style>

ビデオチャット

良いもの(もちろんJavaScript)は最後まで取っておいた。VideoChat コンポーネントには HTML と CSS があまりありません。パブリッシャーとサブスクライバー(あなたとチャット相手の表示)のプレースホルダと、コンテナの吹き出しのスタイリングがあります。残りは JS です。

ビデオチャットを作成するには、いくつかのことを行う必要があります:

  • サーバーからセッションを取得する(新しく作成されたセッションでも、進行中のセッションでも、クライアントは気にしない)。

  • 初期化する

  • ストリームが作成されるのを待ち、そのストリームを購読する。

  • セッションが切断されるのを待つ

  • パブリッシングの初期化(VideoとAudioの送信)

  • セッションに接続し、パブリッシュする

と呼ばれる関数で行われる。 initSessionと呼ばれる関数で行われます。という関数の中で行われます。 initSessionコンポーネントはそれほど複雑ではありません。コンポーネントはそれほど複雑ではありません。 fetchを使ってセッションを取得し、エラーハンドラを定義します。それから、ビデオチャットのためのマークアップ・プレースホルダと、それをレイアウトするための CSS を定義します:

<script>
  fetch('/chat').then(function fetch(res) {
    return res.json();
  }).then(function fetchJson(json) {
    if (json.error) {
      handleError(error);
    } else {
      initSession(json.apiKey, json.sessionId, json.token);
    }
  }).catch(function catchErr(error) {
    handleError(error);
  });

  function handleError(error) {
    if (error) {
      console.error(error);
    }
  }

  function initSession(apiKey, sessionId, token) {}
</script>


<div class="conversation">
  <div id="subscriber"></div>
  <div id="publisher"></div>
</div>

<style>
  .conversation {
    position: relative;
    width: auto;
    min-height: 10em;
    background: #ac57c8;
    border: none;
    border-radius: 10px;
    padding: 20px;
    box-shadow: 5px 15px 10px rgba(0,0,0,.5);
  }
  .conversation:after {
    content: '';
    position: absolute;
    right: 0;
    top: 60%;
    width: 0;
    height: 0;
    border: 20px solid transparent;
    border-left-color: #ac57c8;
    border-right: 0;
    border-bottom: 0;
    margin-top: -10px;
    margin-right: -20px;
  }
</style>

の中身はほとんどコールバックである。 initSessionの中身はほとんどコールバックである。まず streamCreatedのリスナーを作成し、その中でオプション・オブジェクトを定義し、それを使って session.subscribe().のリスナーを作成することもできる。 sessionDisconnected.現在のところ、このコンポーネントは親にフィードバックを与えませんが、チャットが終了したときにシグナルを送れば、より堅牢になります。この sessionDisconnectedハンドラはそのための1つの場所になるでしょう。

を作ることができる。 publisherOptionsを作成することができる。 subscriberOptionsを作成し、Video 要素を縦横 100% のコンテナに追加することを指定するだけです。そして、パブリッシャーを初期化します。

最後に、パブリッシャーの準備ができたら、次のようにセッションに接続します。 session.connect().接続に成功したら session.publish().

function initSession(apiKey, sessionId, token) {
    var session = OT.initSession(apiKey, sessionId);

    // Subscribe to a newly created stream
    session.on('streamCreated', function streamCreated(event) {
      var subscriberOptions = {
        insertMode: 'append',
        width: '100%',
        height: '100%'
      };
      session.subscribe(event.stream, 'subscriber', subscriberOptions, handleError);
    });

    session.on('sessionDisconnected', function sessionDisconnected(event) {
      console.log('You were disconnected from the session.', event.reason);
    });

    // initialize the publisher
    var publisherOptions = {
      insertMode: 'append',
      width: '100%',
      height: '100%'
    };
    var publisher = OT.initPublisher('publisher', publisherOptions, handleError);

    // Connect to the session
    session.connect(token, function callback(error) {
      if (error) {
        handleError(error);
      } else {
        // If the connection is successful, publish the publisher to the session
        session.publish(publisher, handleError);
      }
    });
  }

試してみる

サーバーがずっと稼働していれば、開いているブラウザーのタブでコードの一部または全部が動作しているのを確認できるはずです。サーバーを再起動する必要があるかもしれません。ターミナルでCtrl+Cキーを押してシャットダウンし、ExpressとSvelteを再度 npm run serve.

ブラウザで localhost:5000に戻る。チャットを試す最も簡単な方法は、別のブラウザーを開いて localhost:5000.これはあまり洗練されていませんが、聞こえるエコーでチャットが機能していることが確認できるはずです。

次のステップ

これで基本的なチャットができるようになりました。 Video APIでできることがたくさんあります。.あるいは、今のところ機能は必要最低限にとどめ、サーバーがセッションを供給する方法を変更して、ユーザーがこのインターフェースから "質問 "し、内部ユーザーが別のインターフェースから "回答 "できるようにすることもできます。

Svelteでできることは他にもたくさんある。 チュートリアル.もし、あなたのチャットにもっと多くの機能を追加する場合、例えば、ユーザーの名前や電子メールを収集する場合、これらのツールは非常に便利です。

シェア:

https://a.storyblok.com/f/270183/250x250/f231d97f1b/garann-means.png
Garann Meansデベロッパー・エデュケーター

私はJavaScript開発者で、Vonageの開発者教育者です。長年にわたり、テンプレート、Node.js、プログレッシブ・ウェブ・アプリケーション、そしてオフライン・ファースト戦略に熱中してきましたが、私がいつも本当に愛しているのは、便利できちんと文書化されたAPIです。私の目標は、当社のAPIを使用するお客様の体験を、私がお手伝いできる最高のものにすることです。