LoginSignup
8
5
新しくなったSkyWayを使ってみよう!

Vue.JSとskywayでZoomみたいアプリを作りましょう(初心者OK) Part 1

Posted at

はじめに

vue.jsでズーム、グーグルミーツなどみたいオンライン会議サービスのアプリを作りましょう。

目的

シンプルなオンライン会議システムを開発

概要

システム方式・構成

システム構成は以下となります

  • ウェブアプリケーション
    vue.jsでウェブアプリケーション、ウェブカメラのストリーム、ローカルとリモートの画面
  • SkyWay API サーバー
    既存の外部NTTのSkyWay API

レシピ

まずは新skywayのコンソルからアカウントを作りましょう
https://console.skyway.ntt.com/signup/

メールを認証し、ログインするとプロジェクトを作成しましょう
名の例:kaigi
上からアプリケーションを作りましょう
アプリケーション名: kaigi
作成

アプリケーションIDとシークレットキーをコピーしておきます。

nodeをインストール

vscodeをインストール

プロジェクトのフォルダーを作ります。
そのフォルダーからターミナル(コマンドプロンプト)を開きます。

以下のコマンドを実行します;

npm create vite
project name: kaigi
type: vue
language: javascript

cd kaigi
npm install
code .

Visual Studio コードを開始するはずです

VSコードのメニューからターミナルを開きましょう

npm i @skyway-sdk/room
npm i uuidv4

.env.localファイルを作ってアプリケーションIDとシークレットを以下通り入ります

.env.local
VITE_SKYWAY_SECRET_KEY=シークレットキーを貼付
VITE_SKYWAY_APP_ID=アプリケーションIDを貼付

大事な情報ですので、公開しないようにしましょう。viteなら基準で*.localはgitから抜きます。
しかし、現在アプリはサーバーバックエンドを開発しませんので、ブラウザでシークレットキーをアクセスになってしまうので、必ずそのまま公開しないようにしましょう。

新しいvscodeのターミナルを開きしましょう

npm run dev

ローカルサーバーを開始ます。

アドレスをコピーしてブラウザに張り付けます
私場合は以下のアドレスが出ました:

http://localhost:5173/

app.vueを開いて以下通りに変更します

<script setup>
import StreamReceiver from './components/StreamReceiver.vue'
</script>

<template>
  <StreamReceiver  />
</template>

StreamReceiverのコンポーネント(アプリの部分)を呼びますということです

HelloWorld.vueを削除しましょう
同じところでcomponentsの中StreamReceiver.vueを作りましょう

<script setup>
import { ref } from 'vue'
import { SkyWayContext } from '@skyway-sdk/room';

// 現在のURL
const baseUrl = window.location.href.split('?')[0];

// div ref="stream-area"参考
const StreamArea = ref(null);
// 会議部屋を作ったかどうか
const RoomCreated = ref(false);
// ルームのIDの保管、シェアため
const RoomId = ref(null);

</script>

<template>
  <h1>Kaigi</h1>

  <div class="card">
    <div ref="StreamArea" v-if="RoomCreated">
        
    </div>
    <div v-else>
      <button @click="createRoom">Create Room</button>
    </div>
    <div v-if="RoomId">
        <p>以下のURLは相手とシェア:</p>
        <p>{{ baseUrl }}?room={{ RoomId }}</p>

        <p>またはルームIDを送りましょう:</p>
        <p>{{ RoomId }}</p>

        <p>会議を開始するため以下のボタンをクリックしてください:</p>
        <button @click="joinRoom">Join Room</button>

    </div>
  </div>
</template>

ブラウザで見ると以下通りはずです:
Screenshot 2023-07-05 09.36.15 msedge bw9.png

Create roomを押しても何も変わらない、まだ関数を作りませんでした。今度変更します。

その前はSkyWayAPIと繋がるためにTokenのコードを作らなければなりませんので
componentsのフォルダーの中SkywayToken.jsを作りましょう。
以下通り:

import { SkyWayAuthToken } from '@skyway-sdk/token';
import { uuidV4, nowInSec } from '@skyway-sdk/room';

