Briswell Tech Blog

ブリスウェルのテックブログです

artillery.io - 負荷テストのツールを使ってみる

Web開発にとっては、負荷テストは大事なことですね。
負荷テストとはアクセス数が多い時、サーバエラーが発生するか、データ返却の速度が遅くなるか、ロードバランサーとオートスケーリングが正常に動くかという検証することです。

今回のテックブログの主人公は artillery.io です。
artillery.io は有料プランがありますが、無料でも使えます。

① artillery.ioをインストールする
artillery.ioのホームページはここです: https://www.artillery.io/
artillery.ioをインストールするため、nodejsをインストールする必要があります。
npm を使って、artillery.ioをグローバルのパッケージとしてインストールします。
npm install -g artillery@latest
artillery.ioが正常にインストールされたか、下記のコマンドで確認できます。
artillery dino
恐竜のようなASCII画像が返却されたらartillery.ioが正常にインストールできたということです。

② デモのため、負荷テスト対象の環境を構築
これから簡単なAPIサーバを作成します。検証の時、DBの様子も観察しましょう!
利用するAWSサービスは Elastic Beanstalk と RDSです。
Elastic Beanstalkの設定:

RDSの設定:

APIは処理が軽いapiと処理が重いapiの2つを用意します。処理が重いapiは約4秒でデータ返却します。

③ テストのconfigファイルを作成
config.yml

  # デプロイしたEB環境のURL
  target: "https://testartillery.com/v1"
  http:
    # デフォルトのタイムアウトを延長する
    timeout: 60
  phases:
      # テストの期間、 300秒 = 5分
    - duration: 300
      # 1秒間で2回api叩く
      arrivalRate: 2
      name: stress test

scenarios:
  - name: "fast query"
    flow:
      - get:
          url: "/fast"
  - name: "slow query"
    flow:
      - get:
          url: "/slow"


④ テスト実行
artillery run config.yml -o report.json
のコマンドでテスト実行します。
結果はこんな感じです。

テスト結果
テスト結果

大部分はタイムアウトされました。処理が重いapiは約4秒でデータ返却する想定でしたが、アクセスが多い時、ほぼタイムアウトされたように見えます。そして、スケールアップイベントも起きません。モニタリングをみてみたら、CPUの利用率は低かったです。

APIサーバのモニタリング
APIサーバのモニタリング
DBのCPUの利用率も見てみます。
DBのCPU利用率
DBのCPU利用率

DBのCPU利用率は高かったです!
この利用率が高い問題はDBのインスタンスタイプを変更するか、リードレプリカを追加するかのどちらかで解決できますね。

上記のテストは簡単ですが、artillery.ioはもっと難しいテストにも対応できそうです。色々試して、こちらのコメント欄でアドバイスや経験を共有していただけると幸いです。
では、今日の記事はここまでです。それではまた次の機会に。。

【Japan IT WeeK】AI・業務自動化 展【春】に出展します!

新年度も始まりましたね。

弊社は、明日から3日間Japan IT WeeK AI・業務自動化 展【春】に出展します。
AI・業務自動化展|Japan IT Week【春】

開催日時: 2023/4/5(水) ~ 2023/4/7(金)
会場: 東京ビッグサイト
ブース番号: E26-30

弊社の出展情報はこちらからご確認いただけます。
出展社詳細
招待状はこちらからご確認いただけます。
【e招待券_出展社】AI・業務自動化展|Japan IT Week【春】

 
今年は以下の3本柱で出展しております。

  • 「AIアナログメーター読み取り & AI画像解析」
  • AWS導入支援」
  • クラウド受発注管理システム ai-cata 導入支援」

 
また、アナログメーター読み取りと画像解析には、デモを用意しております!!
「アナログメーター読み取りってどんなものなんだろう」
「画像解析ってどういう仕組みなんだろう」
といった疑問がございましたら、是非お立ち寄りください!
 
今回は特別に、画像解析デモができるまでの流れを簡単に動画にしました。
ご参考になれば幸いです。   www.youtube.com

 
皆様のご来場、心よりお待ちしております。

SlackからChatGPTを使ってみる

最近、毎日ChatGPTの恩恵を受けている大澤です。 動かないコードの解析をさせて原因を特定してもらったり、出力されたエラーログをChatGPTに投げて原因箇所と対策を教えてもらったりしています。

もちろん100%信用できるわけではないので、最終的には自分で原因を特定しないといけませんが、そのステップをアシストしてくれるのはとても便利ですね。

ChatGPTを使用するときはOpenAIの公式からだったりするわけですが、SlackでChatGPTが使えたら便利かなと思い実装してみました。
ちなみにもともとはGPT-3のAPIを利用して作ったのですが、記事を書いているときにちょうどChatGPTのAPIが公開されたので、ChatGPTのAPIに切り替えました。

GPT-3時点では会話させるのに工夫が必要で、そこも↓こんな感じで頑張って作ったのですが無駄になってしまいましたね…

気を取り直してChatGPT for Slackを作っていきます。

■準備

  1. Slackbotの作成
  2. SlackAPIキーの取得 
  3. OpenAIのAPIキーの取得

1、2については弊社のブログで既に紹介されているので、こちらを参考にしてください。

GAS & SlackでMeetのリンク自動生成Botを作ってみた - Briswell Tech Blog

OpenAIのAPIキーの取得

1. アカウントを作成

まずはOpenAIのアカウントを取得します。 以下のリンクをクリックしてアカウント登録を行うことができます。

https://platform.openai.com/signup

2. キーを発行

アカウント登録ができたらログインし、右上の[profile]から[View API Keys]をクリックします。

[Create new secret key]のボタンをクリックし、発行されたキーをどこかに保管しておきましょう。

実装

今回はAWS LambdaでSlack API, ChatGPT APIを使用していきます。プログラムの流れとしては以下です。

  1. SlackのOutgoing Webhookを使用して「@Chatbot」というメンションをトリガーにしてLambdaにメッセージを送信する。
  2. LambdaでChatGPTのAPIを叩いてレスポンスを取得する。
  3. 取得したレスポンスをSlack APIでスレッドに投稿する。
1. OutgoingWebhookを使用する。

OutgoingWebhookの設定の仕方については以下のように多くの記事があるので、そちらを参考にしました。

englishscience.hatenablog.com

今回は次のような設定にしました。

トリガー:<botのメンバーID>
URL:AWS Lambdaの関数URL

2. ChatGPTのAPIを叩く。

ChatGPTのAPIのボディは以下の形式です。

{
    "model": "gpt-3.5-turbo", 
    "messages": [
        {"role": "system", "content": "システムプロンプト"},
        {"role": "user", "content": "ユーザー側のプロンプト"},
        {"role": "assistant", "content": "ChatGPTの返答"},
        {"role": "user", "content": "ユーザー側のプロンプト"},
        …
    ]
}

platform.openai.com

抜粋ですが、コードとしてはこのように書いてみました。openAIのライブラリではなく、requestsライブラリで直接APIを叩きに行ってます。

        import requests
        import json
        OPENAI_HEADERS = {
            'Authorization': 'Bearer 【openAIのAPIキー】'},
            'Content-type': 'application/json'
        }
        CHATGPT_URI = 'https://api.openai.com/v1/chat/completions'

        messages = [
            {"role":"system", "content":"あなたはとてもフレンドリーで賢いAIアシスタントです。ユーザーは株式会社ブリスウェルというIT企業に勤めています。ITに関する複雑な質問も来ると思いますが、step by stepで考えて回答しましょう。"}
        ]
        
~~~

        # --- ユーザーのメッセージとChatGPTのメッセージを振り分ける
        for conversation in conversations:
            message={}
            if conversation[1]=="【<botのメンバーID>】": # botならassistantに割り振る
                message['role'] = "assistant"
                message['content'] = conversation[0]
            else:
                message['role'] = "user"
                message['content'] = conversation[0].replace('【<botのメンバーID>】','')
                print(message['content'])
            messages.append(message)
        
        data = {
            "model": "gpt-3.5-turbo", 
            "messages": messages
        }
        response = requests.post(CHATGPT_URI, headers=OPENAI_HEADERS, data=json.dumps(data))
        r = response.json()

Slackのスレッドを取得してconversationsに入れ、それを辞書型に加工してChatGPTのAPIを叩きに行ってます。
ちなみにSlackのスレッドを取得するにはSlack APIのconversations.repliesを利用します。

api.slack.com

Slack APIのページには「Tester」というタブがあり、そのページでAPIのテストができます。とても便利でした。

3. ChatGPTからの回答をスレッドに投稿する。

こちらはSlack APIのchat.postmessageを叩くだけです。

        SLACK_TOKEN = "【SlackのAPIキー】"
        POST_URL = "https://slack.com/api/chat.postMessage"
        HEADERS = {"Authorization": "Bearer "+SLACK_TOKEN}

        # --- スレッドへ返信する。
        data  = {
          'channel': channel_name, # 投稿するチャンネル名
          'text': f'{messages}', # 投稿するメッセージ(ChatGPTの回答)
          'thread_ts': ts # 投稿するスレッドの親メッセージのtimestamp
        }
        r = requests.post(POST_URL, headers=HEADERS, data=data)

api.slack.com

GPT-3のときに比べてシンプルに実装できるようになっていました。

ChatGPTでslack自動投稿botを作ってみた

昨年末に2回ほど、GAS & slackの記事を書かせていただきました。

GAS & SlackでMeetのリンク自動生成Botを作ってみた - Briswell Tech Blog GAS & Slackで地震発生時の安否確認Botを作ってみた - Briswell Tech Blog