export default function GetToken(app_id, secret) { 
    return new SkyWayAuthToken({
        jti: uuidV4(),
        iat: nowInSec(),
        exp: nowInSec() + 60 * 60 * 24,
        scope: {
        app: {
            id: app_id,
            turn: true,
            actions: ['read'],
            channels: [
            {
                id: '*',
                name: '*',
                actions: ['write'],
                members: [
                {
                    id: '*',
                    name: '*',
                    actions: ['write'],
                    publication: {
                    actions: ['write'],
                    },
                    subscription: {
                    actions: ['write'],
                    },
                },
                ],
                sfuBots: [
                {
                    actions: ['write'],
                    forwardings: [
                    {
                        actions: ['write'],
                    },
                    ],
                },
                ],
            },
            ],
        },
        },
    }).encode(secret);
}

そちらはアプリケーションIDやシークレットや設定を用いてトークンを作ってリターンします。

StreamReceiver.vueを変更しましょう

<script setup>
import { ref, onMounted } from 'vue'
import { SkyWayContext, SkyWayRoom, SkyWayStreamFactory, uuidV4 } from '@skyway-sdk/room';
import  GetToken  from './SkywayToken.js'

// SkyWayのトークンを作成する
const tokenString = GetToken(import.meta.env.VITE_SKYWAY_APP_ID, import.meta.env.VITE_SKYWAY_SECRET_KEY);

// SkyWayの実体とルームの実体を保管するため
const context = {'ctx': null, 'room': null};

// 現在のURL
const baseUrl = window.location.href.split('?')[0];
// div ref="stream-area"参考
const StreamArea = ref(null)
// 会議部屋を作ったかどうか
const RoomCreated = ref(false)
// ルームのIDの保管、シェアため
const RoomId = ref(null)


// SkyWayのAPIと繋がって実体を保管する
const getContext = async () => {
    context.ctx = await SkyWayContext.Create(tokenString);

    // トークンの更新
    context.ctx.onTokenUpdateReminder.add(() => {
        context.ctx.updateAuthToken(tokenString);
    });
    return context.ctx;
}

// 部屋を作り、ルームIDを保管する
const createRoom = async () => {
    // ルームIDがない場合は作成する
    if (!RoomId.value) {
        RoomId.value = uuidV4();
    }

    // ルームの実体を作成する, p2pの手法
    // FindOrCreateは同じ名前のルームがある場合はそれを使う
    context.room = await SkyWayRoom.FindOrCreate(context.ctx, {
        type: 'p2p',
        name: RoomId.value,
    });
    // ルームを作ったことを示すため
    RoomCreated.value = true
}

// 部屋に入る関数
const joinRoom = async () => {
    if (!RoomId.value) {
        alert ('No Room ID');
        return;
    }

    // ルームの実体がない場合は作成する
    if (!RoomCreated.value) {
        await createRoom();
    }

    // ルームに入る, 今は名前はランダム、同じ名前だと入らないので、現在テストため
    const member = await context.room.join({name: uuidV4()});
    // Cameraのストリームを作成する
    const videoStream = await SkyWayStreamFactory.createCameraVideoStream();

    // 映像を送る
    await member.publish(videoStream);

    // ユーザーからCameraの映像を取得する
    const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });

    // 映像を表示する
    const video = document.createElement('video');
    video.srcObject = stream;
    video.autoplay = true;
    video.playsInline = true;
    video.muted = true;
    video.style.width = '100%';
    video.style.height = '100%';
    StreamArea.value.appendChild(video);

    // skywayのストリームへ添付する
    skywayStream.attach(video);
    
    // 映像を再生する
    await video.play();
}

// ページが読み込まれたら SkyWayの実体を作成する
onMounted(async () => {
    await getContext();

    // URLでルームIDがある場合はそれを使う
    RoomId.value = new URLSearchParams(window.location.search).get('room');
});

</script>

<template>
  <h1>Kaigi</h1>

  <div class="card">
    <div ref="StreamArea" v-if="RoomCreated">
        
    </div>
    <div v-else>
    
      <button @click="createRoom">Create Room</button>

        
    </div>
    <div v-if="RoomId">
        <p>以下のURLは相手とシェア:</p>
        <p>{{ baseUrl }}?room={{ RoomId }}</p>

        <p>またはルームIDを送りましょう:</p>
        <p>{{ RoomId }}</p>

        <p>会議を開始するため以下のボタンをクリックしてください:</p>
        <button @click="joinRoom">Join Room</button>

    </div>
  </div>
</template>

ブラウザを確認すると今create roomとjoin roomもできます。カメラストリームを開始はずです。

今度は相手も参加できるようにします。

8
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5