私自身プログラマではないため、記事を書くにあたってスクリプトの作成が肝だったりします。
というよりスクリプト組めなくて諦めた記事がいくつかあったりします。。。

そこで、今回は最近流行りのChatGPTを使うことで、この悩みが解消されるのでは?と思い実際にやってみた次第です。
プログラムとかよくわからないけど、ChatGPTを使って色々自動化したいなんて人の参考になれば幸いです。

今回実装したのは、定期投稿botで投稿条件は以下となります。
* 毎週木曜日にslackの特定のチャンネルに投稿する
* 木曜日が祝日だった場合は水曜日に投稿する
* 年末年始(12/28 ~ 1/3)は投稿しない
※今回の目的はChatGPTでどこまでできるかなので簡易的な要件を選んでいます。

ChatGPTでコード生成(失敗例)

今回はさっそくスクリプトの生成から行なっていきます。 ChatGPT ChatGPTにスクリプトを組んでもらうため、仕様(やりたいこと)を伝える必要があります。
実際にChatGPTに投げた内容は以下になります。

以下の要件を網羅したgoogle apps scriptのScriptを作成してください
なお、VERIFICATION_TOKENとBOT_USER_OAUTH_TOKENは既に取得済みであるものとする
本処理はgoogle apps scriptの日次トリガーで実行されるものとする
祝日の取得には以下のカレンダーIDを使用すること
ja.japanese#holiday@group.v.calendar.google.com

分岐1: 実行日が年末年始(12月28日 ~ 1月3日)ではない
 yes → 分岐2へ
 no → 処理終了

分岐2: 実行日の曜日を確認する
 実行日が水曜日である → 分岐3へ
 実行日が木曜日である → 分岐4へ
 上記以外の曜日である → 処理終了

分岐3: 実行日翌日が祝日である
 yes → 分岐4へ
 no → 処理終了

分岐4: 実行日が祝日である
 yes → 処理終了
 no → slackの特定のチャンネルへ通知を出す

通知内容は以下とする
「<!channel>\nおはようございます。\n退社までに本日分までの工数入力をお願いします。」

そして実際に作成されたスクリプトがこちらです。

function myFunction() {
  const VERIFICATION_TOKEN = "XXXXXXXXXX";
  const BOT_USER_OAUTH_TOKEN = "xoxb-XXXXXXXXXX";
  const CHANNEL_ID = "XXXXXXXXXX";
  const CALENDAR_ID = "ja.japanese#holiday@group.v.calendar.google.com";
  
  const now = new Date();
  const yearEndStart = new Date(now.getFullYear(), 11, 28); // 12月28日
  const newYearEnd = new Date(now.getFullYear() + 1, 0, 3); // 1月3日
  const isYearEnd = now >= yearEndStart && now <= newYearEnd;
  const dayOfWeek = now.getDay();
  
  if (!isYearEnd) {
    if (dayOfWeek === 3) { // 水曜日
      const tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
      const calendar = CalendarApp.getCalendarById(CALENDAR_ID);
      const events = calendar.getEventsForDay(tomorrow);
      const isTomorrowHoliday = events.length > 0;
      
      if (isTomorrowHoliday) {
        sendSlackMessage("<!channel>\nおはようございます。\n退社までに本日分までの工数入力をお願いします。", VERIFICATION_TOKEN, BOT_USER_OAUTH_TOKEN, CHANNEL_ID);
      }
    } else if (dayOfWeek === 4) { // 木曜日
      sendSlackMessage("<!channel>\nおはようございます。\n退社までに本日分までの工数入力をお願いします。", VERIFICATION_TOKEN, BOT_USER_OAUTH_TOKEN, CHANNEL_ID);
      }
    }
  }
}

function sendSlackMessage(message, verificationToken, botUserOauthToken, channelId) {
  const url = "https://slack.com/api/chat.postMessage";
  const headers = {
    "Content-type": "application/json",
    "Authorization": "Bearer " + botUserOauthToken,
  };
  const payload = {
    "text": message,
    "channel": channelId,
  };
  const options = {
    "method": "post",
    "headers": headers,
    "payload": JSON.stringify(payload),
  };
  
  UrlFetchApp.fetch(url, options);
}
}

なかなか良さそうなのですが、木曜日の場合に祝日判断が抜けている。。。

ChatGPTが生成したコードに追記して完成させる

ということで、木曜日が祝日の場合にskipする処理を追記します。
追記したものがこちらになります。
※当方がプログラマではないのでコーディングに無駄があるかもしれませんがご容赦ください。

function myFunction() {
  const VERIFICATION_TOKEN = "XXXXXXXXXX";
  const BOT_USER_OAUTH_TOKEN = "xoxb-XXXXXXXXXX";
  const CHANNEL_ID = "XXXXXXXXXX";
  const CALENDAR_ID = "ja.japanese#holiday@group.v.calendar.google.com";
  
  const now = new Date();
  const yearEndStart = new Date(now.getFullYear(), 11, 28); // 12月28日
  const newYearEnd = new Date(now.getFullYear() + 1, 0, 3); // 1月3日
  const isYearEnd = now >= yearEndStart && now <= newYearEnd;
  const dayOfWeek = now.getDay();
  
  if (!isYearEnd) {
    if (dayOfWeek === 3) { // 水曜日
      const tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
      const calendar = CalendarApp.getCalendarById(CALENDAR_ID);
      const events = calendar.getEventsForDay(tomorrow);
      const isTomorrowHoliday = events.length > 0;
      
      if (isTomorrowHoliday) {
        sendSlackMessage("<!channel>\nおはようございます。\n退社までに本日分までの工数入力をお願いします。", VERIFICATION_TOKEN, BOT_USER_OAUTH_TOKEN, CHANNEL_ID);
      }
    } else if (dayOfWeek === 4) { // 木曜日
      //水曜日同様祝日判定を行う
      const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
      const calendar = CalendarApp.getCalendarById(CALENDAR_ID);
      const events = calendar.getEventsForDay(today);
      const isTodayHoliday = events.length = 0;

      if (isTodayHoliday) {
      //木曜日が祝日の場合は投稿しない
      }else{
        sendSlackMessage("<!channel>\nおはようございます。\n退社までに本日分までの工数入力をお願いします。", VERIFICATION_TOKEN, BOT_USER_OAUTH_TOKEN, CHANNEL_ID);
      }
    }
  }
}

function sendSlackMessage(message, verificationToken, botUserOauthToken, channelId) {
  const url = "https://slack.com/api/chat.postMessage";
  const headers = {
    "Content-type": "application/json",
    "Authorization": "Bearer " + botUserOauthToken,
  };
  const payload = {
    "text": message,
    "channel": channelId,
  };
  const options = {
    "method": "post",
    "headers": headers,
    "payload": JSON.stringify(payload),
  };
  
  UrlFetchApp.fetch(url, options);
}
}

スクリプトを実行してみる

実際に動作確認をしてみます。
const VERIFICATION_TOKEN = "XXXXXXXXXX";
const BOT_USER_OAUTH_TOKEN = "xoxb-XXXXXXXXXX";
const CHANNEL_ID = "XXXXXXXXXX";
上記3つのパラメータ値の設定を忘れずに行いましょう(設定方法は過去の記事を参照してください)。
GAS & SlackでMeetのリンク自動生成Botを作ってみた - Briswell Tech Blog

検証は以下の日付を指定することで水曜日や木曜日を待たずに検証できます。

「実施日」
const now = new Date(); の括弧内に日付をセットすることで該当日で検証可能です。
const now = new Date(2023, 2, 21); // 2023年3月21日で検証する場合の書き方
※月は0始まり(0 = 1月、11 = 12月)でセットします

「曜日」
if (dayOfWeek === 3) の数値を変更することで曜日を変えて検証可能です。
if (dayOfWeek === 2) // 火曜日で検証したい場合の書き方
※曜日は0始まり(0 = 日曜日、6 = 土曜日)でセットします

検証してみて、投稿ができていることを確認できました。
また、祝前日投稿や祝日に投稿しない条件もバッチリでした。

苦労した点

ここからは余談になりますが、ChatGPTでスクリプト生成で苦労した点を残しておきます。

  • 生成するたびに異なるスクリプトを組んでくる
  • 回答の文字数に制限があるのでスクリプト途中で回答が終了する(有料プラン入れってことですね)
  • 完璧に仕様を網羅できていない

ちなみに、最終版のスクリプトになるまで何度も生成を繰り返してました。
また、仕様を網羅できていない点については、ChatGPTへの渡し方(伝え方)で解決できるのかもしれません。

最後に

当初は依頼を投げたらそれっぽいスクリプトを返してくれるのですごく便利なのでは?と思っていたのですが、
実際取り組んでみると、多少のコツであったり知見(生成されたスクリプトが正しいかどうかの判断)がないと厳しいかもしれません。
とはいえ、このレベルであればわざわざプログラマの方を捕まえなくてもよくなったのは非常に良いことだと思います。
ChatGPTへの橋渡しをする職業(コミュニケーター)が今後は出てきたり資格ができたりするんでしょうか。。。

なにはともあれ、ブログの記事が捗りそうですね!

流体シミュレーション

2023年が始まったと思ったら、あっという間にもう三月。年度末は何かと忙しくなりがちですね。

コーヒーを注ぐ瞬間ってなんかほっとします。お湯をかけるときの香りや、ポタポタと落ちる音、しばし待ってからの一口... 至福です。

その至福のコーヒーの再現まではできませんでしたが、今回は、Blenderの物理演算を利用して、流体シミュレーションをしてみました。

1. 障害物:立方体

障害物の立方体を配置して、流体の受け皿とします。

・物理演算プロパティ
流体 → タイプ:エフェクターエフェクタータイプ:コリジョン

2. 障害物:円柱

障害物の円柱を配置して、蛇口のように流体の流出を調整します。

・物理演算プロパティ
流体 → タイプ:エフェクターエフェクタータイプ:コリジョン

3. フロー:球

流体の発生源のオブジェクトになります。

・物理演算プロパティ
流体 → タイプ:フロー → フロータイプ:液体 → フローの挙動:流入

4. ドメイン

流体シミュレーションを行う領域を指定します。

・物理演算プロパティ
流体 → タイプ:ドメインドメインタイプ:液体

5. アニメーション再生結果

モデルを変えることで、色々なシミュレーションができそうです。

Zoom Meeting SDKでWebシステムにZoomを埋め込む話

はじめに

コストコで売っているどデカくて甘いココアがamazonでも買えることを知り、勢いでポチってしまったid:rosoneです。60食分でした。

前回はYoutubeライブ配信をWebシステムに埋め込む記事を書きましたが、今回はその続きでZoomをWebシステムに埋め込む話になります。 背景などは前回の記事を御覧ください。

Zoom SDKの種類

2023/03現在、Webシステムで利用できるSDKは2種類存在しています。 https://marketplace.zoom.us/docs/guides/

  • Zoom Meeting SDK
    • 標準のUI/UXからカスタマイズはほとんどできないが、その分簡単に組み込むことが可能
    • 手間はかからないが、自由度が低いイメージ
  • Zoom Video SDK
    • 標準のUI/UXが準備されていないので、画面レイアウトなどイチからの実装が必要
    • 手間はかかるが、自由度が高いイメージ

今回はZoom Meeting SDKの方を使用します。

Zoom Japanの方がまとめた記事がわかりやすいので、詳細は下記を御覧ください。

qiita.com

Zoomウェビナーの補足

Zoomウェビナー用のSDKも存在するのですが、Zoomウェビナーを使うには有料ライセンスが必要なので、今回は試せていないです。 ただし、ZoomウェビナーはYoutubeライブ配信連携ができるそうなので、前回の記事と組み合わせればWebシステム上に配信を埋め込むことはできそうです。

  1. Zoom上でウェビナー開始
  2. Youtubeライブでも連携配信
  3. Webシステム上にYoutubeライブ配信の埋め込みリンク設置
  4. ユーザーはWebシステム上でウェビナーを閲覧

準備

Zoom公式のGithubからAPI/フロントのサンプルリポジトリが公開されており、今回はフロントはVue, APIはnodeのリポジトリを使用してお試しします。

他にもiOS/Android, react, angularなどあり、充実しています。

Zoomアカウント

APIサイドでZoomのID(key)/Secretを使用するのですが、これらの取得にはZoomアカウントが必要になります。

アカウント作成は以下のSignUpから行います。

https://marketplace.zoom.us/

SDK Key, Secretの発行

https://marketplace.zoom.us/

Zoomアカウントを作成したら、以下のキャプチャにそって進めます。

4は作成したappをマーケットプレイスに公開しますか?というチェックなので、今回はチェックOFFにします。

5では「会社名」「氏名」「メールアドレス」が必須となっているので、入力して進めます。

6の「App Credentials」まで進むとClient ID(key)/Client Secretを取得できますので、コピーして手元に保管します。 (Github等でパブリックに公開などしないよう、お取り扱いにはご注意下さい)

API準備

https://github.com/zoom/meetingsdk-sample-signature-node.js

上記のリポジトリからcloneします。

$ git clone https://github.com/zoom/meetingsdk-sample-signature-node.js.git

リポジトリのREADMEにSetup方法が書いてあるので、内容にそって進めていきます。

1.In terminal, cd into the cloned repo:
$ cd meetingsdk-sample-signature-node.js

ターミナルでcloneしたディレクトリに移動します。

2.Then install the dependencies:
$ npm install

リポジトリ直下でnpm installの実行します。

3.Create an environment file to store your SDK Key and Secret:
$ touch .env

.envファイルを作成します。

4.Add the following code to the .env file, and insert your Zoom SDK App's Key and Secret found on the App Credentials page in the Zoom App Marketplace:
ZOOM_SDK_KEY=SDK_KEY_HERE
ZOOM_SDK_SECRET=SDK_SECRET_HERE
5.Save and close .env.

先程取得したClient ID(key)/Client Secretを3.で作成したファイルにセットするというもので、流れ的にターミナル上でviで編集すると楽かと思います。viに慣れていなければお気に入りのエディタで編集しても問題ありません。

ZOOM_SDK_KEY=「SDK Key, Secretの発行」で取得したSDK Key
ZOOM_SDK_SECRET=「SDK Key, Secretの発行」で取得したSDK Secret

フロント準備

https://github.com/zoom/meetingsdk-vuejs-sample

上記のリポジトリからcloneします。

$ git clone https://github.com/zoom/meetingsdk-sample-vuejs.git

Yarnが必要になるので、入っていない場合は下記などを参考にYarnのインストールを行って下さい。(下記はmacのやり方なので、windowsの方は別途お調べ下さい) https://qiita.com/niwa1903/items/fb1d37c180d6cbc696c8

こちらもリポジトリのREADMEにSetup方法が書いてあるので、内容にそって進めていきます。

1.Once cloned, navigate to the meetingsdk-sample-vuejs directory:
$ cd meetingsdk-sample-vuejs

ターミナルでcloneしたディレクトリに移動します。

2.Then install the dependencies:

$ yarn install

リポジトリ直下でyarn installの実行します。

3.Open the meetingsdk-sample-vuejs directory in your code editor.

cloneした meetingsdk-sample-vuejsディレクトリをお気に入りのエディタで開きます。

4.Open the src/components/HelloWorld.vue file, and enter values for the variables:

src/components/HelloWorld.vue ファイルを開き変数値を編集、と記載されていますが、HelloWorld.vueは埋め込みではなくZoomアプリと同様でウィンドウ全体を使うUIのため、今回はsrc/components/HelloWorldNew.vueを編集して使用します。

src/App.vueを開き、import HelloWorld from ... のファイル指定を HelloWorld.vue から HelloWorldNew.vue に変更します。

②変数値セット

今回はお試しのためハードコードしますが、本来は画面やDBから取得してセットするなど、何かしらロジックは必要になってくるかと思います。

src/components/HelloWorldNew.vueのexport default内 data()のreturnを以下のように変更します。

sdkKey: "「SDK Key, Secretの発行」で取得したSDK Key",
meetingNumber: "ミーティングのID",
passWord: "ミーティングのPW",
signatureEndpoint: "http://localhost:4000",
userEmail: "参加者のメールアドレス",
userName: "参加者のユーザ名",

ミーティングのID/PWはzoomアプリから取得できます。

③UIの日本語表示化 src/components/HelloWorldNew.vueのstartMeeting()内 this.client.initI()の引数に以下を追加します

language: 'jp-JP',

動作確認

APIをローカルで起動します。

$ npm run start

フロントをローカルで起動します。

$ yarn serve

ローカルのフロントにアクセスします。

http://localhost:8080/

サンプルページ感がすごいので、前回の記事でも使わせていただいたおしゃれなテンプレートページを以下のサイト様からお借りして埋め込みしてみます。(レイアウトなどのソース調整部分は割愛します)

ちなみにフルスクリーン版はこんな感じで、いつも使っているようなUIです。

おわりに

Zoom周りのロジックはほぼサンプルリポジトリのまま使える形なので、想像よりも簡単に実現することができたと感じでいます。

しかし、SDKを埋め込みモードで使うやり方や日本語UI設定が検索でなかなかHITせず、ソースをじっくり読み込んだため調査としては時間が結構かかってしまいました。有識者や感の良い方であれば爆速でたどり着ける部分だとは思います。

Webシステム+Zoom埋め込みはアイデアしだいで可能性が広がるので、ワクワクしながらお試しできました!

AWS CodePipelineを使用してAWS Beanstalkにデプロイする方法

こんにちは。ブリスウェルのSonです。
今回は、GitHubからAWS Beanstalkにアプリケーションをデプロイする方法を紹介します。

AWS Beanstalkは、アプリケーションを簡単で早くデプロイおよび管理するためのサービスです。 AWS CodePipelineは、コードを継続的に配信およびデプロイするためのサービスです。

前提条件


1. GitHubトークンの作成

まず、AWS CodePipelineでGitHubリポジトリを使用するために、GitHubからトークンを作成する必要があります。このトークンがbuildspec.ymlファイルで使用されます。トークンを持っている場合は、このステップをスキップができます。

GitHubのアカウントでログインし、Settings > Developer settings > Personal access tokensに移動します。「Generate new token」をクリックして、アクセス許可を与えるためのトークンを作成します。このトークンを取得しておいてください。


2. AWS CodePipelineのセットアップ

AWSコンソールにログインし、「AWS CodePipeline」を選択して、「パイプラインを作成する」ボタンをクリックします。


3. ソースステージの設定

次の画面で、パイプラインに名前を付けます。「次に」のボタンをクリックします。


「ソースステージを追加する」の画面でソースプロバイダーで「GitHub バージョン 2」を選択します。GitHub アプリ接続を選択します。作成していない場合は作成するための「GitHub に接続する」ボタンをクリックします。



次に、デプロイするためのリポジトリとブランチ名を選択します。ここでは、「feature/pipeline」を使用します。ご要望に応じて、「master」や「develop」等のブランチを使用ができます。


4. CodeBuildプロジェクトの設定

CodePipelineは、ソースステージからソースを取得した後、CodeBuildプロジェクトを実行します。

「ビルドステージを追加する」の画面で「AWS CodeBuild」を選択します。 次に、プロジェクト名を選択します。プロジェクトがない場合はプロジェクトを作成するために、「プロジェクトを作成する」ボタンをクリックします。
当画面でデプロイ用の環境変数を設定ができます。


5. デプロイの設定

「デプロイステージを追加する」の画面でデプロイプロバイダーでAWS Elastic Beanstalkを選択して、アプリケーション名、環境名を入力します。


6. レビュー

レビューの画面で設定した情報を確認します。全部の情報はOKだったら、「パイプラインを作成する」のボタンをクリックします。


7. buildspec.ymlの設定

ソースコードのRootフォルダーでbuildspec.ymlファイルを作成します。

version: 0.2

phases: install: runtime-versions: nodejs: 16 commands: - npm -v - yarn -v - npm config set //npm.pkg.github.com/:_authToken=YOUR_PRIVATE_TOKEN
pre_build: commands: - yarn - yarn run check
build: commands: - yarn build

artifacts: files: - '*/'

cache: paths: - 'node_modules/*/**'

このbuildspec.ymlファイルは、AWS CodeBuildのビルドプロジェクトで使用するために使用されます。ビルドプロセスの3つの段階が定義されており、それぞれにコマンドが含まれています。

最初の段階は、「install」です。この段階では、Node.jsランタイムバージョン16を使用し、npmとyarnのバージョンを表示し、作成した「YOUR_PRIVATE_TOKEN」を設定するnpmコマンドを実行します。

次の段階は、「pre_build」です。この段階では、yarnコマンドを使用して必須なパッケージをインストールし、「yarn run check」コマンド等で解析ツールを実行してコード品質を確認します。

最後の段階は、「build」です。この段階では、「yarn build」コマンドを使用してアプリケーションをビルドします。

「artifacts」セクションでは、すべてのファイルがアップロードされるように、ワイルドカードを使用しています。

最後に、「cache」セクションでは、キャッシュされるファイルのパスが指定されています。ここでは、node_modulesディレクトリ以下のすべてのファイルがキャッシュされます。

* 詳しく設定については下記リンクを参照してください。
CodeBuild のビルド仕様に関するリファレンス - AWS CodeBuild


8. 終わりに

テストするために、ちょっとソースを修正して、GitHubへ「feature/pipeline」をプッシュします。実行が成功すると、下記の表示となります。

Pipelineの基本的な機能紹介は以上となります。間違い等がありましたら、コメントお願いします。

ご覧いただきありがとうございました。

Youtubeライブ配信の埋め込みリンクを設置する話

はじめに

凄まじい寒波によりキッチンの水道管が凍りました。水が出ない半日を過ごしたid:rosoneです。 (更に近所では水道管が破裂していました🙄)

さて、Webシステムの開発をしている中で、ライブ配信機能を追加してみるのはどうか?というアイディアが出ました。 少し掘り下げで考えてみます。

  • ライブ配信機能をイチから実装していくと、開発コストだけでなくインフラ面でのコストも高くつく
  • 何かしらの方法でライブ配信を行い、自前のWebシステム上でユーザーが配信を見れる形であれば良さそう
    • ライブ配信のプラットフォームを立ち上げたいわけではない

上記により、例えばYoutube等の既存のプラットフォームを使って配信をし、自前のWebページに配信動画のプレイヤーを配置してあげれば、低コストでスモールスタートすることができそうです。

以上の背景から、オープン/クローズドは問わず1:nの形で配信できるプラットフォームの中から実現できそうなサービスを調べたところ、YoutubeとZoomが候補に上がりました。

Youtubeは非常に簡単にお試しすることができたので、今回はYoutubeライブ配信のページ埋め込みについてまとめます。

Zoomの方は公式のSDKが公開されており実現はできそうなのですが、ある程度しっかりとした実装が必要になりそうなため、お試しがうまく行ったら別の機会でブログにまとめたいと思います。

Youtubeライブから埋め込み用リンクを取得

ゆったりとしたjazzのライブ配信をお借りします。

埋め込みリンクは以下の手順で取得できます。

以下の埋め込みリンクを取得できました。

 <iframe width="560" height="315" src="https://www.youtube.com/embed/YSAodnpu1OA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

HTMLの準備

Webページのテンプレートを以下のサイト様からお借りします。

テンプレートのHTMLをブラウザで開くと、おしゃれなページが表示されました。

この写真部分をYoutubeライブに差し替えていきます。

埋め込みリンクを設置

今回はChromeの検証機能を使用し、ソース上で差し替え対象の写真を指定している箇所を特定します。

エディタでHTMLを開き、該当箇所に埋め込みリンクを差し替えていきます。

コード差し替え後に画面を表示すると、Youtubeライブ配信のプレイヤーが表示されました。

レイアウトが崩れているので、表示位置とサイズを調整します。

いい感じに配置できました。

コメントやいいねなどの付属機能は付いていないですが、シークバーの追っかけ再生、再生速度や画質変更などの基本的な再生機能は本家Youtubeと同等で利用できるようです。

最後に

レイアウトなど気にしなければ、モノの数分で自前のページにYoutubeライブのプレイヤーを設置することができました。

今回はソースを直接編集していますが、実際の運用では同じように毎回ソースを修正してデプロイしてというのは現実的ではないですね。

自前のWebシステム上で配信動画のURLを入力して更新するような仕組みだけ作ってあげれば、「はじめに」で記載したアイディアを実現できそうです。

  1. Youtubeライブ配信を開始
  2. Youtube上から埋め込みリンクを取得
  3. 自前のWebシステム上でURLを入力

ちなみに、はてなブログに埋め込みリンクをそのまま設置すると、下記のようになりました。

寒い日が続きますが、水道管の凍結対策も忘れずにお過ごし下さい。

バタフライ・エフェクト

どんな小さな出来事でも連鎖反応で未来に大きな影響を及ぼす「バタフライ・エフェクト」。ゲームや映画で良く使われる演出ですね。

今回は、以下のローレンツ方程式により、バタフライ・エフェクトの現象を確かめてみます。

x, y, zの変数とp, r, bの定数の常微分方程式です。定数値は、p=10, r=28, b=8/3 をローレンツさんは用いています。

1. ローレンツ方程式を定義

def lorenz(x, y, z, p=10, r=28, b=8/3):
    dot_x = -p * x + p * y
    dot_y = -x * z + r * x - y
    dot_z = x * y - b * z
    return dot_x, dot_y, dot_z

2. 時間間隔とステップ数を設定

dt = 0.01
num_steps = 15000

3. 空の配列を作成

xs = np.empty(num_steps + 1)
ys = np.empty(num_steps + 1)
zs = np.empty(num_steps + 1)

4. 初期値を設定

初期値①

xs[0], ys[0], zs[0] = (1., 1., 1.)

初期値②(0.001だけ増やす)

xs[0], ys[0], zs[0] = (1., 1., 1.001)

5. 座標生成

for i in range (n_steps):
    dot_x, dot_y, dot_z = lorenz(xs[i], ys[i], zs[i] )
    xs[i + 1] = xs[i] +  (dot_x * dt)
    ys[i + 1] = ys[i] +  (dot_y * dt)
    zs[i + 1] = zs[i] +  (dot_z * dt)

6. 描画

初期値の違いがどのように結果に影響してくるのか。グラフ描画(ローレンツ・アトラクタ)により確認してみます。

初期値①(1.000, 1.000, 1.000)

初期値②(1.000, 1.000, 1.001)

ほんの僅かな初期値の違いにより、周回する軌道が異なってくることが確認できました。まさにカオスです。

予測には精度の高い初期値(観測値)が大事なのですね。

芝大門から眺める愛宕山

Pythonで3D地形図化 - Briswell Tech Blog

年の瀬も間近になってまいりました。ラストスパートですね!

弊社のオフィスがある芝大門の近くにある愛宕山
天然の山としては東京23区内最高峰(25.7m)で、かつては江戸の見晴らしの名所と言われていました。

愛宕山 | 錦絵でたのしむ江戸の名所

こちら(出典:国立国会図書館)のように愛宕山は錦絵にも描かれています。
現在は、周辺が高層ビルに囲まれているため、かつてのように見晴らすことはできなくなりましたが、急な石段(出世の石段)も現存し、存在感を残しています。

ふと感じたのが...
愛宕山から見る江戸(愛宕山→江戸)は、上記のような錦絵や江戸後期の写真にも残っているので、どのような眺めであったのか確認できるのですが、
自分が今いる芝大門から見る愛宕山(江戸→愛宕山)はどのような眺めだったのか。町屋や大名屋敷も数メートルほどの高さだったので、愛宕山を眺めることができたはず。

現在の3D地形図をもとにそれを確認してみようと思います。

地理院地図 / GSI Maps|国土地理院

こちらの地理院地図の3D表示機能を使い

  • ズームレベル:13
  • タイルのX座標:7276
  • タイルのY座標:3226

芝大門愛宕山が含まれる上記のタイルのobjファイル(3Dモデルフォーマット)をダウンロードします。

そのobjファイルをパワポで手軽に3Dビューしてみます。

当時はこのような眺めだったのですね。感動です。

良いお年をお迎えください。