TECH PLAY

電通総研

電通総研 の技術ブログ

822

みなさん、こんにちは。 電通 総研 金融ソリューション事業部の鈴木です。 今回は、 AWS CodeDeployで Amazon ECSに対してアプリケーションをBlue/Greenデプロイした際に発生したエラーについて、原因と解決方法を記載します。 アプリケーションの構成 発生した事象 原因 解決方法 まとめ アプリケーションの構成 今回紹介するアプリケーションの全体構成は、以下のとおりです。 (今回の記事に関係しない周辺リソースは省略しています) アプリケーションはECSで管理しており、 ロードバランサー にApplication Load Balancer(ALB)を配置しています。 デプロイについて、 GitHub ActionsからコンテナイメージをECRにプッシュし、CodeDeployによってBlue/Greenデプロイを実行しています。 Blue/Greenデプロイとは、アプリケーションのデプロイに伴うダウンタイムを最小限に抑え、動作検証後に ロールバック が可能なリリースの運用方式です。 詳しくは、 CodeDeploy によるECS でのBlue/Greenデプロイの話 を参照してください。 発生した事象 GitHub Actionsに設定したCDワークフローから稼働中のアプリケーションに対して、新しいバージョンのアプリケーションをデプロイした際に以下のエラーが発生しました。 The ELB could not be updated due to the following error: Primary taskset target group must be behind listener... 上記のエラーにより、CodeDeployのデプロイフローが動作せず、新しいバージョンのアプリケーションのデプロイが失敗しました。 (CodeDeployで「デプロイの再試行」や、ECSで「新しいデプロイの強制」を用いてデプロイを再実行してもエラーは解消しませんでした) 原因 結論としては、ECSタスクが指定しているターゲットグループと、ALBのリッスンしているターゲットグループの不一致が原因でした。 ターゲットグループとは、ELB (Elastic Load Balancing) の コンポーネント で、 トラフィック を分散する複数のターゲットをグループ化したものです。ターゲットは、 Amazon EC2 インスタンス 、IP アドレス、Lambda関数などがあります。 エラーについて、 AWS 公式ページに以下のような記述がありました。 このエラーは、オプションのテストリスナーを設定しており、そのリスナーに間違ったターゲットグループが設定されている場合に発生する可能性があります。 Amazon ECS のデプロイに関する問題のトラブルシューティング 上記の通り、ECSタスクが指定しているターゲットグループとALBのリスナールールで指定しているターゲットグループを調べてみたところ、下記のようになっていました。 ※ 画像について、都合により各リソース名はマスクしています。 ※ ECSタスクのターゲットグループは「target-group-1」、ALBのリスナールールは「target-group-2」としています。ターゲットグループが異なることを表しています。 ECSのタスク ALBのリスナールール 図にすると以下のようになっており、ECSタスクとALBのリスナールールで指定しているターゲットグループが不一致していることでエラーとなっていました。 解決方法 ALBのリスナールールを手動で変更し、起動中のECSタスクと同様のターゲットグループをリッスンするように修正することで解消しました。 (ALBのリスナールールで指定しているターゲットグループを「target-group-2」から「target-group-1」に変更) 上記の修正により、ECSタスクで指定しているターゲットグループがALBのリスナールールで指定しているターゲットグループと一致します。 これにより、CodeDeployでデプロイを再試行することにより新しいリソースをデプロイすることができました。 まとめ 本記事ではCodeDeployでECSに対してアプリケーションをデプロイした際のエラーについて原因と解決方法を記載しました。 インターネットを調べても同様の記事を見つけられなかったため、備忘として残したいと思います。 ECSタスクとALBのリスナールールで指定しているターゲットグループがずれた根本原因についてはいまだに特定できていないため、継続調査していこうと思います。 以上、同様の事象が発生した方の役に立てれば幸いです。最後までお読みいただきありがとうございました。 私たちは一緒に働いてくれる仲間を募集しています! 【金融×IT】システム アプリケーション・アーキテクト 【金融×IT】クラウドアーキテクト ◎技術力を備えたリーダを目指せる フルサイクルエンジニア 執筆: @suzuki.takuma 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
アバター
皆さんこんにちは!コーポレート本部システム推進部の佐藤太一です。 突然ですが、8月23日に完全オフラインイベントを開催します!その名も「 電通 総研 Architect Meetup」です。 電通 総研のアーキテクトが登壇し、普段の仕事ぶりについてお話する貴重な機会です。 イベントの前半では、事業部門の若手アーキテクトがそれぞれの仕事について紹介します。普段は外部でお話ししない2人なので、このレアな機会をお見逃しなく!登壇者に直接質問できる時間も設けていますので、 電通 総研について気になっている方はぜひご参加ください。 後半は、XI本部のアーキテクトである 米久 保さんと金融ソリューション事業部のアーキテクトの水野さんが登壇し座談会形式でお話しします。 米久 保さんは、7月22日に発売される「 アーキテクトの教科書 価値を生むソフトウェアのアーキテクチャ構築 」の著者です。 このセッションでは、社外のアーキテクトも参加し、アーキテクトとしての考え方やその実践、要素技術への取り組み方や組織論など幅広く議論する予定です。 私、佐藤太一も司会進行役として登壇します。オフラインならではの熱い議論をお届けしますので、ぜひご期待ください! イベントに興味を持った方は、以下のサイトからお申し込みください。 電通総研 Architect Meetup 参加申し込みサイト たくさんのご参加をお待ちしています! 執筆: @sato.taichi 、レビュー: @handa.kenta ( Shodo で執筆されました )
アバター
こんにちは、 電通 総研金融ソリューション事業部の飯田です。 前編 では、音に応じて位置、回転、スケールを変化させる方法をご紹介しました。 この記事では、音に応じてマテリアルを変化させる方法をご紹介します。 前編 の続きになっていますので、まだご覧になっていない方は前編もご一読ください。 実行手順 マテリアルを作成、ブループリントに適用する ブループリントで、動的なマテリアルを作成、初期設定する ブループリントで、マテリアルを動的に変化する 1. マテリアルを作成、ブループリントに適用する コンテンツブラウザ上で右クリックを行い、「マテリアル」を選択します。 マテリアルが作成されました。 マテリアルをダブルクリックすると、専用のウィンドウが開かれます。 このウィンドウで、マテリアルの見た目を設定します。 まず、ベースの色を作ります。 ベースの色は、マテリアルの「ベー スカラー 」で設定できます。 グラフ上を右クリックし、「Constant3Vector」ノードを作ります。 RGBの三次元情報を扱うため、マテリアル関連の実装では基本的にベクトルを使います。 左下の詳細パネルからConstantをダブルクリックし、ベースにしたい色を設定してOKを押します。 ここでは黄色に設定しました。 先ほど作った「Constant3Vector」ノードと、「ベー スカラー 」をつなぎます。 左上のサンプルビューで分かるように、ベースの色が黄色に変わりました。 次に、マテリアルから放射される光の色を作ります。 放射は、マテリアルの「エミッシブカラー」で設定できます。 今回は、ベースの色と同じにしたいため、上記で作ったConstant3Vectorノードからつなげました。 内側から光っているような表現に変わったことが分かります。 さらに、放射の強さを設定するためのパラメータを用意しておきます。 「ScalarParameter」ノードを作ります。 一律に強さを設定したいため、 スカラー (1次元)のパラメータを使っています。 パラメータを適切な名前に変更します。ここでは「Emissive Strength」にしました。 詳細パネルのDefault Value は1.0にしておきます。 乗算(Multiply)ノードを作ります。 下記のように、放射の色と、強さのパラメータを乗算ノードの入力につなぎ、出力を「エミッシブカラー」につなぎます。 これにより、放射の色と放射の強さが乗算されるようになりました。 放射の強さの値を上げることで、光ったような表現にできるため、今回は、この放射の強さのパラメータ「Emissive Strength」を音に応じて変化させていきます。 次に、作成したマテリアルを、前編で作ったブループリントに紐づけます。 前編 で作ったブループリントをダブルクリックしてウィンドウを開きます。 ビューポートタブで、 コンポーネント パネルでStatic Meshを選択します。 詳細パネルのマテリアルで、先ほど作ったマテリアルを選択します。 ここまでで、マテリアルの作成と適用は終了です。 2. ブループリントで、動的なマテリアルを作成、初期設定する イベントグラフタブに切り替えます。 ここから前編までで作成したブループリントに実装します。 「On Audio Playback Percent」ノードの後に、ノードを加えていきます。 「Create Dynamic Material Instance」ノードを作ります。 ダイナミックマテリアル インスタンス を作るノードです。 ダイナミックマテリアル インスタンス は、外部からマテリアルのパラメータを変化させることができます。 また、「Parent」で、先ほど作成したマテリアルを選択します。 作られたダイナミックマテリアル インスタンス 用に、変数を作成します。 左のマイブループリントタブから、「変数」の右にあるプラスアイコンをクリックして変数を作ります。 名前を「Dynamic Material Instance」としました。 名前の右の領域をクリックして、型を「Material Instance Dynamic」の「オブジェクト参照」を選択します。 作成した変数を、グラフ上に ドラッグ&ドロップ して、Set Dynamic Material Instanceを選択します。 画像のように、「Create Dynamic Material Instance」ノードの「Return Value 」をつなぎます。 これで「Dynamic Material Instance」変数に、Create Dynamic Material Instanceノードで作ったものがセットされました。 「Set Material」ノードを作ります。 「ターゲット」に設定されているオブジェクトに、「Material」で設定されているマテリアルをセットするノードです。 Dynamic Material Instance変数を、 ドラッグ&ドロップ して、Get Dynamic Material Instanceを選択して、「Material」に「Dynamic Material Instance」変数をつなげます。 ここまで作ったノードを、下記画像のようにつなげます。 ここまでで、 動的に制御するために、1で作ったマテリアルから、ダイナミックマテリアル インスタンス を作る 作ったダイナミックマテリアル インスタンス をマテリアルとして、オブジェクトに設定する ができました。 次は、どのように動的に変化させるかを実装していきます。 3. ブループリントで、マテリアルを動的に変化する ブループリントのイベントグラフタブに切り替えます。 前編までで作成した「Set Relative Transform」ノードの後に、ノードを加えていきます。 「Set Scalar Parameter Value 」ノードを作ります。 上述と同様にDynamic Material Instance変数を、「ターゲット」につなぎます。 「Parameter Name」に、1. で作成した音に応じて変化させたいパラメータの名前を入力します。 ここでは「Emissive Strength」を入力します。 また、「 Value 」に、振幅のデータとして「Get Cooked Amplitude Envelope Data」の「Out Envelope Data」をつなぎます。 さらに、放射の具合を強調できるよう、乗算(Multiply)ノードを作成してみました。 値は6としています。 ここまでを保存して、シーンビューで確認してみます。再生ボタンを押します。 gifファイルのため、音との同期は伝えられず少しわかりづらいですが、スケールが小さくなっているときには放射が抑えられていることが分かります。 以上が、音に応じてオブジェクトのマテリアルを変化させる方法でした。 おわりに 後編では、音に応じてマテリアルを変化させる方法をご紹介しました。 ここでは放射の強さをパラメータとして設定しましたが、マテリアルには粗さや金属っぽさ、透明度など他にも質感を表現する要素が多くあるので、表現の可能性が広いと思いました。 最後までご覧いただき、ありがとうございました。 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! 電通総研採用ページ 執筆: @iida.maya 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
こんにちは、 電通 総研金融ソリューション事業部の飯田です。 今回は、 Unreal Engine 5で、音に応じてオブジェクトの位置、回転、スケールやマテリアルの表現を変化させる方法をご紹介します。 前編で位置、回転、スケールを変化させる方法、後編でマテリアルを変化させる方法をご紹介します。 検証環境 / ソフト OS:Windows11 GPU : NVIDIA GeForce RTX 4090 Game Engine: Unreal Engine 5.2.1 実行手順 音データを用意する ブループリントを作成する ブループリントに、 コンポーネント を追加する ブループリントで、音楽を再生する ブループリントで、Transformを動的に変化する Unreal Engine では、ブループリントを使用して、ゲーム内の挙動を実装していきます。 ブループリントとは、 スクリプト を視覚的に実装するシステムです。 プログラミングで言う「関数」「オブジェクトの参照」「ゲームプレイイベント(ボタン押下処理の判定など)」をノードと呼ばれる四角いボックスで表現し、このノードをつなぎあわせていくことでゲーム内実装を作っていきます。 今回は、ブループリントを使って、「指定の音楽を再生」「再生している音に反応するようにオブジェクトの位置、回転、スケールが変わる」の2段階で実装していきます。 こちらの記事 でも、ブループリントと衝突を使った実装を扱っています。ぜひご一読ください! 1. 音データを用意する コンテンツブラウザ上に、再生したい音楽を ドラッグ&ドロップ します。 なお、音楽は.wavファイルの形式である必要があります。 これで、音楽が サウンドウェーブ として読み込まれました。 サウンドウェーブ をダブルクリックすると、専用のウィンドウが開きます。 解析>Envelope>Enable Amplitude Envelope Analysisにチェックを入れて、左上のフロッピーアイコンで保存します。 サウンドウェーブ 上を右クリックし、「キューを作成」をクリックします。 サウンド キューが作成されました。 この サウンド キューを使って音楽を再生します。 2. ブループリントを作成する コンテンツブラウザ上で右クリックを行い、「ブループリント クラス」を選択します。 表示されるクラス選択ウィンドウで、「Actor」を選択します。 ブループリントが作成されました。 3. ブループリントに、 コンポーネント を追加する コンポーネント とは、そのブループリントが持っておくべき要素のことです。 今回は、再生する音の要素として「Audio」、音に反応する形状の要素として「Static Mesh」を追加していきます。 作成したブループリントをダブルクリックすると、専用のウィンドウが開かれます。 ウィンドウで、ビューポートタブになっていることを確認します。 左側の コンポーネント パネルから、「+追加」ボタンを押します。 コンポーネント の検索欄で「Audio」と入力し、Audioをクリックします。 同様に コンポーネント の検索欄で「Static Mesh」と入力し、Static Meshをクリックします。 コンポーネント が2つ追加されました。 次に、 コンポーネント で実装に必要な設定をしていきます。 コンポーネント パネルのAudio コンポーネント をクリックし、右側の詳細パネルの サウンド >Soundで、事前準備で作成した サウンド キューを選択します。 また、 アクティベーション >Auto Activeのチェックを外しておきます。 コンポーネント パネルのStatic Mesh コンポーネント をクリックし、スタティックメッシュ>Static Meshで、音に反応させるメッシュを選択します。 今回はUEのプリセットで提供されている、球状のメッシュ「EditorSphere」を選択しています。 ここまでで、 コンポーネント の作成と設定が完了しました。 4. ブループリントで、音楽を再生する ここからノードをつなげて、処理を加えていきます。 イベントグラフタブに切り替えます。 「On Audio Playback Percentにイベントをバインド」ノードを作ります。 中央のグラフ上で右クリックし、「On Audio Playback Percentにイベントを割り当てる」をクリックします。 自動で「On Audio Playback Percent イベント」が作成されます。 「On Audio Playback Percent イベント」は、音楽が再生されている間繰り返し実行されるイベントで、音楽の進行度合いをパーセンテージで計算できます。 (パーセンテージの部分は今回は使いません。) 先ほど作成したAudio コンポーネント を参照するようにします。 左下のマイブループリントパネルから、変数>Audioを、イベントグラフ上に ドラッグ&ドロップ し、「Get Audio」をクリックします。 「Play」ノードを作ります。 音楽を再生するノードです。「ターゲット」で、再生したい音楽を指定できます。 ノードを画像のようにつなげます。 ここまでで、ゲーム開始後に 音楽が再生されている間、繰り返し実行されるイベントを登録する 音楽を再生する ように、実装できました。 次に、繰り返し実行されるイベントとして、「再生中の音楽に応じて、オブジェクトのスケールが変わる」を実装していきます。 5. ブループリントで、Transformを動的に変化する 「Get Cooked Amplitude Envelope Data」ノードを作ります。 再生中の振幅データを取得するノードです。「Out Envelope Data」で、振幅を渡すことができます。 「Set Relative Transform」ノードを作ります。 位置、回転、スケールの情報を持ったTransformの情報を、「ターゲット」につながっているオブジェクトに対して設定するノードです。 位置、回転、スケールに分けるため、「New Transform」上で右クリックし、「構造体ピンを分割」をクリックします。 今回は、スケールを変えてみようと思うので、「New Transform Scale」の上で右クリックし、さらに「構造体ピンを分割」をクリックします。 「Get Relative Transform」ノードを作ります。 「ターゲット」につながっているオブジェクトの現時点のTransformの情報を、取得するノードです。 こちらも位置、回転、スケールに分けるため、「Return Value 」上で右クリックし、「構造体ピンを分割」をクリックします。 今回は、スケールに振幅データをつなげて、音に応じてスケール全体が変わるようにしてみます。 ノードを画像のようにつなげます。 位置と回転は変化させるつもりがないので、「Get Relative Transform」のLocationとRotationは、そのまま「Set Relative Transform」のLocationとRotationにつないでいます。 ここまでで、 再生中の音楽(の振幅)に応じて、スケールが変わる 上記は、イベントとして登録されているため、音楽の再生中に繰り返し実行される ができました。 保存して、シーンビューで確認してみます。 コンテンツブラウザにある作成したブループリントを、シーンビューに ドラッグ&ドロップ します。 上部の再生ボタンを押します。 残念ながらgifファイルのために、音との同期は伝えられないのですが 音の大きさに合わせて球のスケールが変化しています。 ここまでは、スケールを変化させましたが、同様に位置と回転を変化させることもできます。 上述した「構造体ピンを分割」「構造体ピンを再結合」を使って、変化させたい値に振幅のデータをつなげるだけです。 例えば、下記のようにすれば、高さ(Z)の位置のみを変えるようにできます。 変化の度合いの強弱を調整したい場合は、乗算ノードが便利です。 乗算ノードの下のボックスに値を入力すると、乗算が行われます。 高さ(Z)の位置のみを変えたものは、下記になります。 以上が、音に応じてオブジェクトの位置、回転、スケールを変化させる方法でした。 おわりに 前編では、音楽に応じてオブジェクトの位置、回転、スケールを変化させる方法をご紹介しました。 このやり方では音楽全体の振幅データを使っているため、特定の周波数や楽器に応じて変化していませんが、理想は周波数や楽器に応じて表現を変えられることだと思います。 例えば、周波数を解析して、周波数ごとにオブジェクトのTransformを変化させることができれば、オーディオビジュアライザーが作れます。 このような表現の幅が広がるような学習をしていき、今後ご紹介していければと思います。 後編では、音に応じて動的にマテリアルを変更する方法をご紹介します。 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! 電通総研採用ページ 使用した音のデータ: https://pixabay.com/ja/sound-effects/grinder-drum-loop-6697/ 参考: https://youtu.be/nTCboJrkI8o 執筆: @iida.maya 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
こんにちは。コミュニケーションIT事業部 ITソリューション部の英です。 普段はWebアプリや スマホ アプリの案件などを担当しています。あと、趣味でAIを勉強しています。 いつもはAI関連の記事を書いていますが、今回は AWS の認証サービスである Amazon Cognito について検証します。 近々案件で使いそうなので、そのための予習です。 さて、前回は トーク ン発行までのフローを解説しました。 今回はこれらの トーク ンを使用して、 AWS 上のリソースに対するアクセス制御を行うための設定をしていきます。 → 前回の記事 今回の構成はこちらです。 (引用元: ユーザープールと共に API Gateway と Lambda を使用してリソースにアクセスする ) #ここから本題 STEP1: API 用のLambda関数を作成する APIGatewayを経由して、このLambda関数を呼びだすことにします。 パラメータで変数を受け取って、その中身を返却するだけのシンプルな作りです。 import json def lambda_handler(event, context): # イベントのログを出力 print("Received event: " + json.dumps(event, indent=2)) # リクエストボディからデータを抽出 body = json.loads(event.get('body', '{}')) # データの抽出 key1 = body.get('key1') key2 = body.get('key2') # データの処理(ここでは単純に受け取ったデータをレスポンスに含める) response_message = f"Received key1: {key1}, key2: {key2}" # アクセストークンが有効である場合のレスポンス response = { 'statusCode': 200, 'body': json.dumps({ 'message': 'Access token is valid. Hello from Lambda!', 'response_message': response_message }) } return response STEP2:APIGatewayを作成する AWS コンソールで新しい API を作成しましょう。 STEP3:オーソライザーを作成する オーソライザーのタイプはLambdaかCognitoかを選択できます。 今回はCognitoを選択しましょう。 より細かな検証を行いたい場合は、Lambdaでカスタムロジックを書くことができます。 トーク ンのソースにAuthorizationを指定するのを忘れないようにしてください。 「オーソライザーをテスト」でID トーク ンの検証ができます。 Cognitoから受け取った「id_token」を貼り付けて実行すると、個人に紐づく情報が出力されます。 これをクレーム(claims)といいます。 ID トーク ンの中身については以下の公式リファレンスを参照してください。 → ID トークンの使用 STEP4: API キーを作成する API を呼びだすために必要な API キーを発行します。 開発、検証、本番と環境ごとに API キーを発行しましょう。 今回は1つだけ作成します。 STEP5:メソッドを作成する 今回はPOSTで受け取って、Lambdaを起動する設定にします。 STEP1で作成した関数を指定しておきましょう。 API キーを必須とし、リク エス トバリデーターではヘッダーを検証する設定にしておいてください。(Authorization) STEP6:使用量プランを作成する ここでは API の同時リク エス ト数などを設定できます。環境ごとに設定することができます。 これとは別に API の性能はクォータも影響してきますので、環境ごとの設定を確認し、必要であれば引き上げ申請を行いましょう。 → 使用量プランの API レベルとステージレベルのスロットリング目標の設定 STEP7:プランに API キーを追加する STEP6で作成したプランに API キーを追加します。 これでステージ(dev)と API キーの紐づけが完了しました。 API のエンドポイントは環境ごとに吐き出されます。 STEP8:リク エス ト用の スクリプト 作成 今回はCloud9で作成した Python スクリプト から API をコールします。ここの手順はPostmanでも何でもいいです。 分かりやすいように API キーや トーク ンをベタ打ちしていますが、本番開発では暗号化したり、 環境変数 に登録するなど対策してから使用してください。 import requests import json # API GatewayのエンドポイントURL api_url = 'https://(APIのエンドポイント)/dev' # 取得したIDトークン(※前回の記事を参照) id_token = '(Cognitoから受け取ったid_token)' # APIキー api_key = '(APIキー)' # API Gatewayに送信するデータ data = { 'key1': 'dentsu', 'key2': 'soken' } # ヘッダーの設定 (Authorizationでid_tokenを渡します、x-api-keyでAPIキーを渡します) headers = { 'Content-Type': 'application/json', 'Authorization': id_token, 'x-api-key': api_key } # デバッグ情報の表示 (必要に応じて使用してください) #print("Sending request to API Gateway...") #print(f"URL: {api_url}") #print("Headers:") #for key, value in headers.items(): # print(f" {key}: {value}") #print("Payload:") #print(json.dumps(data, indent=2)) # POSTリクエストを送信 try: response = requests.post(api_url, headers=headers, data=json.dumps(data)) response.raise_for_status() # HTTPエラーが発生した場合に例外をスロー # レスポンスの表示 print(f'Status Code: {response.status_code}') print('Response Headers:') for key, value in response.headers.items(): print(f' {key}: {value}') print('Response Body:') print(response.json()) except requests.exceptions.RequestException as e: print(f"Request failed: {e}") if e.response is not None: print(f"Response Code: {e.response.status_code}") print(f"Response Body: {e.response.text}") STEP9:検証 パターン1:正常系 まずは、すべての情報が正しい場合のリク エス トを実行してみます。 ステータスコード 200で返ってきていることが確認できます。 POSTで投げた値( dentsu ,soken)もLambda側で受け取れていることが確認できます。 パターン2:異常系(不正なid_token) id_tokenに適当な文字を加えて実行してみます。 頭にIjyou(いじょう)を足しました。 401(Unauthorized) が返ってきました。 Cognitoオーソライザーが正しく機能しているようです。 このユーザー(id_token)は認証済みではないといっています。 パターン3:異常系(不正な API キー) api _keyに適当な文字を加えて実行してみます。 頭にIJyou(いじょう)を足しました。 403(Forbidden) が返ってきました。 API キーが正しく機能しているようです。 API キーが無効だといっています。 今回はこれ以上の検証をしませんが、その他の ゲートウェイ レスポンスについては公式のリファレンスを参照してください。 → ゲートウェイレスポンスのタイプ さいごに APIGatewayとCognitoを統合する方法を解説しました。 今回はCognitoオーソライザーを使用して、id_tokenのみ確認しましたが、 access _tokenも検証したい場合はLambdaオーソライザーを選択して独自に検証ロジックを記述する必要があります。 → API Gateway Lambda オーソライザーを使用する これからも AWS 関連の検証記事をたくさん書いていきます。 ↓ のスターを押していただけると嬉しいです。励みになります。 最後まで読んでいただき、ありがとうございました。 私たちは一緒に働いてくれる仲間を募集しています! コミュニケーションIT事業部 執筆: 英 良治 (@hanabusa.ryoji) 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
アバター
こんにちは。コーポレート本部 サイバーセキュリティ推進部の耿です。 大好きだった Aurora Serverless v1 が 2024/12/31 をもってサポート終了ということで、泣く泣く Aurora Serverless v2 へ移行しました。 公式 では クラスタ のアップグレードを使用した手順が紹介されていますが、今回はそれではなく Aurora Serverless v2 クラスタ を新規に作成し、 mysqldump によるデータ移行という方法を取りました。その概要を書き残します。 Aurora Serverless v1 の好きなところ なぜ mysqldump を使ったのか 作業概要 1. 事前準備:CDKで Serverless v2 クラスタを作成 2. 事前準備:旧DBのテーブル定義の確認 3. データ移行 4. データ移行後作業 さいごに Aurora Serverless v1 の好きなところ 正直なところ v1 を使い続けたいと思っていました。 v1はv2よりも「サーバレス」という言葉がよく似合う インスタンス や AZ を意識する必要がなく、AZ 障害時に自動でフェイルオーバーする アクティビティがしばらくない場合は一時停止できる。特に開発環境などにおいて費用の節約になる (2024/11/21追記) v2でも特定のエンジンバージョン以上にて一時停止できるようになりました! Introducing scaling to 0 capacity with Amazon Aurora Serverless v2 | AWS Database Blog v2よりも安い 機能面の違いがあるとはいえ、同じキャパシティではv2の半分の料金である Data API 、クエリエディタが便利 踏み台を管理せずにDB接続できるのが楽 23年末に Serverless v2 の PostgreSQL にて Data APIがサポート されたが、 MySQL は執筆時点ではまだサポートされていない・・・ (2024/9/30追記) Aurora MySQL 3.07以上で Data APIが使えるようになりました! しかしサポート終了には対応しなければならないので、いい感じの移行の方法を検討しました。 なぜ mysqldump を使ったのか 公式の移行ガイド では クラスタ のアップグレードを利用する方法が紹介されていましたが、今回の環境で適用するには難点があると判断しました。一番の理由は CDK を利用してリソース管理していたためです。 まず、CDK/CloudFormationによるデプロイでは既存 クラスタ のアップグレードを実施できない(DB作り直し扱いになる)ため、手動でアップグレードを実施する必要があります。手動でDB クラスタ をアップグレードすると、CDKコードの状態と実際のDB クラスタ の状態に差分が生じてしまいます。この状態はIaCでイン フラリ ソースを管理している以上避けたいです。 cdk import や cdk migrate を使って、実際のリソースをCDK管理下に置くことはできます。しかし今回は Auroraクラスタのパスワードローテーション もCDKで実装しており、DB移行後も同様にCDKコード上でそれを表現したいです。調査した限りでは、Aurora クラスタ のパスワードを管理しているSecrets Managerシークレットや、ローテーションを実行するLambda関数も含めてきれいにCDKにimport/migrateする方法は見つかりませんでした。 逆に考えると、パスワードローテーション関連のリソースも含めてCDKできれいに管理したければ、シンプルに新しいServerless v2 クラスタ を新規にCDKから作成すれば良いということになります。今回の環境ではある程度システム停止時間を設けられるということもあり、静止点を設けてv1からv2へのデータ移行する方針で進めることにしました。 MySQL を利用していたので、 mysqldump を使うことにしました。 作業概要 1. 事前準備:CDKで Serverless v2 クラスタ を作成 従来使っていた Serverless v1 クラスタ はこんな感じで構築していました。 const auroraSubnetGroup = new rds.SubnetGroup( this , "SubnetGroup" , { vpc : vpc, vpcSubnets : { subnetGroupName : "dbSubnet" } , } ); const parameterGroup = new rds.ParameterGroup( this , "ParameterGroup" , { engine : rds.DatabaseClusterEngine.AURORA_MYSQL, parameters : { character_set_client : "utf8mb4" , character_set_connection : "utf8mb4" , character_set_database : "utf8mb4" , character_set_results : "utf8mb4" , character_set_server : "utf8mb4" , time_zone : "Asia/Tokyo" , } , } ); // Serverless v1 クラスター const myCluster = new rds.ServerlessCluster( this , "MyCluster" , { engine : rds.DatabaseClusterEngine.AURORA_MYSQL, clusterIdentifier : "my-cluster" , defaultDatabaseName : "db-name" , parameterGroup : parameterGroup, removalPolicy : RemovalPolicy.RETAIN, deletionProtection : true , vpc : vpc, vpcSubnets : { subnetGroupName : "dbSubnet" } , scaling : { minCapacity : 1 , maxCapacity : 2 , autoPause : Duration.hours( 0 ) } , securityGroups : [ dbSecurityGroup ] , subnetGroup : auroraSubnetGroup, enableDataApi : true , backupRetention : Duration.days( 7 ), } ); // マスターユーザーのシングルユーザーローテーション myCluster.addRotationSingleUser( { vpcSubnets : { subnetType : ec2.SubnetType.PRIVATE_WITH_EGRESS } , } ); // アプリケーションが使うユーザーのマルチユーザーローテーション const appSecret = new rds.DatabaseSecret( this , "AppSecret" , { username : "app" , secretName : "AppSecret" , masterSecret : myCluster.secret, } ); const appSecretAttached = appSecret.attach(myCluster); myCluster.addRotationMultiUser( "AppUserRotation" , { secret : appSecretAttached, vpcSubnets : { subnetType : ec2.SubnetType.PRIVATE_WITH_EGRESS } , } ); 新規に Serverless v2 クラスタ を次のように作ります。 const parameterGroupV2 = new rds.ParameterGroup( this , "ParameterGroupV2" , { engine : rds.DatabaseClusterEngine.auroraMysql( { version : rds.AuroraMysqlEngineVersion.VER_3_06_0 } ), parameters : { character_set_client : "utf8mb4" , character_set_connection : "utf8mb4" , character_set_database : "utf8mb4" , character_set_results : "utf8mb4" , character_set_server : "utf8mb4" , time_zone : "Asia/Tokyo" , } , } ); // Serverless v2 クラスター const myClusterV2 = new rds.DatabaseCluster( this , "MyClusterV2" , { clusterIdentifier : "my-cluster-v2" , engine : rds.DatabaseClusterEngine.auroraMysql( { version : rds.AuroraMysqlEngineVersion.VER_3_06_0 } ), vpc : vpc, parameterGroup : parameterGroupV2, vpcSubnets : { subnetGroupName : "dbSubnet" } , defaultDatabaseName : "db-name" , removalPolicy : RemovalPolicy.RETAIN, deletionProtection : true , securityGroups : [ dbSecurityGroup ] , subnetGroup : auroraSubnetGroup, // ここではライターインスタンス1つのみの構成 writer : rds.ClusterInstance.serverlessV2( "Writer" , {} ), serverlessV2MinCapacity : 0.5 , serverlessV2MaxCapacity : 2.0 , storageEncrypted : true , backup : { retention : Duration.days( 7 ) } , // バックトラック機能を有効 backtrackWindow : Duration.days( 3 ), } ); // マスターユーザーのシングルユーザーローテーション myClusterV2.addRotationSingleUser( { vpcSubnets : { subnetType : ec2.SubnetType.PRIVATE_WITH_EGRESS } , } ); // アプリケーションが使うユーザーのマルチユーザーローテーション const appSecretV2 = new rds.DatabaseSecret( this , "AppSecretV2" , { username : "app" , secretName : "AppSecret" , masterSecret : myClusterV2.secret, } ); const appSecretAttachedV2 = appSecretV2.attach(myClusterV2); myClusterV2.addRotationMultiUser( "AppUserRotationV2" , { secret : appSecretAttachedV2, vpcSubnets : { subnetType : ec2.SubnetType.PRIVATE_WITH_EGRESS } , } ); シークレットローテーションの設定はv1と全く同じです。 Serverless v1ではサポートされていなかった バックトラック機能 は便利なので有効にしてあります。 2. 事前準備:旧DBのテーブル定義の確認 v2の MySQL ではまだクエリエディタがサポートされていないので、踏み台 インスタンス を作成して接続確認をします。 v1の各テーブルの定義を確認しておきます。 SHOW FULL COLUMNS FROM <テーブル名>; 3. データ移行 データ移行本番ではアプリケーションからDBへの接続を停止し、移行の成功を確認するために各テーブルのデータ行数を確認しました。 SELECT COUNT(*) FROM <テーブル名>; そして旧DBのデータダンプを取ります。 mysqldump -u admin -p -h <HOST_NAME_V1> <DB_NAME> --set-gtid-purged=OFF > db_dump. sql グローバル トランザクション IDに関する情報を出力するとデータロード時にエラーが発生しました。グローバル トランザクション IDの変更は不要なので --set-gtid-purged=OFF オプションを付けています。 今回は MySQL 5.7 から 8.0 への移行ですが、8.0ではデフォルトの照合順序が utf8mb4_0900_ai_ci に変わっています。旧DBと同じ設定になるよう、ダンプファイル内の DEFAULT CHARSET を utf8mb4_general_ci に明示的に変えておきます。 sed 's/DEFAULT CHARSET=utf8mb4/DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci/' db_dump. sql > db_dump_modified. sql 新DBにデータをロードします。 mysql -u admin -p -h <HOST_NAME_V2> <DB_NAME> < db_dump_modified. sql ロードが完了したら、新DBの各テーブルの定義とデータ行数を確認します。 SHOW FULL COLUMNS FROM <テーブル名>; SELECT COUNT(*) FROM <テーブル名>; 4. データ移行後作業 データ移行後は以下の作業を行いました。 マスターユーザーでDBに接続し、アプリが利用するDBユーザーを作成(パスワードはSecrets Managerに作成されたシークレットから確認) 手動でSecrets Managerのパスワードローテーションを実行し、成功することを確認 アプリケーションが新DBを使用するように変更 アプリケーションの接続確認 踏み台 インスタンス 上のデータダンプを削除 しばらく運用し、問題なければAurora Serverless v1 クラスタ ーと関連リソースを削除 これで無事に Aurora Serverless v2 への移行が完了しました。 さいごに 公式の移行ガイドとは違う方法でしたが無事にデータ移行が完了し、CDKコードもきれいな状態で満足です。 踏み台 インスタンス を運用したくないので、早く MySQL もData API をサポートしないかなぁと首を長くして待っています。 さよなら、ありがとう、Aurora Serverless v1 執筆: @kou.kinyo 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
Microsoft Buildとは? Microsoft Buildのプログラム 注目アップデート情報の紹介 アップデート情報のサマリ Azure AI系のアップデート情報 Azure OpenAI Service Azure AI Studio Phiシリーズ Windows Copilot Runtime アプリケーションサービス系のアップデート情報 Azure Functions データプラットフォーム系のアップデート情報 Microsoft Fabric Azure Cosmos DB Azure Database for PostgreSQL ローコードツールのアップデート情報 Copilot Studio 開発ツール系のアップデート情報 GitHub Copilot for Azure GitHub Copilot Workspace まとめ 現地参加をしてよかったこと こんにちは。 すっかり日が経ってしまいましたが、米国シアトルで開催された Microsoft Build 2024に現地参加をしたのでリポート記事になります。 電通 総研からは、石井(製造ソリューション事業部)、尾崎(金融ソリューション事業部)、山田(X イノベーション 本部)、武者( 電通 総研USA支社)の4名が現地参加してきました。 【イベント参加情報】 米国シアトルで開催された Microsoft Build 2024に4名のメンバーで現地参加してきました! 後日、参加レポートをテックブログで公開予定です! #MSBuild pic.twitter.com/4M533irGsF — 電通 総研 テックブログ (@dentsusoken) May 23, 2024 米国 現地法人 メンバーも合流し、普段の業務では所属部署、役割がそれぞれ異なるメンバーでの参加となり、クロス イノベーション が活発な 電通 総研らしいものとなりました。 また今回の参加メンバーは4名中3名が20代であり、若手社員も積極的に海外イベントに参加できる環境が整っています。 ※ 電通 総研では Microsoft Buildに限らずさまざまな海外イベントに多様なメンバーが参加しています。 Microsoft Buildとは? Mictosoft Buildは Microsoft が主催する開発者向けの年次カンファレンスです。 今年は4,000人以上が現地参加し、その中で日本人は200名ほどだということです。 開催場所は、「シアトル コンベンションセンター Summit」という建物でかなり綺麗でした。 Microsoft Buildのプログラム Microsoft Buildのセッションタイプは Keynote 、Breakout、Lab、 Microsoft Build Stageといった種類があります。 会場の案内も各セッションタイプがどこで開催されるかで案内されていました。 Keynote は最も注目されるセッションで初日と2日目の朝に開催されます。 Breakoutは1つのセッションが45分で構成され、詳細な技術トピックを扱った発表がされます。 Labは現地限定のセッションで1時間の枠で構成され、ハンズオン形式で手を動かしながら学べるセッションになります。 注目アップデート情報の紹介 Microsoft Build 2024で発表された注目すべきアップデート情報を紹介したいと思います。 アップデート情報のサマリ 今回のアップデート情報は「Copilot Stack」を軸に、各サービスが「Copilot Stack」のどのレイヤーに位置付けられているものかを示しながらの発表でした。 特にデータ&AI領域のアップデート内容が中心で Keynote 中、幾度となく「Copilot」というワードが使われていました。 Microsoft として生成AI、ビジネスデータのプラットフォーム提供を進めていく姿勢であることがよく分かる内容でした。 Azure AI系のアップデート情報 最初にAzure AI系のアップデート情報から紹介しようと思います。 Azure OpenAI Service Azure OpenAI Service関連でのアップデートでは「GPT-4o」モデルのGAが発表されました。 すでに使われている方も多いと思いますが「GPT-4o」モデルはレスポンスが非常に速く、生成AIを活用したアプリケーションにおいて課題となっていた レイテンシー の部分で大きな改善が期待できるものです。 またAzure OpenAI Service系ではアナウンス段階ですが「Azure OpenAI Batch Service」も発表されました。 こちらは本家OpenAIのBatch API のAzure実装と思われ、低コストで大きなデー タセット に対し、Azure OpenAI Serviceの処理が適用可能になります。 Azure AI Studio Azure AI StudioもGAされ、より開発者ファーストな SDK の充実、生成AI系 フレームワーク と統合されたtrace機能のプレビュー提供開始や、Models as a Service(MaaS)のアナウンスがありました。 trace機能について実際に試した後藤さんの記事がありますので、よろしければ参照してください。 tech.dentsusoken.com Phiシリーズ 小規模な生成AIモデルである「Phi」シリーズに新しいモデルが登場し、マルチモーダル対応の「Phi-3- vision 」も発表されました。 Windows Copilot Runtime また Windows でのAI開発環境の強化の観点で「 Windows Copilot Runtime」が発表され、 Windows Copilot Libraryを利用することで Windows ネイティブアプリケーションにもAI機能の開発が可能になることが発表されました。 アプリケーションサービス系のアップデート情報 Keynote ではアプリケーションサービス系のアップデート情報は薄めでしたが、Azure Functionsに関しては多くのアップデートがありました。 Azure Functions まず Flex Consumption Planがプレビューで利用できるようになりました。 Flex Consumption Planの案内では、スケール性能が向上、仮想ネットワーク統合のサポート、料金形態もサーバレスらしいものになるということで、多くの開発者が求めているアップデート内容だったかと思います。 スケール性能に関しては、 GitHub における Flex Consumption PlanでのAzure Functionsの関数アプリのプライベートテストにおいて、1秒間で160万のメッセージをさばくほどスケールすることが紹介されていました。 またAzure FunctionsのAzure Container AppsへのデプロイもGAとなりました。 Azure Container Appsではノードに GPU マシンを利用でき、Azure Functionsで GPU が必要な処理を実行するといったシナリオも現実的なものになりました。 その他にもAzure Functionsにはバインドといった便利な機能があるので、それらを使ったアプリケーションをAzure Container Appsでも活用できるというのは大きいかなと思います。 データプラットフォーム系のアップデート情報 データプラットフォーム系のアップデートでは Microsoft Fabricが注目されがちですが、データベース系のソリューションも大きなアップデートがありました。 Microsoft Fabric Microsoft Fabricでは「Real Time Intelligecne」というストリーミングデータやイベント駆動での分析機能などが発表されました。これによってスケジュールベースではないシナリオにも対応できる点が魅力です。 Azure Cosmos DB Azure Cosmos DB for NoSQLでベクトル検索のサポートがアナウンスされました。 ベクトル検索はAIアプリケーションを実装する上で重要な要素となっており、これまではCosmos DB for MongoDB(vCore)やAzure AI Searchを利用する必要がありましたが、Cosmos DB for NoSQLでベクトル検索がサポートされることで、比較的安価にアプリケーションにベクトル検索が取り入れられるようになりました。 Cosmos DB for NoSQLでのベクトル検索ではフィルタークエリと併用できるのがポイントで、 パーティション キーでフィルタすることでパフォーマンスを高めることができます。 Azure Database for PostgreSQL Azure Database for PostgreSQL でも PostgreSQL の 拡張機能 pgvector によるベクトル検索のサポートがアナウンスされました。 RDB でのベクトル検索のサポートにより、 RDB がメインの エンタープライズ 向けのシステムにおいてもベクトル検索の活用が見込めます。 ベクトル検索の アルゴリズム として DiskANN もサポート予定とのことで、このあたりの情報はキャッチアップしておくと良さそうです。 その他、Azure Database for PostgreSQL ではAzure AI Serviceを呼びだす 拡張機能 のAzure AI 拡張がGAになりました。 この機能を活用することで SQL の中でAzure AI Serviceの呼び出しが可能になるため、 RDB の マイグレーション スクリプト などを応用することで、既存データのベクトル化などが比較的容易に実現可能な見込みがあります。 ローコードツールのアップデート情報 Power Platform系のローコードツールではCopilot Studioのアップデートが大きかったです。 Copilot Studio Copilot Studioが大幅にアップデートされ、カスタムCopilotを作るためのローコードツールとなりました。 カスタムCopilotではベースとなる Microsoft Copilotを「Knowledge」と「Actions」の2軸で適用範囲を広げていくというコンセプトになっています。 さらに「Team Copilot」というものもアナウンスされ、近い将来、CopilotがTeams会議にメンバーの一人として参加し、 ファシリテーション をするなど、人間のように振る舞うようになっていくビジョンも発表されていました。 開発ツール系のアップデート情報 開発ツール系のアップデートでもCopilot尽くしです。 GitHub Copilot for Azure GitHub Copilot for Azureは Visual Studio 、 Visual Studio Code のCopilot Chatから利用可能で、Azure上でのリソース情報まで把握し、アプリケーションの トラブルシューティング やデプロイなどの操作をCoilotで支援するものです。 GitHub Copilot Workspace GitHub Copilot Workspaceは GitHub のIssueからCopilotが計画を立ててコード生成、Pull Requestの作成までを行う機能です。 Issueに対し、解決のための計画が作成されます。 計画段階で人間が介在し、計画を編集することもできます。 計画をもとに生成されたコードを人間がレビューします。 レビューでは修正を依頼することもできます。 コードを実際に動かしたければ、Codespacesなどの機能を利用し、ブラウザ上で動作検証も実施できます。 まとめ 今回の Microsoft Build 2024では、既存のアプリケーションにAI機能を組み込むことを見据えたアップデートが多い印象でした。 Windows Copilot Runtimeの登場や各データベースサービスでのベクトル検索のサポートの充実によって、「全てのアプリケーションにAI機能を搭載可能になる」というのは現実味を帯びてきたように思えます。 Copilot Studioなどローコードツールの進化も目覚ましく、コードベースの開発を主とする開発者も積極的に利用していくものになっていく可能性もあると感じました。 本記事で取り上げたアップデート内容はほんの一部です。 セッションの アーカイブ や「Book of News」などを見ることでより詳細なアップデート内容が確認できます。 build.microsoft.com news.microsoft.com 現地参加をしてよかったこと 最後に現地参加したメンバーからそれぞれ良かった点を紹介します。 今回、現地で参加したことによって最新のアップデート情報をその場でキャッチアップできたことはモチベーションの向上にも繋がりとても良かったです。また現地でセッションなどにも参加したことで、注目されがちな Keynote 以外のコンテンツもとても勉強になると知れたことが良かったです。ハブブースで開発者と直接コミュニケーションが取れることも現地参加の醍醐味だと感じました。(山田) 現地で開発者の方々と直接会話できたことが、一番の収穫でした。各サービスの今後の展望やターゲット層、また自分が想定していなかった新たな使い方について、多くの貴重な情報を得ることができました。また、現地セッションでは、録画には残らないような貴重なノウハウを得られる機会もありました。これらの経験から、来年の参加も非常に楽しみにしています。(尾崎) ベテラン枠で参加してきました。世界中の技術者が集い、Copilotを中心とした最先端テク ノロ ジー を探求してその可能性と未来に想いを馳せながらコミュニケーションをしている姿を見ることができ、また一部それに参加することができて、自身としても改めて大きなエネルギーを得ることができたと感じています。ともすれば近視眼的な考えに陥ってしまう日常業務から離れて、こういった視座を高くする機会を得ることができる環境に感謝します。(石井) 米国 現地法人 に出向中の武者です。まずは、本社メンバーとともに Microsoft Build 2024に参加し、皆様から刺激を受けることができたことをうれしく思います。ありがとうございました。カンファレンスでは「Copilot」という言葉がどのセッションでも繰り返し使われていました。Copilotはテク ノロ ジー のあらゆる分野に影響を与え、その進化が非常に速いことを改めて感じました。米国 現地法人 としては、Copilot Studioや 電通 総研として自社開発をしている生成AIソリューションのKnow Narratorシリーズを活用して、在米邦人企業の皆様のお役に立つ必要があります。特に、Copilot StudioがPower Appsの一部になったことで、ユーザー様でのチャットボット開発や保守ができるようになったと感じます。Labセッションでは、Copilot Studioのデータベース連携やデータベースからAzure AI API の呼び出しまでを実施しました。この実装はデータベースや API の知識が必要であり、この部分こそが DENTSU SOKEN USAの価値になってくると感じました。お客様と協力して、最先端のシステム導入を米国でも進めていきたいです。(武者) 私たちは一緒に働いてくれる仲間を募集しています! AI系プロジェクトマネージャー/リーダー(◎AIコンサル ◎AIプロジェクトマネージャー) (東京)製造DX開発プロジェクトマネージャー/システム開発リーダ/ITアーキテクト (大阪)製造DX開発プロジェクトマネージャー/システム開発リーダ/ITアーキテクト AIサービス開発エンジニア クラウドアーキテクト 【金融×IT】クラウドアーキテクト ◎技術力を備えたリーダを目指せる AIソリューション開発エンジニア ◎AIビジネス創出・推進に関われる 執筆: @yamada.y 、レビュー: @miyazawa.hibiki ( Shodo で執筆されました )
アバター
こんにちは、 電通 総研金融ソリューション事業部の飯田です。 今回は、 Blender で作成したモデル、マテリアル、アニメーションを、FBX形式でUE5に取り込む方法をご紹介します。 UE内のエディターを用いてアニメーションを設定する手順については、こちらの記事を参考にしてください。 https://tech.dentsusoken.com/entry/ue_collision 検証環境 / ソフト OS:Windows11 GPU : NVIDIA GeForce RTX 4090 Blender :Blender4.0.2 Game Engine: Unreal Engine 5.2.1 実行手順 Blender でモデル、マテリアル、アニメーションを作成 Blender でエクスポート Unreal Engine でインポート マテリアルの修正 1. Blender でモデル、マテリアル、アニメーションを作成 モデル、マテリアル、アニメーションを用意します。 ここでは、モデルとしてドアのオブジェクト、アニメーションとしてドアが回転する動きを用意しました。 ドアのオブジェクトに回転の動きをつける方法は、下記の記事を参考にしています。 https://styly.cc/ja/tips/blender/nimi-blender-animation/ また、テクスチャを利用して、下記の設定で木のマテリアルを作成しています。 FBX形式でのエクスポートでは、 Blender でマテリアルを設定していても、後に Unreal Engine で再設定が必要になります(4. マテリアルの修正で詳述)。 2. Blender でエクスポート エクスポートしたいオブジェクトをすべて選択します。 選択すると、オレンジ色の枠が表示されます。 メニューバーから、ファイル>エクスポート>FBXをクリックします。 エクスポートの設定をするウィンドウが開きます。 中央部分でファイル置き場を設定し、右部分でエクスポートの詳細の設定を行います。 下記画像のように設定します。 今回は、選択したオブジェクトを出力するため、内容>対象で「選択したオブジェクト」にチェックを入れています。 トランスフォーム>スケールを適用では、「すべてFBX」にします。 Blender と Unreal Engine は基準とするスケールが異なっているため、 正しいスケールで Unreal Engine でインポートするために必要な設定です。 トランスフォーム>「前方」「上」では、作成したモデルがどの軸に向いているかに合わせます。 今回のモデルでは、手前がY軸のマイナス方向、上がZ軸のプラス方向だったため、その内容で設定しています。 また、アニメーションがあるため、「アニメーション」をベイクにチェックを入れておきます。 画面下部の入力欄で、ファイル名を決定します。 最後に、「FBXをエクスポート」を押します。 ここまでで、指定したフォルダにFBXファイルが作成されました。 3. Unreal Engine でインポート Unreal Engine で任意のプロジェクトを開きます。 コンテンツブラウザのインポートボタンを押します。 先ほど作成したFBXファイルを選択し、「開く」を押します。 FBXインポートオプションウィンドウが開くので、インポート設定をします。 まず、ウィンドウ右上の「デフォルトにリセット」ボタンを押します。 Animation>Import Animationsにチェックを入れます。 それ以外は設定を変えずに、「全てインポート」を押します。 インポートが完了すると、コンテンツブラウザに、作成したモデルとアニメーションが読み込まれます。 オブジェクトとアニメーション関連ファイルとして、ドアとフレームのスケルタルメッシュ、アニメーション、ス ケルト ン、物理アセットが読み込まれています。 マテリアル関連のファイルとして、マテリアル、テクスチャ3枚が読み込まれています。 ここで読み込まれているテクスチャ3枚は、 Blender で設定したものと同じベー スカラー 、ラフネス、ノーマルの3枚です。 各テクスチャの役割は、下記の記事をご参考ください。 https://tech.dentsusoken.com/entry/pbr-material-1 問題なく読み込めたか確認します。 「スケルタルメッシュ」と書かれているものを選択し、シーンビューに ドラッグ&ドロップ します。 オブジェクトがシーンビューに表示され、正しくインポートできていることを確認できました。 (マテリアルの反映はされないため、後ほど設定を行います。) シーンビューでアニメーションを確認するには、右下の詳細パネルから表示の設定をします。 アニメーションを行うオブジェクトを選択します。 Animation>Animation Modeを「アニメーションアセット」にします。 Animation>Anim to Playから Blender で作成したアニメーションを選択します。 スケルタルメッシュ>Update Animation in Editorにチェックを入れます。 ここまでで、アニメーションがインポートされていることを確認できました。 4. マテリアルの修正 Unreal Engine にインポートされる際、 Blender で設定していたマテリアルとテクスチャは読み込まれていますが(下記画像黄色枠)、 マテリアルがどのテクスチャを参照するかの関連付けが切れてしまっているため、 改めて関連付けを行っていくことになります。 コンテンツブラウザ上で、マテリアルをダブルクリックします。 マテリアル用のウィンドウが開きます。 あらかじめインポート時に、TexCoordノードやTexture Sampleノードが構成されています。 TexCoordノードは、インポートしたオブジェクトのUV座標の情報を持っているノードです。 Texture Sampleノードは、テクスチャの設定を行うノードです。 「ベー スカラー 」につながっているTexture Sampleノードをクリックします。 左下の詳細パネルのTexutreで、色を設定するテクスチャを指定します。 「ラフネス」につながっているTexutre Sampleノードをクリックします。 左下の詳細パネルのTexutreで、ラフネス(粗さ)を設定するテクスチャを指定します。 ラフネスはグレースケールを扱うマップのため、Sampler Typeを「リニアカラー」にします。 設定したテクスチャをダブルクリックします。 右の詳細パネルのテクスチャ>sRGBのチェックを外します。 ラフネスのテクスチャを、カラーではなくグレースケールの値を持った画像として扱うためです。 「Normal」につながっているTexture Sampleノードをクリックします。 左下の詳細パネルのTexutreで、ノーマル(凹凸)を設定するテクスチャを指定します。 NormalはRGBの各チャンネルでグレースケールを扱うマップのため、Sampler Typeを「リニアカラー」にします。 設定したテクスチャをダブルクリックします。 右の詳細パネルのテクスチャ>sRGBのチェックが外れていることを確認します。 テクスチャが OpenGL 形式の場合は、テクスチャ>詳細設定>Flip Green Channelにチェックを入れます。 Normalマップの形式については、「5. ノーマルマップについての補足」にて後述します。 最後に、ノードとの間のつながりが、下記画像のようになるように修正します。 シーンビューで確認すると、木のマテリアルが反映されていることを確認できました。 以降は、より細かいマテリアルの調整です。 ここまでの設定だと、 Blender で設定していたときよりも木目が大きく、木目の方向も異なっていることがわかります。 調整するために、テクスチャのサイズ、回転を変えていきます。 テクスチャのサイズを変えるには、Texture Coordinateノードで設定します。 Texture Coordinateノードの UTiling、VTilingの値を変更します。 値を大きくするほど細かく見えるようになります。 今回は、 Blender ではもともとScaleを5と設定していたため、5と設定しました。 テクスチャの回転を変えたい場合は、CustomRotaterノードが便利です。 CustomRotaterノードを下記画像のように配置します。 Rotation Centerは、テクスチャの回転の中心位置を決めることができます。 Rotation Angleは、テクスチャの回転角度を決められます。 このパラメータは範囲が0~1のため、90度であれば0.25とします。 今回は、90度回転させるために、Rotation Angleからパラメータノードを作ります。 Rotation Angleの上で右クリックし、「パラメータへ昇格」をクリックします。 名前を適切なものに変更し、Default Value に0.25と入力しました。 ここまででシーンビューで確認すると、木目が細かくなり、木目の線の方向が90度回転しました。 以上が、 Blender で作成したモデル、マテリアル、アニメーションをUnreal Engine5にインポートする方法の紹介でした。 5. ノーマルマップについて(補足) ノーマルマップ(ノーマル設定用のテクスチャ)について補足します。 描画プログラムはソフトによって異なっており、基本的にはソフトに合わせたノーマルマップの形式を使用する必要があります。 例えば Blender の描画プログラムは OpenGL 、 Unreal Engine は DIrectX です。 同様に、ノーマルマップは OpenGL 形式と DirectX 形式の2種類があります。 OpenGL 形式と DirectX 形式では、凹凸の方向が逆になります。 下記画像だと、左側が OpenGL 形式で、右側が DirectX 形式です。 ダウンロードしたテクスチャの場合、 glや dxという接辞が名前に入っていることが多く、 前者が OpenGL 形式、後者が DirectX 形式と分かります。 今回は Blender から OpenGL 形式のテクスチャを持ってきており、 DirectX を使用している Unreal Engine では凹凸を反転する必要があったため、 ノーマルマップの設定でFlip Green Channelにチェックを入れています。 DirectX 形式であれば、このチェックは不要です。 6. Blender でのアニメーションについて(補足) 最後に、アニメーションについての補足を記載します。 Blender でのアニメーションの作成方法は、3種類あります。 オブジェクトの形状は変えずに、オブジェクト自体の位置や回転、スケールを変更させる オブジェクトの頂点を動かし、その前後変化を登録することで形状を変える ボーンでオブジェクトの形状を変える それぞれについて、下記で詳細を記載します。 オブジェクトの形状は変えずに、オブジェクト自体の位置や回転、スケールを変更させるアニメーション これはドアの開閉の動きや、ボールの上下運動などの表現に使われます。 今回のドアを開くアニメーションもこちらに該当しています。 アニメーションの際に、ドアやボールの形状は変える必要がなく、 ドアであれば回転、ボールなら上下の位置を変えることで動きを表現できるためです。 オブジェクトの頂点を動かし、その前後変化を登録することで形状を変えるアニメーション オブジェクトの形状を変えるとは、オブジェクトの頂点の位置を変えることと同じです。 オブジェクトの頂点の位置を変え、変更後の形状を Blender で設定することで 形状の前後変化をアニメーションとして表現する方法をとります。 これは人間やキャ ラク ターの表情変化など、軽微な変化の表現に使われます。 例えば、笑った顔であれば、目尻を動かしたり口角をあげるだけで、それ以外は変える必要がなく軽微な変化と言えます。 普段の顔を変形前、笑った顔を変形後として設定して、笑った顔への変化を表現できます。 ボーンでオブジェクトの形状を変えるアニメーション こちらも2つ目と同様、オブジェクトの頂点の位置を変えます。 形状を変える際に、オブジェクトに入れ込んだボーン(骨組み)に合わせて、 オブジェクトの頂点が追従する方法をとります。 オブジェクトの頂点を直接動かすのではなく、ボーンという仲介を挟んで動かすところが、2つ目と異なります。 これは人間がジャンプしたり生物が歩いたりなど、人間や生物の身体の動きの表現に使われます。 これらを表現する際、始終身体の形状が変わることになります。 例えば、ジャンプであれば、予備動作で胴体を丸めたりひざやひじを曲げた後、すぐ胴体やひざを伸ばします。 オブジェクトの色々な箇所が動き、かつ同じ箇所が連続的に変化することになります。 このようにオブジェクトが全体的・連続的に動くことを想定して、 扱いやすいように骨組みを用意し、骨組みを動かすことで扱いやすくします。 この記事では、基本的な1つ目の形状変化のないアニメーションを、Unreal Engine5に移行する方法について説明しました。 今後は、2つ目と3つ目のアニメーションのセットアップや移行方法についても学習し、ご紹介できればと思います。 終わりに 今回は、UE5.2.1を使用して、 Blender で作成したモデル、マテリアル、アニメーションをUnreal Engine5にインポートする方法の紹介でした。 内容は難しくありませんが、別ソフト間でのデータのやりとりは想定外に手間どることが多いです。特にマテリアル関連は問題が生じやすい印象です。 スムーズにその後の作業に入るために、流れと起こりがちな問題について整理しておくことが大事だと改めて思いました。 また、今回はFBXファイル形式を扱いましたが、他の形式の選択肢も増えてきています。 USDやglTFなどの形式についても注目していきたいと思いました。 https://www.adobe.com/jp/products/substance3d/discover/3d-files-formats.html 最後までご覧いただき、ありがとうございました。 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! 私たちは一緒に働いてくれる仲間を募集しています! 電通総研中途採用ページ 電通総研新卒採用ページ 執筆: @iida.maya 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
アバター
こんにちは。コミュニケーションIT事業部 ITソリューション部の英です。 普段はWebアプリや スマホ アプリの案件などを担当しています。あと、趣味でAIを勉強しています。 いつもはAI関連の記事を書いていますが、今回は AWS の認証サービスである Amazon Cognito について検証します。 近々案件で使いそうなので、そのための予習です。 Amazon Cognitoには ユーザープール と IDプール の2つのサービスがありますが、今回はユーザープールにフォーカスして記事を書きます。 詳細は公式リファレンスを参照してください。 → ユーザープールとIDプールの違いについて また、各案件でCognitoを採用するべきか否かを判断するために、事前に割り当て(クォータ)を確認しておきましょう。 引き上げが可能なパラメータもあれば、事前相談が必要なものもあります。例えばユーザープール1つにつき、最大ユーザー数は4000万人となっていますが、これ以上使用する場合には AWS アカウントチームと相談する必要があります。 BtoCの大きめの案件であれば、事前にこのあたりの調査や調整をしてケアしておきましょう。 → クォータについて さて、今回はLambdaを使って認証フローを実際に動かしてみましょう! 次回はそのフローで得られた トーク ンを用いて、アクセス制御を実装していきます。 Amazon Cognitoとは AWS が提供するユーザー認証とアクセス管理サービスです。ユーザープールとIDプールを使用して、ユーザー認証を行い、アプリケーションへの安全なアクセスを実現します。 ユーザープールとは アプリケーションユーザーのサインアップ、サインイン、多要素認証(MFA)を管理する機能です。これにより、ユーザー情報を安全に保存し、認証プロセスをシンプルにします。 外部IDプロバイダーの統合 ユーザープールに外部IDプロバイダー( Google 、 Facebook 、 SAML など)を追加することで、ユーザーはこれらのプロバイダーを使用してサインインできます。これにより、簡単に外部IDプロバイダーと統合でき、ユーザー管理が一元化されます。 各種 トーク ンについて トーク ン名 用途 ID トーク ン 認証後にユーザー情報を含む トーク ン。ユーザーの属性情報の取得や、各種 AWS リソースへのアクセス制御に使用する アクセス トーク ン ユーザープール内の情報の参照および更新に使用する リフレッシュ トーク ン 新しい トーク ンを発行するための トーク ン。ID トーク ンやアクセス トーク ンの有効期限が切れた際に再発行を行う。 各 トーク ンの具体的な用途については、公式リファレンスを参照してください。 → IDトークンの使用 → アクセストークンの使用 また、各 トーク ンの有効期限はアプリケーションクライアントの設定から変更できます。 詳細は公式リファレンスを参照してください。 → アプリケーションクライアントの設定 他サービスとの統合 API Gateway Cognitoオーソライザーを使用して、認証されたユーザーのみが API にアクセスできるようにします。 これにより、 API アクセスのセキュリティが強化されます。( 本記事の後編ではこちらの検証を行います ) CloudFront 署名付きURLや Cookie 、Lambda@Edgeと組み合わせて、認証されたユーザーのみがコンテンツにアクセスできるように設定できます。これにより、コンテンツ配信のセキュリティが向上します。 → Authorization@Edge using cookies: Protect your Amazon CloudFront content from being downloaded by unauthenticated users Application Load Balancer ALBはCognitoと統合できます。これにより、Cognitoで認証されたユーザーのみがアプリケーションにアクセスできます。 → Application Load Balancer を使用してユーザーを認証する #ここから本題 今回の認証フローは以下のとおり。 サインアップ : ユーザーがサインアップに必要な情報を入力する (メールアドレス、パスワード、ニックネーム) サインアップをすると、メールで 認証コード が送信される。 メールアドレスの確認 : ユーザーがメールで受け取った 認証コード を入力し、メールアドレスの認証を行う。 サインイン : ユーザーがサインインに必要な情報を入力する (メールアドレス、パスワード) サインインをすると、SMSで 認証コード が送信される。 二要素認証(SMSコードの確認) : ユーザーがSMSで受け取った 認証コード を入力し、電話番号の認証を行う。 アクセス トーク ンの取得 : サインインが成功すると、ユーザーにはアクセス トーク ン、ID トーク ン、リフレッシュ トーク ンが発行される。 これらのステップをLambda関数で実装し、実際に動かしてみましょう。 STEP1:ユーザープールの作成 サインインエクス ペリエ ンスを設定 以下のように設定し、ユーザープールを新規作成します。 「フェデレーテッド アイデンティティ プロバイダー」は後からでも設定が可能なので、いったんスキップします。 サインインオプションは後から変更できないので注意しましょう。今回はメールと電話番号を使用します。 セキュリティ要件を設定 ここではパスワードポリシーや、アカウントの復旧(パスワードを忘れた場合など)について設定できます。 多要素認証のMFAの方法については、「SMSメッセージ」を選択しておきます。 サインアップエクス ペリエ ンスを設定 今回は「自己登録を有効化」しています。 開発中でまだオープンでないアプリで使用する場合は、無効化しておくことが推奨されています。 この場合、 AWS コンソールから直接ユーザープールにユーザーを追加することになります。 後ほどnicknameをメール本文に埋め込みたいため、必須属性として選択しておきましょう。 メッセージ配信を設定 メッセージ配信のプロバイダーとしてSESかCognitoかを選べます。今回はCognitoを選択します。 IAMロールについては既存のポリシーを選択していますが、内容は↓に転記しておきます。 Amazon SNS でSMSメッセージを配信するために必要な権限となります。 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "sns:publish" ], "Resource": [ "*" ] } ] } アプリケーションを統合 ここで生成するクライアントシークレットは後ほどLambdaからCognitoを呼びだすときに使用します。 確認および作成 設定を確認して保存してください。 「email_varified」と「phone_number_varified」はCognitoの認証フローでのみ書き込みが可能となっています。 STEP2:カスタムメッセージの作成 Lambda関数でカスタムメッセージを作成できます。 以下のようにメールオブジェクトを返却するだけのシンプルな関数を作成しておきます。 このためだけに関数を作成するのはちょっと無駄な感じもしますが、デフォルトのメッセージテンプレートは自由度が低いためこの方法を採用しています。メール本文にCognitoの{nickname}を埋め込みます。 その他のtrigger sourcesについては公式リファレンスを参照してください。 → Custom message Lambda trigger sources Cognitoのユーザープールのプロパティ画面で、Lambdaトリガーを作成して先ほどの関数を紐づけます。 STEP3:signup関数を定義する 今回は簡易化のためにクライアントID、クライアントシークレットを 環境変数 に設定していますが、実際の案件では Amazon KMSなどを使用して暗号化してください。(※後述) メールアドレス、電話番号、ニックネームを渡すことでcognitoクライアントの sign _up処理を呼び出しています。 SignUpの ソースコード import boto3 import json import os import hmac import hashlib import base64 cognito_client = boto3.client('cognito-idp') CLIENT_ID = os.environ['CLIENT_ID'] CLIENT_SECRET = os.environ['CLIENT_SECRET'] def get_secret_hash(username): msg = username + CLIENT_ID dig = hmac.new(str(CLIENT_SECRET).encode('utf-8'), msg=str(msg).encode('utf-8'), digestmod=hashlib.sha256).digest() return base64.b64encode(dig).decode() def lambda_handler(event, context): email = event['email'] password = event['password'] phone_number = event['phone_number'] nickname = event['nickname'] secret_hash = get_secret_hash(email) try: response = cognito_client.sign_up( ClientId=CLIENT_ID, SecretHash=secret_hash, Username=email, Password=password, UserAttributes=[ {'Name': 'email', 'Value': email}, {'Name': 'phone_number', 'Value': phone_number}, {'Name': 'nickname', 'Value': nickname} ] ) return { 'statusCode': 200, 'body': json.dumps({'message': 'ユーザー登録が成功しました'}, ensure_ascii=False) } except cognito_client.exceptions.UsernameExistsException: return { 'statusCode': 400, 'body': json.dumps({'error': 'ユーザー名は既に存在します'}, ensure_ascii=False) } except Exception as e: return { 'statusCode': 500, 'body': json.dumps({'error': str(e)}, ensure_ascii=False) } ※入力値検証については各々で実装してください。本題と逸れるため本記事では触れません。 ※パラメータは以下の公式リファレンスを参照してください → sign_up SignUpのテストイベント (メールを受信できるアドレスを設定しましょう) { "email": "(任意)@example.com", "password": "(半角英数記号を使ったパスワード)", "phone_number": "+81(電話番号)", "nickname": "でんつーそーけん" } STEP4:ConfirmSignUp関数を定義する confirmation_codeを受け取って、cognitoクライアントのconfirm_ sign _upを呼び出しています。 confirmation_codeはCognitoから配信されたメール本文に記載されます。(この記事の後半でテストします) ConfirmSignUpの ソースコード import boto3 import json import os import hmac import hashlib import base64 cognito_client = boto3.client('cognito-idp') CLIENT_ID = os.environ['CLIENT_ID'] CLIENT_SECRET = os.environ['CLIENT_SECRET'] def get_secret_hash(username): msg = username + CLIENT_ID dig = hmac.new(str(CLIENT_SECRET).encode('utf-8'), msg=str(msg).encode('utf-8'), digestmod=hashlib.sha256).digest() return base64.b64encode(dig).decode() def lambda_handler(event, context): email = event['email'] confirmation_code = event['confirmation_code'] try: response = cognito_client.confirm_sign_up( ClientId=CLIENT_ID, Username=email, ConfirmationCode=confirmation_code, SecretHash=get_secret_hash(email) ) return { 'statusCode': 200, 'body': json.dumps({'message': 'ユーザーが正常に確認されました'}, ensure_ascii=False) } except cognito_client.exceptions.UserNotFoundException: return { 'statusCode': 400, 'body': json.dumps({'error': 'ユーザーが存在しません'}, ensure_ascii=False) } except cognito_client.exceptions.CodeMismatchException: return { 'statusCode': 400, 'body': json.dumps({'error': '無効な確認コードです'}, ensure_ascii=False) } except Exception as e: return { 'statusCode': 500, 'body': json.dumps({'error': str(e)}, ensure_ascii=False) } ※入力値検証については各々で実装してください。本題と逸れるため本記事では触れません。 ※パラメータは以下の公式リファレンスを参照してください → confirm_sign_up ConfirmSignUpのテストイベント { "email": "(任意)@example.com", "confirmation_code": "(メールで受け取った認証コード)" } STEP5:InitiateAuth関数を定義する emailとpasswordを受け取って、cognitoクライアントのinitiate_authを呼び出しています。 ここで多要素認証のSMSが配信されます。(この記事の後半でテストします) また、ここで生成されたSessionは次のステップ(Challenge)で使用するので控えておきましょう。 USER_ID_FOR_SRPはユーザープール内での一意なIDになります。 InitiateAuthの ソースコード import boto3 import json import os import hmac import hashlib import base64 cognito_client = boto3.client('cognito-idp') CLIENT_ID = os.environ['CLIENT_ID'] CLIENT_SECRET = os.environ['CLIENT_SECRET'] def get_secret_hash(username): msg = username + CLIENT_ID dig = hmac.new(str(CLIENT_SECRET).encode('utf-8'), msg=str(msg).encode('utf-8'), digestmod=hashlib.sha256).digest() return base64.b64encode(dig).decode() def lambda_handler(event, context): email = event['email'] password = event['password'] secret_hash = get_secret_hash(email) try: response = cognito_client.initiate_auth( AuthFlow='USER_PASSWORD_AUTH', AuthParameters={ 'USERNAME': email, 'PASSWORD': password, 'SECRET_HASH': secret_hash }, ClientId=CLIENT_ID ) if 'ChallengeName' in response: # 次の認証ステップが必要な場合 return { 'statusCode': 200, 'body': json.dumps({ 'challenge_name': response['ChallengeName'], 'session': response['Session'], 'challenge_parameters': response['ChallengeParameters'] }, ensure_ascii=False) } return { 'statusCode': 200, 'body': json.dumps({ 'access_token': response['AuthenticationResult']['AccessToken'], 'id_token': response['AuthenticationResult']['IdToken'], 'refresh_token': response['AuthenticationResult']['RefreshToken'] }, ensure_ascii=False) } except cognito_client.exceptions.NotAuthorizedException: return { 'statusCode': 401, 'body': json.dumps({'error': 'ユーザー名またはパスワードが正しくありません'}, ensure_ascii=False) } except Exception as e: return { 'statusCode': 500, 'body': json.dumps({'error': str(e)}, ensure_ascii=False) } ※入力値検証については各々で実装してください。本題と逸れるため本記事では触れません。 ※パラメータは以下の公式リファレンスを参照してください → initiate_auth InitiateAuthのテストイベント { "email": "(任意)@example.com", "password": "(半角英数記号を使ったパスワード)" } STEP6:ConfirmSMS関数を定義する ここが少し複雑なのですが、respond_to_auth_challenge(SMS_MFA)で使用するsessionやuser_id_for_srpはSTEP5のresponseのchallenge_parametersに記載されています。 JSON を解析して値を取り出し、同一セッション内で検証ステップを進めるようにしてください。 ConfirmSMSの ソースコード import boto3 import json import os import hmac import hashlib import base64 import logging cognito_client = boto3.client('cognito-idp') CLIENT_ID = os.environ['CLIENT_ID'] CLIENT_SECRET = os.environ['CLIENT_SECRET'] def get_secret_hash(username): msg = username + CLIENT_ID dig = hmac.new(str(CLIENT_SECRET).encode('utf-8'), msg=str(msg).encode('utf-8'), digestmod=hashlib.sha256).digest() return base64.b64encode(dig).decode() def lambda_handler(event, context): email = event['email'] mfa_code = event['mfa_code'] session = event['session'] user_id_for_srp = event['user_id_for_srp'] secret_hash = get_secret_hash(user_id_for_srp) try: response = cognito_client.respond_to_auth_challenge( ClientId=CLIENT_ID, ChallengeName='SMS_MFA', Session=session, ChallengeResponses={ 'USERNAME': user_id_for_srp, 'SMS_MFA_CODE': mfa_code, 'SECRET_HASH': secret_hash } ) logger.info(f"Response: {response}") return { 'statusCode': 200, 'body': json.dumps({ 'access_token': response['AuthenticationResult']['AccessToken'], 'id_token': response['AuthenticationResult']['IdToken'], 'refresh_token': response['AuthenticationResult']['RefreshToken'] }, ensure_ascii=False) } except cognito_client.exceptions.CodeMismatchException as e: logger.error(f"CodeMismatchException: {e}") return { 'statusCode': 400, 'body': json.dumps({'error': '無効なMFAコードです'}, ensure_ascii=False) } except cognito_client.exceptions.NotAuthorizedException as e: logger.error(f"NotAuthorizedException: {e}") return { 'statusCode': 401, 'body': json.dumps({'error': '認証が失敗しました'}, ensure_ascii=False) } except Exception as e: logger.error(f"Exception: {e}") return { 'statusCode': 500, 'body': json.dumps({'error': str(e)}, ensure_ascii=False) } ※入力値検証については各々で実装してください。本題と逸れるため本記事では触れません。 ※パラメータは以下の公式リファレンスを参照してください → respond_to_auth_challenge ConfirmSMSのテストイベント { "email": "(任意)@example.com", "mfa_code": "(SMSで受け取った認証コード)", "session": "(STEP5で受け取ったセッションID)", "user_id_for_srp": "(STEP5で受け取ったuser_id_for_srp)" } STEP7:検証 これで会員登録から初回ログインまでの関数を書き終わったので、さっそくテストしてみましょう。 まず、 SignUp を呼び出します。 メールが飛んできました。 先ほどLambdaで作成したメールテンプレートが反映されています。 ニックネームもしっかり埋め込まれています。 この状態でユーザープールを確認すると、メールアドレスも電話番号も「 未検証 」のステータスで登録されています。 次に ConfirmSignUp を呼び出します。 メールアドレスが「 検証済み 」のステータスになりました。 次に InitiateAuth を呼び出します。 SMS_MFAというチャレンジが発生し、セッションIDが返ってきています。 手元の スマートフォン にはSMSで認証コードが飛んできます。 飛んでこない場合はLambdaに紐づいているIAMロールを確認してください。(前述の通り) 次に ConfirmSMS を呼び出します。 無事に access _token、id_token、refresh_tokenを取得することができました。 電話番号が「 検証済み 」のステータスになりました。 補足 先ほどスキップしましたが、Lambdaの 環境変数 を暗号化&復号化するには以下のようにしてください。 LambdaはKMSと統合されているので、暗号化は AWS コンソール上から行うことができます。 KMSを触るための権限をLambdaに付与する必要がありますので、各自で設定してください。以下は一例です。 他にも、 AWS Secrets Managerに入れて保管するような方法もあります。 # KMSクライアントの作成 kms_client = boto3.client('kms') class KMSDecryptor: @staticmethod def decrypt_kms_key(ciphertext_blob: str) -> str: try: res = kms_client.decrypt( CiphertextBlob=bytes(base64.b64decode(ciphertext_blob)), EncryptionContext={'LambdaFunctionName': os.environ['AWS_LAMBDA_FUNCTION_NAME']} )['Plaintext'].decode('utf-8') return res except Exception as e: logger.error(f"Decryption error: {e}") raise e # 環境変数を確認し、復号化 try: encrypted_user_pool_id = os.environ['ENCRYPTED_USER_POOL_ID'] encrypted_client_id = os.environ['ENCRYPTED_CLIENT_ID'] encrypted_client_secret = os.environ['ENCRYPTED_CLIENT_SECRET'] USER_POOL_ID = KMSDecryptor.decrypt_kms_key(encrypted_user_pool_id) CLIENT_ID = KMSDecryptor.decrypt_kms_key(encrypted_client_id) CLIENT_SECRET = KMSDecryptor.decrypt_kms_key(encrypted_client_secret) さいごに 今回はとても長い記事になってしまいました。 次回はこの トーク ンを使用して AWS リソースに対するアクセス制御を実装していきます。 これからも AWS ×AIの検証記事をたくさん書いていきます。 ↓ のスターを押していただけると嬉しいです。励みになります。 最後まで読んでいただき、ありがとうございました。 私たちは一緒に働いてくれる仲間を募集しています! コミュニケーションIT事業部 執筆: 英 良治 (@hanabusa.ryoji) 、レビュー: @akutsu.masahiro ( Shodo で執筆されました )
アバター
こんにちは、金融ソリューション事業部の孫です。 記事の前編 では、 Kubernetes 上に必要なDockerイメージを作成しました。 今回は、EKSの構築に取り組み、 Kubernetes ホスティング のUEアプリケーションを配信します。 はじめに 実施手順 開発環境 インフラ構造図 1. EKS環境の構築 ClusterとNodeGroupの作成 ECRアクセス権の追加 2. Kubernetes Device Plugins for DirectXのインストールとテスト 3. AWS ALB Ingress Controllerのインストール ALB Ingress Controller用のIAMの構築 aws-load-balancer-controller インストール 4. UEアプリケーションリリース用のyamlファイルの作成 TURNサービスリリース用yaml PixelStreamingサービス用yamlファイル ALB作成用のyamlファイル 5. プロジェクトのデプロイとデモンストレーション セキュリティグループ編集 UEアプリケーションへのアクセス おわりに 参考文献 はじめに 前編 で述べたように、 Kubernetes で GPU を必要とするサービスの実行が容易なことではなく、特に Windows ノードではさらに難しいです。 この記事では、 Kubernetes Device Plugins for DirectX プラグイン を使用して GPU サポート問題を解決します。 執筆時点で、 Windows ノードで GPU を必要とするサービスを実行する記事はほとんど見つかりませんでした。 この記事が同様の解決策を求めている読者に役立つことを願っています。 このブログを理解するために必要な前提知識は、 前編 の記事を参照してください。 実施手順 EKS環境の構築 Kubernetes Device Plugins for DirectX のインストールとテスト AWS ALB Ingress Controllerのインストール UEアプリケーションリリース用の yaml ファイルの作成 プロジェクトのデプロイとデモンストレーション 開発環境 eksctl: 0.176.0 kubectl: v1.27.3 AWS CLI : version 2 helm: v3.14.4 Helm chart version: 1.7.2 wddm -device-plugin: 0.0.1 AWS ALB Ingress Controller version: v2.7.2 インフラ構造図 以下のEKSサービスを構築します: 1. EKS環境の構築 ClusterとNodeGroupの作成 eksctl コマンドを使用して、EKS クラスタ ーとNodeGroupを迅速に構築します。 この クラスタ ーには、WindowsNodeとLinuxNodeの2つのNodeGroupが含まれています。 ※Tips:EKSサービスの一部 プラグイン 、例えばネットワーク プラグイン ( VPC -CNI)は Linux ノードでのみ動作するため、 Windows ノードのみの クラスタ ーを作成することはできません。 前回の記事 で、 NVIDIA GPU ドライバを含むWindowsNodeに必要なAMIが既に作成されています。 以下の yaml ファイルで設定します: # test_windows_node_eksctl.yamlの内容 --- apiVersion : eksctl.io/v1alpha5 kind : ClusterConfig metadata : name : test-windows-node-cluster region : ap-northeast-1 version : '1.28' nodeGroups : - name : windows-ng instanceType : g4dn.2xlarge ami : ami-0ffxxxxxxx amiFamily : WindowsServer2022FullContainer volumeSize : 120 minSize : 1 maxSize : 1 - name : linux-ng amiFamily : AmazonLinux2 minSize : 1 maxSize : 1 以下のコマンドで クラスタ ーを作成します: $ eksctl create cluster -f test_windows_node_eksctl.yaml 作成後、CloudFormationで作成されたリソースを確認できます。 ECRアクセス権の追加 CloudFormationを開き、作成された クラスタ ーのStackで NodeInstanceRole を見つけます。 クラスタ ーがECRからイメージを引き出せるように、そのRoleページで AmazonEC2ContainerRegistryReadOnly ポリシーをアタッチします。 これにより、ClusterとNodeGroupの作成が完了しました。 2. Kubernetes Device Plugins for DirectX のインストールとテスト Kubernetes Device Plugins for DirectX は、 GPU サービスを実行するための重要な プラグイン です。 次に、この プラグイン をインストールします。 インストールされたことを確認するために、まずWindowsNodeの状態情報を確認します。 割り当て可能なリソースに GPU 関連のリソースはないことがわかります。 次に、 プラグイン のインストールを行います。 以下はインストールに使用する Yaml ファイルの内容です。 リソースタイプは DaemonSet で、これにより追加する各WindowsNodeに自動的にこの プラグイン がインストールされます。 また、 WDDM_DEVICE_PLUGIN_MULTITENANCY パラメータを通じて、各WindowsNodeは GPU リソースの数を設定できます。 # _DirectX-Device-DaemonSet.yamlの内容 apiVersion : apps/v1 kind : DaemonSet metadata : name : device-plugin-wddm spec : selector : matchLabels : app : device-plugin-wddm template : metadata : labels : app : device-plugin-wddm spec : nodeSelector : kubernetes.io/os : 'windows' kubernetes.io/arch : 'amd64' node.kubernetes.io/windows-build : '10.0.20348' securityContext : windowsOptions : hostProcess : true runAsUserName : "NT AUTHORITY \\ SYSTEM" hostNetwork : true containers : - name : device-plugin-wddm image : "index.docker.io/tensorworks/wddm-device-plugin:0.0.1" imagePullPolicy : Always # Configure the WDDM device plugin to allow 4 containers to mount each display device simultaneously env : - name : WDDM_DEVICE_PLUGIN_MULTITENANCY value : "4" 以下のコマンドで プラグイン をインストール: $ kubectl apply -f ./DirectX-Device-DaemonSet.yaml インストール結果の確認: Nodeの状態情報の確認 インストール前と比較して directx.microsoft.com/display: リソースが4つあります GPU が正しく取得できているかの確認 GPU リソースが正常に取得できたかを確認するため、 _device-discovery-wddm.yml.yaml という確認用の yaml ファイルを実行します。 # _device-discovery-wddm.yml.yamlの内容 apiVersion : batch/v1 kind : Job metadata : name : example-device-discovery-wddm spec : template : spec : containers : - name : example-device-discovery-wddm image : "index.docker.io/tensorworks/example-device-discovery:0.0.1" resources : limits : directx.microsoft.com/display : 1 nodeSelector : "kubernetes.io/os" : windows restartPolicy : Never backoffLimit : 0 以下のコマンドで Yaml ファイルを実行: $ kubectl apply -f ./_device-discovery-wddm.yml.yaml これにより、ホストマシンにインストールされている Nvidia ビデオカード 情報を取得できるかを確認します。 Nvidia GPU の状態確認 Nvidia GPU の状態を確認するために、 _nvidia-smi-wddm.yml という yaml ファイルを使用します。 # _nvidia-smi-wddm.ymlの内容 apiVersion : batch/v1 kind : Job metadata : name : example-nvidia-smi spec : template : spec : containers : - name : example-nvidia-smi image : "mcr.microsoft.com/windows/servercore:ltsc2022" command : [ "nvidia-smi.exe" ] resources : limits : directx.microsoft.com/display : 1 nodeSelector : "kubernetes.io/os" : windows restartPolicy : Never backoffLimit : 0 以下のコマンドで yaml ファイルを実行: $ kubectl apply -f ./_nvidia-smi-wddm.yml これにより、 Nvidia GPU の状態を確認し、結果を得られます。 3. AWS ALB Ingress Controllerのインストール PixelStreamingサービスが外部からアクセス可能になるように、 AWS ALB Ingress Controller プラグイン をインストールします。 この プラグイン を使って、アプリケーション ロードバランサー (以下はALB)を作成します。 ALB Ingress Controller用のIAMの構築 # OIDC Create $ eksctl utils associate-iam-oidc-provider --region ap-northeast-1 --cluster test-windows-node-cluster --approve # AWS Load Balancer ControllerにIAMポリシーを作成し、AWS APIへの呼び出しを代行させる。 $ curl -o iam_policy_latest.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json # Create Policy $ aws iam create-policy \ > --policy-name AWSLoadBalancerControllerIAMPolicy \ > --policy-document file://iam_policy_latest.json $ eksctl create iamserviceaccount \ > --cluster=test-windows-node-cluster \ > --namespace=kube-system \ > --name=aws-load-balancer-controller \ > --attach-policy-arn=arn:aws:iam::236960927670:policy/AWSLoadBalancerControllerIAMPolicy \ > --override-existing-serviceaccounts \ > --approve # iamserviceaccountの確認 $ eksctl get iamserviceaccount --cluster test-windows-node-cluster NAMESPACE NAME ROLE ARN kube-system aws-load-balancer-controller arn:aws:iam:: $ kubectl get sa aws-load-balancer-controller -n kube-system NAME SECRETS AGE aws-load-balancer-controller 0 32s aws -load-balancer-controller インストール # 参考:https://github.com/aws/eks-charts/tree/master/stable/aws-load-balancer-controller helm repo add eks https://aws.github.io/eks-charts $ helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=test-windows-node-cluster --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller # インストールされていることを確認。 kubectl -n kube-system get deployment NAME READY UP-TO-DATE AVAILABLE AGE aws-load-balancer-controller 0/2 2 0 10s # Webhook-svcが作成されていることを確認。 $ kubectl -n kube-system get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE aws-load-balancer-webhook-service ClusterIP xx.xxx.xx.x <none> 443/TCP 102m kube-dns ClusterIP xx.xxx.xx.x <none> 53/UDP,53/TCP,9153/TCP 3m9s 4. UEアプリケーションリリース用の yaml ファイルの作成 TURNサービスリリース用 yaml 以下はTURNサービスへの接続用のアカウント名とパスワードを設定する yaml の内容です。 今回はDemoのため、アカウント名とパスワードは平文で処理されています。 ただし、実際の本番環境では、 Kubernetes のSecretリソースタイプを使用してこれらの情報を安全に作成するべきです。 # _turn-demo-deployment.yamlの内容 --- apiVersion : apps/v1 kind : DaemonSet metadata : name : turn-demo labels : app : turn-demo spec : selector : matchLabels : app : turn-demo template : metadata : labels : app : turn-demo spec : restartPolicy : Always terminationGracePeriodSeconds : 30 hostNetwork : true nodeSelector : kubernetes.io/os : linux containers : - name : turn-server image : [ aws accound id ] .dkr.ecr.ap-northeast-1.amazonaws.com/turn-windows-demo:latest imagePullPolicy : Always ports : - name : turn-udp containerPort : 3478 hostPort : 3478 protocol : UDP - name : turn-tcp containerPort : 3478 hostPort : 3478 protocol : TCP env : - name : INTERNAL_IP valueFrom : fieldRef : fieldPath : status.podIP # Firewall rules on the node pool instances must be created for these port ranges - name : TURN_PORT value : "3478" - name : TLS_PORT value : "443" - name : TURN_MIN_PORT value : "49152" - name : TURN_MAX_PORT value : "65535" - name : TURN_REALM value : turnserver - name : TURN_USER value : [ turn username ] - name : TURN_PASS value : [ turn password ] PixelStreamingサービス用 yaml ファイル ネットワーク遅延を低減するため、SignallingサーバーとUnrealEngineのデモゲームを同一のPodに配置しています。 以下のパラメータ設定に注意してください: --peerConnectionOptions 中のSTUN/TURNサービスの IPアドレス は、LinuxNodeのPublicIPであるべきです。 ネットワーク遅延を減少させるために、STUN/TURNサーバーは Linux ノードにスケジュールされます。 今回はPublic IPを手動で記入することを行っていますが、本番環境では手作業を減少させるためにPublic IPアドレス を確定する スクリプト を追加すべきです。 --peerConnectionOptions 中のSTUN/TURNサービスのアカウント名とパスワードは、 _turn-demo-deployment.yaml で設定された値と一致する必要があります。 GPU リソースの割り当てについては、 directx.microsoft.com/display 値を指定することで設定します。 # _demo-deployment.yamlの内容 apiVersion : apps/v1 kind : Deployment metadata : name : ue-demo-deployment labels : app : ue-demo-app spec : replicas : 1 selector : matchLabels : app : ue-demo-app template : metadata : labels : app : ue-demo-app spec : nodeSelector : "kubernetes.io/os" : "windows" containers : - name : signalling-server image : [ aws accound id ] .dkr.ecr.ap-northeast-1.amazonaws.com/signalling-windows-demo:latest ports : - name : http containerPort : 80 - name : stream containerPort : 8888 command : [ "cmd" , "/C" ] args : - "node" - "cirrus.js" - '--peerConnectionOptions={"iceServers":[{"urls":["stun:[linuxNode Public IP]:3478","turn:[linuxNode Public IP]:3478?transport=udp"],"username":"[turn username]","credential":"[turn password]"}]}' - name : ue-project-demo image : [ aws accound id ] .dkr.ecr.ap-northeast-1.amazonaws.com/unreal-engine-windows-demo:latest imagePullPolicy : Always resources : limits : directx.microsoft.com/display : 1 ALB作成用の yaml ファイル httpサービス用のALBを作成します。ユーザーがこのALBの DNS アドレスにアクセスすることで、デモUEアプリケーションにアクセスできます。 # _demo-ingress.yamlの内容 # Service apiVersion : v1 kind : Service metadata : name : demo-web-service labels : app : ue-demo-app spec : type : ClusterIP selector : app : ue-demo-app ports : - name : http protocol : TCP port : 80 targetPort : 80 --- apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : demo-web annotations : alb.ingress.kubernetes.io/load-balancer-name : demo-alb alb.ingress.kubernetes.io/scheme : internet-facing alb.ingress.kubernetes.io/target-type : ip spec : ingressClassName : alb rules : - http : paths : - path : / pathType : Prefix backend : service : name : demo-web-service port : number : 80 5. プロジェクトのデプロイとデモンストレーション 以下のコマンドで yaml ファイルをデプロイします:: $ kubectl apply -f _turn-demo-deployment.yaml $ kubectl apply -f _demo-deployment.yaml $ kubectl apply -f _demo-ingress.yaml ユーザーとPixelStreamingサーバー間のメディアストリーミング転送は、主にTURNサーバーを通じてリレーされます。 そのため、LinuxNodeのセキュリティグループで以下のインバウンドポートを開放する必要があります。 セキュリティグループ編集 以下のポートを開放します: TCP 32355-65535 0.0.0.0/0 UDP 32355-65535 0.0.0.0/0 TCP 3478 0.0.0.0/0 UDP 3478 0.0.0.0/0 UEアプリケーションへのアクセス 以下のコマンドでALBの DNS アドレスを確認します: $ kubectl get ingress ブラウザで ADDRESS 列に表示されたアドレスを入力すると、UEアプリケーションにアクセスできます! おわりに Amazon EKSの Windows ノードでUEアプリケーションの配信に成功しました! 通常、ゲーム開発は Windows システムで行われることが多いです、特に Unreal Engine などの開発エンジンを使用する開発者にとってはそうです。 ゲーム製品とOSの互換性を確保するために、通常は Windows Server環境でゲームをリリースすることが推奨されます。 以前は、 Kubernetes には Windows コンテナ内の GPU アプリケーションのサポートが限られていました。 そのため、ゲーム開発者は従来のEC2 インスタンス に依存してゲームサーバーをデプロイおよび運用する必要があり、運用の柔軟性と拡張性を制限していました。 今回のブログを通じて、 Kubernetes 上での Windows コンテナの GPU サポート問題は解決されたことが確認できました。 これにより、将来的に Windows コンテナが Kubernetes 領域で広く利用される可能性が示されました! 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間をお待ちしております! 電通総研の採用ページ 参考文献 PixelStreamingInfrastructure Offscreen rendering in Windows containers Kubernetes Secrets DirectX-Device-Plugins Containers Quick Start epicgame packages Application load balancing on Amazon EKS Amazon EKS optimized Windows AMIs eksctl Config file Schema 執筆: @chen.sun 、レビュー: @miyazawa.hibiki ( Shodo で執筆されました )
アバター
こんにちは、金融ソリューション事業部の孫です。 前回の記事 で、 Amazon EKS( AWS が提供する Kubernetes サービス、以下EKSと略)用の Windows ノードAMI( Amazon Machine Images、以下AMIと略)の構築方法について紹介しました。 今回は、このAMIを使用して Windows ノードを作成し、UnrealEngine(以下はUE)アプリケーションを配信する方法を説明します。 今回のUE アプリケーションサーバ ーは Windows コンテナで実行され、 PixelStreaming 技術を使用して Webブラウザ からアクセスできます。 従来のアプリケーションのインストールとは異なり、ユーザーはアプリケーションをローカルにインストールする必要がなく、 Webブラウザ を通じていつでもどこでもアクセスできます。 はじめに 実施手順 開発環境 前提準備 1. PixelStreamingアーキテクチャの紹介 2. Signalling ServerのDockerイメージの構築 3. TURN/STUN ServerのDockerイメージの構築 4. デモ用UEアプリケーションのDockerイメージの構築 Pixel Streamingプロジェクトの準備 Dockerfileの作成 Dockerイメージのビルド 5. ローカルテストおよびECRへのアップロード signalling-demoイメージの起動 UnrealEngine-demoイメージの起動 Webブラウザでの確認 Amazon Elastic Container Registryへのイメージのアップロード 作成完了後 ローカルのDockerイメージのアップロード おわりに 参考文献 はじめに Kubernetes の運用において、 GPU リソースを利用する際にはいくつかの大きな課題があります。 これはホストマシンのハードウェアに特別な要求があるだけでなく、関連する設定も非常に複雑です。 Linux コンテナに対しては、 Nvidia 公式が NVIDIA device plugin for Kubernetes を提供しており、開発者がホストマシン上の GPU リソースへ簡単にアクセスできます。 一方、 Windows コンテナに対しては、 Nvidia からはまだ プラグイン のサポートが出ていません。 幸いにも、TensorWorks社が Kubernetes Device Plugins for DirectX を オープンソース 化している為、これを利用することで Windows コンテナにおいてもホストマシン上の GPU リソースへのアクセスが可能になります。 また、今回のデモで使用するUEアプリケーションは、 UnrealEngine の PixelStreaming sample を利用します。 今回のブログ内容は多岐にわたるため、ブログを 前編 と 後編 の2つに分けて紹介します。 前編 では、Dockerイメージの構築に焦点を当てます: Signalling Serverサービスイメージの構築 TURN/STUN Serverサービスイメージの構築 デモ用UEアプリケーションイメージの構築 ローカルテスト 後編 では、EKSの構築と Kubernetes yaml ファイルの作成について説明します: Kubernetes Device Plugins for DirectX のインストールとテスト EKS環境の構築 yaml ファイルの作成 プロジェクトのデプロイとゲームの展示 この記事を読む前に、読者が以下の知識を持っていることを前提とします: AWS の基本操作 EKSの使用経験 コンテナの開発経験 UnrealEngineの基本操作 実施手順 PixelStreaming アーキテクチャ の紹介 Signalling ServerのDockerイメージの構築 TURN/STUN ServerのDockerイメージの構築 デモ用UEアプリケーションのDockerイメージの構築 ローカルテストおよびECRへのアップロード 開発環境 OS: Windows 11 Pro 22H2 x64 RAM:32GB CPU: Intel Core i5 -13600K GPU : GeForce RTX 3080 UnrealEngineのバージョン:5.3 Docker Desktopのバージョン:4.30.0 ※注意:Docker Desktopは Windows コンテナモードに切り替えてください。 前提準備 サービスの構築を始める前に、以下の環境準備が完了していることを前提とします: AWS アカウントの登録 ローカルの AWS CLI 環境の設定が完了 Docker Desktopがインストールされている ※注意:環境設定の詳細ステップについては、関連公式ドキュメントを参照してください。本文では詳しく述べません。 1. PixelStreaming アーキテクチャ の紹介 Pixel Streamingについては、 金融ソリューション事業部の山下さんのブログ にご紹介したとおり、ビデオストリームをユーザーの Webブラウザ に直接送信する技術です。 PixelStreamingの アーキテクチャ は、主に三つの部分から構成されます: UE+PixelStreaming Plugin :ゲームのメディアストリーム出力を提供します。 Signalling and Web Server :クライアントとのWebRTC接続を確立するサービスとユーザーがアクセスするWebページを提供します。 STUN/TURN Server :NATトラバー サルサ ービスを提供します。 ※詳細な技術情報については、 UnrealEngineドキュメント を参照してください。ここでは詳しく述べません。 これから、これら三つの部分のDockerイメージをそれぞれ構築します。 2. Signalling ServerのDockerイメージの構築 Unreal Engine の公式には SignallingサーバーのDockerイメージ が提供されていますが、これは Linux ベースのDockerイメージであり、 Windows サーバー上では動作しません。 そのため、公式の Dockerfile を参考にして、 Windows システムで動作するDockerfileを構築する必要があります。 作成したDockerfileの主な処理手順は以下のとおりです: Node.jsをインストール Signalling Serverのコードをコンテナにコピー Signalling Serverアプリケーションをインストール エントリーポイント(entrypoint)プログラムを設定 ここで注意すべき点: 基本イメージの選択について Dockerイメージのサイズを可能な限り小さくするために、 mcr.microsoft.com/windows/servercore:ltsc2022 をBase Imageとして選択しました Signalling Serverのコードについて Epic公式のリポジトリ からダウンロード可能 フロントエンドについては、事前に SignallingWebServer/platform_scripts/cmd/setup.bat を実行して構築する必要があります 完了すると Public フォルダが生成されます イメージサイズを小さくするために、不要なフォルダ(Docs、platform_scripts)を削除します 最終的なファイル構成は以下のとおりです SignallingWebServer │ .dockerignore │ cirrus.js │ config.json │ Dockerfile │ package-lock.json │ package.json │ Readme.md │ turnserver.conf ├─modules ├─Public └─tps 上記の手順に基づいて作成されたDockerfileは以下のとおりです: # escape=` FROM mcr.microsoft.com/windows/servercore:ltsc2022 as installer SHELL [ " powershell ", " -Command ", " $ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue'; " ] # Install Node.js RUN Invoke-WebRequest -OutFile nodejs.zip -UseBasicParsing " https://nodejs.org/dist/v19.9.0/node-v19.9.0-win-x64.zip "; Expand-Archive nodejs.zip -DestinationPath C:\ ; Rename-Item " C: \\ node-v19.9.0-win-x64 " c: \n odejs FROM mcr.microsoft.com/windows/servercore:ltsc2022 as signalling-server SHELL [ " powershell ", " -Command ", " $ErrorActionPreference = 'Stop';$ProgressPreference='silentlyContinue'; " ] # Set Node Environment variable WORKDIR C:\nodejs COPY --from=installer C:\nodejs\ . RUN SETX PATH C: \n odejs RUN npm config set registry https://registry.npmjs.org/ # copy SignallingWerServer source COPY SignallingWebServer C:\SignallingWebServer # install dependencies COPY SignallingWebServer\package*.json C:\tmp\ RUN cd C: \t mp\ ; npm ci # RUN New-Item -ItemType Directory -Path C:/app RUN Copy-Item -Path C: \t mp \n ode_modules -Destination C:\SignallingWebServer -Recurse RUN Remove-Item -Path C: \t mp \n ode_modules -Recurse WORKDIR C:\SignallingWebServer RUN npm prune --production RUN ls -l . # Expose TCP ports 80 for player WebSocket connections and web server HTTPaccess EXPOSE 80 # Expose TCP port 8888 for streamer WebSocket connections EXPOSE 8888 EXPOSE 8888/udp # Expose TCP port 19302 for connections to Google's stun server EXPOSE 19302 # entrypoint ENTRYPOINT [ " node ", " cirrus.js " ] 次に、イメージのビルドを実行します: ## Build $ cd D:\SignallingWebServer $ docker build -t signalling-demo . ## 確認 $ docker images signalling-demo REPOSITORY TAG IMAGE ID CREATED SIZE signalling-demo latest xxxxxxxxxxx 2 days ago 4.68GB 3. TURN/STUN ServerのDockerイメージの構築 Epic公式と同様に、coturnを使用してTURN/STUNサービスを提供します。 Dockerfileの処理手順は以下のとおりです: 非常にシンプルで、coturnを直接インストールするだけです。 FROM alpine:3.17 as turn-server # add dependencies RUN apk update && \ apk add -u --no-cache bind-tools coturn # set entrypoint script COPY entrypoint.sh / RUN chmod +x /entrypoint.sh CMD [ " /entrypoint.sh " ] エント リーファ イル(entrypoint.sh)の内容は次の通りです: エント リーファ イルには、coturnサービスを開始するために必要なパラメータが定義されています。 #!/bin/sh export INTERNAL_IP="${INTERNAL_IP:-$(ip a | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -n 1)}" export EXTERNAL_IP="${EXTERNAL_IP:-$(dig +short myip.opendns.com @resolver1.opendns.com)}" echo "---------" echo "INTERNAL_IP : $INTERNAL_IP" echo "EXTERNAL_IP : $EXTERNAL_IP" echo "TURN_REALM : $TURN_REALM" echo "---------" turnadmin -a \ -u ${TURN_USER:-turn} \ -p ${TURN_PASS:-change} \ -r ${TURN_REALM:-example.com} # Start coturn server with options # https://github.com/coturn/coturn/blob/master/README.turnserver # https://github.com/coturn/coturn/wiki/turnserver turnserver -n --no-cli \ --verbose \ --listening-port=${TURN_PORT:-3478} \ --relay-ip="${INTERNAL_IP}" \ --listening-ip="${INTERNAL_IP}" \ --external-ip="${EXTERNAL_IP?missing external ip}/${INTERNAL_IP}" \ --server-name=${TURN_REALM:-example.com} \ --fingerprint \ --lt-cred-mech \ --realm=${TURN_REALM:-example.com} \ --user="${TURN_USER:-pixel}:${TURN_PASS:-changeme}" \ --rest-api-separator=":" \ --channel-lifetime=${TURN_CHANNEL_LIFETIME:-"-1"} \ --min-port=${TURN_MIN_PORT:-49152} \ --max-port=${TURN_MAX_PORT:-65535} ${EXTRA_ARGS} \ --no-tlsv1 \ --no-tlsv1_1 \ --no-tlsv1_2 \ --secure-stun \ --tls-listening-port=${TLS_PORT:-5349} \ --cert=${CERT_FILEPATH:-/etc/turn/tls.crt} \ --pkey=${PKEY_FILEPATH:-/etc/turn/tls.key} 注意すべき点は、ネットワーク遅延の観点から Linux サーバーが Windows サーバーよりも優れているため、 Linux システムを使用してTURN/STUNサービスを提供することです。 コンパイル 時にはDocker Desktopの実行モードを一時的に Linux コンテナに切り替える必要があります。 切り替え後、イメージのビルドを行います。 ## Build $ cd D:\TURN $ docker build -t turn-demo . ## 確認 $ docker images turn-demo REPOSITORY TAG IMAGE ID CREATED SIZE turn-demo latest xxxxxxxxxxx 2 days ago 31MB 4. デモ用UEアプリケーションのDockerイメージの構築 Unreal Engine のDockerイメージに関しては、Epic公式が提供するRuntimeイメージ runtime-windows-ltsc2022 があります。 しかし、 Unreal Engine のアプリケーションをEpicが提供した Windows Runtimeコンテナ上で実行すると、以下のエラーが発生します。 LogWindows: Error: appError called: Assertion failed: (((HRESULT)(Hr)) >= 0) [File:D:\build\++UE5\Sync\Engine\Plugins\Runtime\WindowsMoviePlayer\Source\WindowsMoviePlayer\Private\WindowsMoviePlayer.cpp] [Line: 45] LogWindows: Error: Failed to create dialog. The operation completed successfully. Error: 0x0 (0) LogWindows: Error: === Critical error: === LogWindows: Error: LogWindows: Error: Assertion failed: (((HRESULT)(Hr)) >= 0) [File:D:\build\++UE5\Sync\Engine\Plugins\Runtime\WindowsMoviePlayer\Source\WindowsMoviePlayer\Private\WindowsMoviePlayer.cpp] [Line: 45] LogWindows: Error: LogWindows: Error: どうやら、イメージの構築中にいくつかの ミドルウェア が不足しているようです。 一方、 mcr.microsoft.com/windows/server:ltsc2022 ベースイメージを使用すると問題は発生しません。 そのため、公式が使用する windows/servercore イメージの代わりに windows/server ベースイメージを使用して再 コンパイル します。 Pixel Streamingプロジェクトの準備 イメージを構築する前に、 Unreal Engine からデモアプリケーションを作成し、そしてパッケージ化にします。 まず、 Epic Games Launcher を開き、 Unreal Engine ⇒ Sample に移動します。 次に、画面を下にスクロールして Pixel Streaming Demo プロジェクトを見つけます。 クリックして、 Create Project ボタンを押して Unreal Engine 5.3プロジェクトを作成します。 プロジェクトが作成されたら、プロジェクトを起動します。 これはPixel Streamingのサンプルなので、Pixel Streamingに関する設定は事前に完了しています。 そして、プロジェクトをパッケージ化します。ターゲットプラットフォームは Windows です。 パッケージ化が完了した後のファイル構造は次の通りです: Dockerfileの作成 次に、Dockerfileの作成を開始します。 Epic公式の Dockerfile を参考にします。 基本的な処理手順は次の通りです: DirectX runtimeのインストール DirectX shader compilerのインストール Visual C++ runtimeのインストール entrypointファイルをコンテナにコピー パッケージ化されたPixel Streamingプロジェクトをコンテナにコピー Dockerfileの全内容は以下のとおりです: # escape=` FROM mcr.microsoft.com/windows/server:ltsc2022 # Retrieve the DirectX runtime files required by the Unreal Engine, since even the full Windows base image does not include them RUN curl --progress-bar -L " https://download.microsoft.com/download/8/4/A/84A35BF1-DAFE-4AE8-82AF-AD2AE20B6B14/directx_Jun2010_redist.exe " --output %TEMP%\directx_redist.exe && ` start /wait %TEMP%\directx_redist.exe /Q /T:%TEMP%\DirectX && ` expand %TEMP%\DirectX\APR2007_xinput_x64.cab -F:xinput1_3.dll C:\Windows\System32\ && ` expand %TEMP%\DirectX\Feb2010_X3DAudio_x64.cab -F:X3DAudio1_7.dll C:\Windows\System32\ && ` expand %TEMP%\DirectX\Jun2010_D3DCompiler_43_x64.cab -F:D3DCompiler_43.dll C:\Windows\System32\ && ` expand %TEMP%\DirectX\Jun2010_XAudio_x64.cab -F:XAudio2_7.dll C:\Windows\System32\ && ` expand %TEMP%\DirectX\Jun2010_XAudio_x64.cab -F:XAPOFX1_5.dll C:\Windows\System32\ # Retrieve the DirectX shader compiler files needed for DirectX Raytracing (DXR) RUN curl --progress-bar -L " https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.6.2104/dxc_2021_04-20.zip " --output %TEMP%\dxc.zip && ` powershell -Command "Expand-Archive -Path \"$env:TEMP\dxc.zip\" -DestinationPath $env:TEMP" && ` xcopy /y %TEMP%\bin\x64\dxcompiler.dll C:\Windows\System32\ && ` xcopy /y %TEMP%\bin\x64\dxil.dll C:\Windows\System32\ # Install the Visual C++ runtime files using Chocolatey RUN powershell -NoProfile -ExecutionPolicy Bypass -Command " [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) " RUN choco install -y vcredist-all COPY entrypoint.cmd C:\entrypoint.cmd COPY enable-graphics-apis.ps1 C:\enable-graphics-apis.ps1 ################## # Project Settings COPY UnrealEngine-Demo C:\UnrealEngine-Demo # Set our Unreal Engine application as the container's entrypoint, wrapped in the helper script ENTRYPOINT [ " cmd.exe ", " /S ", " /C ", " C: \\ entrypoint.cmd ", " C: \\ UnrealEngine-Demo \\ PixelStreaming_53 \\ Binaries \\ Win64 \\ PixelStreaming_53.exe ", " -stdout ", " -FullStdOutLogOutput ", " -AudioMixer ", " -RenderOffscreen ", " -unattended ", " -PixelStreamingURL=ws://127.0.0.1:8888 " ] 以下の点に注意してください: System DLLのコピーについて Windows Serverベースイメージに変更したため、必要なSystem DLLはすでに含まれているのでコピーは不要です entrypoint.cmdファイルについて DirectX 以外のグラフィックス API を提供することが目的です 参考ドキュメント: Enabling vendor-specific graphics APIs in Windows containers Dockerイメージのビルド 以下のコマンドを実行してイメージをビルドします: ## Build $ cd D:\UnrealEngine-runtime $ docker build -t UnrealEngine-demo . ## 確認 $ docker images unreal-engine-demo REPOSITORY TAG IMAGE ID CREATED SIZE unreal-engine-demo latest xxxxxxxxxxx 2 days ago 11.8GB 5. ローカルテストおよびECRへのアップロード 次に、UnrealEngine-demoとsignalling-demoの両方のイメージが正常に動作するかをローカルでテストします。 Docker では Linux コンテナと Windows コンテナを同時に起動できないため、 turn-demo イメージのローカルテストは行いません。 signalling-demoイメージの起動 以下のコマンドを実行してコンテナを作成します: $ docker run --rm -p 8888:8888 -p 8888:8888/udp -p 8080:80 signalling-demo UnrealEngine-demoイメージの起動 Windows OS上で GPU リソースにアクセスするには、以下の起動パラメータを追加する必要があります: --isolation process --device class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 ※参考ドキュメント: GPU acceleration in Windows containers したがって、 GPU リソースが必要なコンテナの起動コマンドは以下のとおりです: $ docker run --rm -ti --isolation process --device class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 --entrypoint "cmd.exe" unreal-engine-demo /S /C C:\\entrypoint.cmd C:\\UnrealEngine-Demo\\PixelStreaming_53\\Binaries\\Win64\\PixelStreaming_53.exe -stdout -FullStdOutLogOutput -AudioMixer -RenderOffscreen -unattended -PixelStreamingURL=ws://[Local Public IP]:8888 Signallingサーバーに正常に接続されると、Signallingサーバーに以下のログが出力されます: 08:19:52.154 Streamer connected: ::ffff:[Local Public IP] 08:19:52.155 ::ffff:[Local Public IP] <- {"type":"identify"} 08:19:52.652 ::ffff:[Local Public IP] -> {"type":"endpointId","id":"DefaultStreamer"} 08:19:52.652 Registered new streamer: DefaultStreamer 08:20:52.646 DefaultStreamer -> {"type":"ping","time":1715761252} Webブラウザ での確認 ブラウザを開き、 127.0.0.1:8080 と入力すると、以下のUEアプリケーション画面が表示されます: Signallingサーバーのログ出力でも、ユーザー接続のログが表示されます: これで、イメージが正常に動作することを確認できました。 Amazon Elastic Container Registryへのイメージのアップロード 次に、ローカルのイメージを Amazon Elastic Container Registry(以下はECR)にアップロードします。 これにより、これから構築するEKSで使用できます。 AWS Console ⇒ Amazon ECR ⇒ Private registry ⇒ Repositories を開きます。 「 リポジトリ を作成」ボタンをクリックし、以下の3つのイメージ リポジトリ を順番に作成します: signalling- windows -demo unreal -engine- windows -demo turn- windows -demo 作成完了後 ローカルのDockerイメージのアップロード ## Amazon ECR login $ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 236960927670.dkr.ecr.ap-northeast-1.amazonaws.com ## Set tags $ docker tag signalling-demo:latest 236960927670.dkr.ecr.ap-northeast-1.amazonaws.com/signalling-windows-demo:latest $ docker tag unreal-engine-demo:latest 236960927670.dkr.ecr.ap-northeast-1.amazonaws.com/unreal-engine-windows-demo:latest $ docker tag turn-demo:latest 236960927670.dkr.ecr.ap-northeast-1.amazonaws.com/turn-windows-demo:latest ## Upload Docker images $ docker push signalling-windows-demo:latest 236960927670.dkr.ecr.ap-northeast-1.amazonaws.com/signalling-windows-demo:latest $ docker push unreal-engine-windows-demo:latest 236960927670.dkr.ecr.ap-northeast-1.amazonaws.com/unreal-engine-windows-demo:latest $ docker push turn-windows-demo:latest 236960927670.dkr.ecr.ap-northeast-1.amazonaws.com/turn-windows-demo:latest これで、サービスに必要なDokcerイメージの作成タスクが完了しました。 おわりに 今回の 前編 では、Pixel Streaming アーキテクチャ に必要なサービスのDockerイメージを構築しました。 次回の 後編 では、EKSの構築に焦点を当てて、 Kubernetes に基づくUEアプリケーションを配信する手順を紹介します。 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間をお待ちしております! 電通総研の採用ページ 参考文献 PixelStreaming Pixel Streaming use cases PixelStreaming Hosting and Networking Guide NVIDIA device plugin for Kubernetes UnrealEngine Enabling vendor-specific graphics APIs in Windows containers GPU acceleration in Windows containers Turn on GPU access with Docker Compose Development images vs. runtime images 執筆: @chen.sun 、レビュー: @iwasaka.emari ( Shodo で執筆されました )
アバター
こんにちは、金融ソリューション事業部の孫です。 前編 では、 Unreal Editorを含む Windows コンテナイメージの構築を完了しました。 本記事では、 前編 で構築したコンテナイメージを利用する Amazon EKS(以下EKS)の Windows Node AMIを作成します。 EKSのドキュメント をよると、 AWS はユーザー向けに最適化された EKS optimized WindowsAMI を提供していることがわかりました。 このEKS optimized WindowsAMIにはEKSでの動作可能な ミドルウェア がインストールされていますが、 前編 で構築したコンテナイメージをサポートするには不足している部分がまだ多く存在します。 そのため、この記事では Unreal Editor用のカスタム Windows AMIを構築します。 はじめに Packerについて Packerの特徴と機能: 使用手順 実施手順 1. Packerツールのインストール 2. Packerのテンプレートファイルの作成 Packerテンプレートファイル 3. Windowsイメージのビルドとテスト 終わりに 参考文献 はじめに 本記事では、以下を前提知識として扱います。 AWS の基本操作 EKSの使用経験 コンテナ開発経験 PowerShell スクリプト の作成経験 今回では、HashiCorp社が提供する Packer ツールを使用してAMIを作成します。 また、 AWS が提供するEC2 Image Builderを使用してAMIを作成することも可能ですが、以下の理由でPackerを選定しました。 イメージ作成プロセスを完全に制御したい 今後、既存のCI/CDプロセスに統合する予定がある Packerについて Packerは、HashiCorpによって開発された オープンソース のツールで、異なるプラットフォーム向けにサーバーイメージを自動で作成するためのものです。 開発者やシステム管理者がテンプレートファイルを通じてイメージを定義し、 AWS 、Azure、 Google Cloud Platformなど複数の クラウド サービス向けのイメージを作成できます。 Packerの特徴と機能: イメージの自動作成 : PackerはOSのイメージを自動作成し、手動でのイメージ作成や設定の時間と複雑さを軽減します。 マルチプラットフォーム に対応 :Packerは複数の クラウド プラットフォームと仮想化技術をサポートしており、異なる環境間での一貫性を促進します。 カスタマイズと拡張性 : Packerの設定はシンプルなテンプレートファイルを使用して行われ、ユーザーは具体的なニーズに応じてイメージをカスタマイズできます。さらに、Packerは多くのビルダー、事前に設定されたテンプレート、 プラグイン をサポートしており、機能を拡張できます。 DevOpsツールチェーンとの統合 : Packerは、 Vagrant やTerraformなどの他のDevOpsツールと容易に統合でき、CI/CDのプロセスをサポートします。 使用手順 テンプレートの作成 :ユーザーはまず、イメージの作成方法を定義したテンプレートファイルを作成する必要があります。 ビルドの実行 :Packerの コマンドライン ツールを使用してビルドを実行します。 具体的な作成手順は、次のセクションで詳しく説明します。 実施手順 Packerツールのインストール Packerのテンプレートファイルの作成 Windows イメージのビルドとテストの実行 使用する環境およびソフトウェアのバージョンは以下のとおりです: OS: Windows 11 Pro 22H2 x64 RAM: 32GB CPU: i5-13600K Packer: v1.10.0 eksctl: 0.176.0 AWS CLI : version 2 1. Packerツールのインストール PackerのインストールはTerraformと同様に非常に簡単です。 exeファイルをダウンロードし、 環境変数 に追加するだけでインストールが完了します。 # PackerのダウンロードURL https://developer.hashicorp.com/packer/install # 環境変数の設定 `Control Panel` ⇒ `System` ⇒ `System Settings` ⇒ `Environment Variables`を順に開き、 `System variables`のボックス内で`PATH`変数をダブルクリックして編集画面を開きます。 変数値の最後に実行ファイルの所在Pathを追加します。例:C:\path また、 Chocolatey を使用して Windows ソフトウェアを管理しているユーザーは、以下のコマンドを実行するだけでインストールが完了します。 $ choco install packer ※他のシステムのユーザーは、Packerの インストールガイド を参考にインストールしてください。 インストール完了後、Packerが正しくインストールされているか確認します: # 以下のコマンドを実行し、正しくバージョン情報が表示されればインストール成功 $ packer version Packer v1.10.0 2. Packerのテンプレートファイルの作成 構築する Windows AMIに含める必要があるソフトウェアは以下のとおりです。 今回は、 Windows ノード上で Unreal Editorを含むコンテナイメージを実行する為、 GPU 関連のソフトウェアを含めています。 NVIDIA GPU drivers Vulkan runtime library DirectX shader compiler ※本記事では取り扱いませんが、EKSを活用してコンテナを運用する手順については unrealcontainers を参照してください。 また、 Unreal Editorコンテナの起動速度を向上させるために、 Windows AMI内に事前にキャッシュしておく必要もあります。 次に、テンプレートファイルの作成に取り掛かります。 Packerテンプレートファイル Packerテンプレートのフォーマットと文法はTerraformと同様であり、Terraformの使用経験があるユーザーはすぐに使いこなせるでしょう。 Terraformの使用経験がないユーザーでも心配ありません。テンプレートの定義内容は非常に直感的で、何をしようとしているのかが理解しやすいです。 では、テンプレートファイル(eks-worker-node-ami.pkr.hcl)の作成を開始しましょう。 まず、必要な プラグイン およびそのバージョン情報を定義します。 #ターゲットのクラウドサービスはawsであるため packer { required_plugins { amazon = { version = ">= 1.0.9" source = "github.com/hashicorp/amazon" } } } AMI作成のEC2を定義する この設定は、PackerがEC2 インスタンス を構築し、そこからAMIを作成するために使用するパラメータと設定を指定します。 利用されるPackerのSource名は amazon-ebs です。 主なパラメータには、AMI名、ソースAMI、 インスタンス タイプ、リージョンなどがあります。 ここでは、 AWS が提供する EKS optimized WindowsAMI をベースイメージとして使用し、その上に必要なシステム環境を構築します。 EKS optimized WindowsAMI には、EKSに接続するために必要なOS環境が既に構築されているため、この基盤を使用することでプロセスを簡素化できます。 source "amazon-ebs" "eks-worker-node" { ami_name = "eks-windows-worker-node" # AMI name instance_type = "g4dn.2xlarge" # instancetype region = "ap-northeast-1" # region vpc_id = "vpc-xxxxxxxxxxxxxxxxx" # VPC id subnet_id = "subnet-xxxxxxxxxxxxxx" # Subnet id # base AMI source_ami_filter { filters = { name = "Windows_Server-2022-English-Full-EKS_Optimized-1.28-*" root-device-type = "ebs" virtualization-type = "hvm" } most_recent = true owners = [ "amazon" ] } # Expand the boot disk to 120GB launch_block_device_mappings { device_name = "/dev/sda1" volume_size = 120 volume_type = "gp3" delete_on_termination = true } # Allow S3 access for the VM temporary_iam_instance_profile_policy_document { Version = "2012-10-17" Statement { Action = [ "s3:Get*" , "s3:List*" , "s3:Describe*" , "s3-object-lambda:Get*" , "s3-object-lambda:List*" ] Effect = "Allow" Resource = [ "*" ] } } # Use our startup script to enable SSH access user_data_file = "$ { path.root } /scripts/startup.ps1" # Use SSH for running commands in the VM communicator = "ssh" ssh_username = "Administrator" ssh_timeout = "30m" # Don't automatically stop the instance, since sysprep will perform the shutdown disable_stop_instance = true } ビルドプロセスを作成する ここで、AMI名、参照するソース名(上記で構築したEC2 インスタンス )を設定し、最後に Powershell スクリプト を実行して必要な環境を構築します。 ビルドが完了したAMIは、 AWS コンソールで確認できます。 build { name = "eks-worker-windows-node" sources = [ "source.amazon-ebs.eks-worker-node" ] # Run our setup script provisioner "powershell" { script = "$ { path.root } /scripts/setup_base_eks_optimized_ami.ps1" } # Perform cleanup and shut down the VM provisioner "powershell" { script = "$ { path.root } /scripts/cleanup.ps1" valid_exit_codes = [ 0 , 2300218 ] } } ここまでで、AMI作成のテンプレートファイルの作成が完了しました。 次に、環境を構築するための PowerShell スクリプト を作成します。 ① スタートアップ スクリプト (startup.ps1) この スクリプト の目的は、EC2の SSH を構成し、後続のEC2へのログインおよび構築 スクリプト の実行に使用することです。 EC2のmetaServiceにはIMDSv1とIMDSv2の2つのバージョンがあります。 ご自身のEC2設定に応じて、対応するバージョンのコードを選択してください。 # startup.ps1 <powershell> # Install the OpenSSH server and set the sshd service to start automatically at system startup Add-WindowsCapability -Online -Name OpenSSH.Server~~~~ 0.0.1.0 Set-Service -Name sshd -StartupType 'Automatic' # Create the OpenSSH configuration directory if it doesn't already exist $sshDir = 'C:\ProgramData\ssh' if (( Test-Path -Path $sshDir ) -eq $false ) { New-Item -Path $sshDir -ItemType Directory -Force | Out-Null } # Retrieve the SHH public key from the EC2 metadata service $authorisedKeys = " $sshDir \administrators_authorized_keys" # IMDSv2 #$response = Invoke-WebRequest -Uri "http://169.254.169.254/latest/api/token" -Method PUT -Headers @{"X-aws-ec2-metadata-token-ttl-seconds"="21600"} #$token = $response.Content #$metadata = Invoke-WebRequest -Uri "http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key" -Headers @{"X-aws-ec2-metadata-token"=$token} #$metadata.Content | Out-File -FilePath "$authorisedKeys" # Retrieve the SHH public key from the EC2 metadata service # IMDSv1 curl.exe 'http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key' -o " $authorisedKeys " # Set the required ACLs for the authorised keys file icacls.exe " $authorisedKeys " / inheritance:r / grant "Administrators:F" / grant "SYSTEM:F" # Install the Windows feature for containers, which will require a reboot Install-WindowsFeature -Name Containers -IncludeAllSubFeature # Restart the VM Restart-Computer < / powershell> ② 構築 スクリプト (setup.ps1) まず、使用するバージョン情報およびインストールに使用する一時フォルダーを設定します。 # setup.ps1 # Constants $Containered_Ver = "1.7.11" $eks_optimized_ami_windows_Ver = "1.28.0" $ContainerdPath = "$env:ProgramFiles\containerd" $TempRoot = "C:\TempEKSArtifactDir" $TempPath = "$TempRoot\EKS-Artifacts" # Create each of our directories Write-Host "Create each of our directories" foreach ($dir in @($TempRoot, $TempPath)) { New-Item -Path $dir -ItemType Directory -Force | Out-Null } バージョン選定に関して注意すべき2点は次の通りです: Windows Serverのコンテナランタイムの選定については、 Microsoft公式がcontainerdの使用を推奨しています 。Dockerは現在サポートされておらず、containerdのみが GPU サポートなどの Windows Containerの高度な機能をサポートしています。 Kubernetes で Windows Containerの GPU サポート プラグイン を使用するためには、containerdのバージョンが1.7.0以上である必要があります。 参考: https://github.com/TensorWorks/DirectX-Device-Plugins?tab=readme-ov-file EKS optimized WindowsAMI にキャッシュイメージを追加するためには、 EKS optimized WindowsAMI の構築 Image Builder Component を使用する必要があります。具体的なバージョンは Kubernetes のバージョンに依存しますが、今回は1.28.0バージョンを使用します。 次に、必要なソフトウェアを順にインストールします。 NVIDIA GPU drivers # Install the NVIDIA GPU drivers Write-Host "Install the NVIDIA GPU drivers" $driverBucket = 'ec2-windows-nvidia-drivers' $driver = Get-S3Object -BucketName $driverBucket -KeyPrefix 'latest' -Region 'us-east-1' | Where-Object {$_.Key.Contains('server2022')} Copy-S3Object -BucketName $driverBucket -Key $driver.Key -LocalFile "$TempRoot\driver.exe" -Region 'us-east-1' Start-Process -FilePath "$TempRoot\driver.exe" -ArgumentList @('-s', '-noreboot') -NoNewWindow -Wait Vulkan runtime library # install the Vulkan runtime library Invoke-WebRequest -Uri "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-runtime-components.zip?u=" -OutFile "$env:TEMP\vulkan-runtime-components.zip" Expand-Archive -Path "$env:TEMP\vulkan-runtime-components.zip" -DestinationPath "$env:TEMP" Copy-Item -Path "*\x64\vulkan-1.dll" -Destination C:\Windows\System32\ DirectX shader compiler # Retrieve the DirectX shader compiler files needed for DirectX Raytracing (DXR) Invoke-WebRequest -Uri "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.6.2104/dxc_2021_04-20.zip" -OutFile "$env:TEMP\dxc.zip" Expand-Archive -Path "$env:TEMP\dxc.zip" -DestinationPath "$env:TEMP" Copy-Item -Path "$env:TEMP\bin\x64\dxcompiler.dll" C:\Windows\System32\ Copy-Item -Path "$env:TEMP\bin\x64\dxil.dll" C:\Windows\System32\ # Clean up any temp files generated during prerequisite installation Remove-Item -LiteralPath "$env:TEMP" -Recurse -Force New-Item -Type directory -Path "$env:TEMP" そして、 EKS optimized WindowsAMI に含まれているContainerdのバージョンを更新します(1.6.18⇒1.7.1) # TEMPORARY UNTIL EKS ADDS SUPPORT FOR CONTAINERD v1.7.11: # Download and extract the containerd 1.711 release build Write-Host "Download and extract the containerd 1.7.11 release build" $webClient = New-Object System.Net.WebClient $containerdTarball = " $TempPath \containerd- $Containered_Ver .tar.gz" $containerdFiles = " $TempPath \containerd- $Containered_Ver " $webClient .DownloadFile( "https://github.com/containerd/containerd/releases/download/v $Containered_Ver /containerd- $Containered_Ver -windows-amd64.tar.gz" , $containerdTarball ) New-Item -Path " $containerdFiles " -ItemType Directory -Force | Out-Null tar.exe -xvzf " $containerdTarball " -C " $containerdFiles " # Stop containerd service Stop-Service -Name "containerd" -Force # Upgrade container version from 1.6.18 to 1.7.11 Write-Host "Upgrade container version from 1.6.18 to 1.7.11" Move-Item -Path " $containerdFiles \bin\containerd.exe" -Destination " $ContainerdPath \containerd.exe" -Force Move-Item -Path " $containerdFiles \bin\containerd-shim-runhcs-v1.exe" -Destination " $ContainerdPath \containerd-shim-runhcs-v1.exe" -Force Move-Item -Path " $containerdFiles \bin\ctr.exe" -Destination " $ContainerdPath \ctr.exe" -Force # restart containerd service Start-Service -Name containerd # Clean up the containerd intermediate files Write-Host "Clean up the containerd intermediate files" Remove-Item -Path " $containerdFiles " -Recurse -Force Remove-Item -Path " $containerdTarball " -Force 最後に、 EKS optimized WindowsAMI のImage Builder コンポーネント を使用して、前編で作成したコンテナイメージをキャッシュイメージとして追加します。 # Download the EKS artifacts archive Write-Host "Download the EKS artifacts archive" $webClient .DownloadFile( "https://ec2imagebuilder-managed-resources-us-east-1-prod.s3.amazonaws.com/components/eks-optimized-ami-windows/ $eks_optimized_ami_windows_Ver /EKS-Artifacts.zip" , "C:\EKS-Artifacts.zip" ) # Extract the EKS artifacts archive Write-Host "Extract the EKS artifacts archive" Expand-Archive -Path "C:\EKS-Artifacts.zip" -DestinationPath $TempRoot Remove-Item -Path "C:\EKS-Artifacts.zip" -Force # Add the unreal-engine-dev-windows-5.1:latest to the list of images to pre-pull Write-Host "Add the unreal-engine-dev-windows-5.1:latest image" $baseLayersFile = " $TempPath \eks.baselayers.config" $baseLayers = Get-Content -Path $baseLayersFile -Raw | ConvertFrom-Json $baseLayers .ue += "unreal-engine-dev-windows-5.1:latest" $patchedJson = ConvertTo-Json -Depth 100 -InputObject $baseLayers Set-Content -Path $baseLayersFile -Value $patchedJson -NoNewline # Get added new BaseLayers Write-Host "Perform EKS worker node setup" Push-Location $TempPath .\ Get-EKSBaseLayers .ps1 -ConfigFile eks.baselayers.config -ContainerRuntime containerd Pop-Location # Perform cleanup Write-Host "Perform cleanup" Remove-Item -Path " $TempRoot " -Recurse -Force ③ クリーン スクリプト (cleanup.ps1) この スクリプト の目的は、スタートアップ スクリプト (startup.ps1)で設定した SSH 環境を削除し、sysprep(システム準備)を開始することです。 # cleanup.ps1 # Perform cleanup Set-Service -Name sshd -StartupType 'Manual' Remove-Item -Path 'C:\ProgramData\ssh\administrators_authorized_keys' -Force # Remove the file for this script, since Packer won't have a chance to perform its own cleanup Remove-Item -Path $PSCommandPath -Force # Perform sysprep and shut down the VM # Need delete edge account for sysprep & " $Env:ProgramFiles \Amazon\EC2Launch\EC2Launch.exe" sysprep --shutdown = true 3. Windows イメージのビルドとテスト テンプレートファイルに対してPackerコマンドを実行し、 Windows AMIのビルドを開始します。 ビルドコマンド $ packer build .\eks-worker-node-ami.pkr.hcl ...出力ログ... ==> Wait completed after 52 minutes 42 seconds ==> Builds finished. ビルド完了の確認 AWS Console ⇒ EC2 ⇒ イメージ ⇒ AMI で作成されたAMIを確認できます。 Windows AMIのテスト AMIをテストするために、eksctlを使用してEKSを作成します。 以下の yaml ファイルでは、2つのnodegroupを含む Kubernetes クラスタ ーを定義しています。 # test_windows_node_eksctl.yaml apiVersion : eksctl.io/v1alpha5 kind : ClusterConfig metadata : name : test-windows-node-cluster region : ap-northeast-1 version : '1.28' nodeGroups : - name : windows-ng instanceType : g4dn.2xlarge ami : [ 作成したAMI id, ami-xxxxx ] amiFamily : WindowsServer2022FullContainer volumeSize : 120 minSize : 1 maxSize : 1 - name : linux-ng amiFamily : AmazonLinux2 minSize : 1 maxSize : 1 EKSの作成を開始します: $ eksctl create cluster -f test_windows_node_eksctl.yaml 完了確認 eksctlのコマンド実行により、 AWS はCloudFormationを呼び出してリソースを作成します。 CloudFormationでの確認 EKS管理コンソールでの確認 クラスタ ーの確認 ノードグループの確認 Session Manager を使用して Windows ノードにログインし、ソフトウェアのインストールおよびイメージのキャッシュを確認 containerdのバージョンが1.7.11であることを確認 NVIDIA GPU ドライバーを確認 Vulkanと DirectX を確認 unreal -engine-dev- windows -5.1:latestがキャッシュされていることを確認 終わりに 本記事を読むことで、UEアプリ用のカスタム Windows Node AMIの作成方法について理解していただけたと思います。 もちろん、この記事で作成した スクリプト は Unreal Editorの動作要件に基づいていますが、ビルドテンプレートファイルは共通のものです。 今後、読者は AWS 提供の EKS optimized WindowsAMI がご自身のプロジェクト要件を満たさないと感じた場合、この記事を参考にして スクリプト を置き換えて独自の Windows AMIを作成できます。 この記事では、 Windows Containerでの GPU 利用要件について言及しました。これに興味を持たれる方もいるでしょう。 次回の記事では、今回作成した Windows ノードを使用して、 Unreal Engine のPixel Streamingプロジェクトを実現する方法について説明します。 どうぞお楽しみに。 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間をお待ちしております! 電通総研の採用ページ 参考文献 Amazon EKS EKS optimized WindowsAMI Packer amazon-ebs Windows install-the-container-runtime DirectX-Device-Plugins 執筆: @chen.sun 、レビュー: 寺山 輝 (@terayama.akira) ( Shodo で執筆されました )
アバター
こんにちは、金融ソリューション事業部の孫です。 本記事ではUEアプリ用のカスタム Windows Node AMIを作成します。 これまでの 記事 では Linux ベースのノードで運用しておりました。 しかし、開発プロジェクトによっては Windows ノードは必須となるケースがあるので、その場合に本記事の知見が読者の皆様にご参考になれば幸いです。 本記事の内容は、 前編 と 後編 に分けて紹介します。 前編 では、 Unreal Editorを動作させるためのコンテナイメージの構築に焦点を当てています。 後編 では、その Unreal Editorコンテナイメージを Windows AMIに統合し、EKSでノードとして使用できるようにします。 はじめに コンテナイメージの構築環境 実施手順 1. 既存のLinuxコンテナイメージの構築プロセス 2. Windowsコンテナイメージ構築方法の検討 3. Windowsコンテナ用のDockerfileの作成 4.Windowsコンテナのテスト テスト1:コンテナを利用してプロジェクトを編集する テスト2:コンテナを使用してアプリケーションをパッケージングする 問題集 Shared DDCの設定方法 おわりに 参考文献 はじめに まず、 Unreal Engine のRuntimeとDevelopmentコンテナイメージの違いを説明します: Runtimeコンテナイメージ :このタイプのコンテナは、パッケージ化されたUEアプリケーションを実行するための環境のみを含み、完全な開発機能は含まれていません。これは Java Runtime や .NET Runtime に例えることができます。 Developmentコンテナイメージ :このタイプのコンテナには Unreal Editorおよびその他のビルドツールが含まれており、完全な Unreal Engine のバージョンに相当します。これは Java SDK や .NET SDK に例えることができます。 UEの公式ドキュメント より、技術的および法的な制約のため、 Windows ベースのDockerイメージは Runtimeコンテナイメージのみ提供という制限がわかりました。 制限を乗り越えるために、 TensorWorks と ue4-dockerプロジェクト のドキュメントを参考にし、実作の Windows Developmentコンテナイメージを作成します。 コンテナイメージの構築環境 Unreal Engine 5の Windows Developmentコンテナイメージを構築するために、以下の環境を使用しました: OS : Windows 11 Pro 64ビット CPU : Intel Core i5 -13500k メモリ :32GB GPU : NVIDIA GeForce RTX 3080 Unreal Engine :5.1.1 Docker Desktop :4.30.0 ※注意:Docker Desktopは Windows コンテナモードに切り替えてください。 実施手順 既存の Linux コンテナイメージの構築プロセス Windows コンテナイメージ構築方法の検討 Windows コンテナイメージ用Dockerfile作成 Windows コンテナのテスト 1. 既存の Linux コンテナイメージの構築プロセス Epic社は Linux Developmentコンテナイメージの Dockerfile を公開しており、これを参考に Windows Developmentコンテナイメージの構築プロセスを設計します。 ベースイメージと環境の設定 まず、Dockerfileで必要なベースイメージを設定します。 Linux の配布版は Ubuntu 、 CentOS 、 Red Hat など多岐にわたるため、ベースイメージは開発者が選択するパラメーター形式で設定されます。 ARG BASEIMAGE FROM ${BASEIMAGE} as prerequisites 次に、 NVIDIA GPU Driverをインストールするために、 環境変数 を設定しています。 ENV DEBIAN_FRONTEND=noninteractive ENV NVIDIA_DRIVER_CAPABILITIES ${NVIDIA_DRIVER_CAPABILITIES},compute,display,video UE ソースコード の コンパイル 環境構築 必要なシステムパッケージやツール( build-essential 、 git 、 python3 、 DirextX など)をインストールします。 RUN apt-get update && apt-get install -y --no-install-recommends build-essential ... libxv1 x11-xkb-utils xauth xfonts-base xkb-data ユーザー作成 非ルートユーザーを作成し、Git LFS を設定し、Gitクローン操作のための認証ヘルパーをインストールします。 RUN useradd --create-home --home /home/ue4 --shell /bin/bash --uid 1000 ue4 RUN git lfs install ... UEの ソースコード クローン 指定されたUE リポジトリ とブランチから ソースコード をGitでクローンします。 RUN mkdir /home/ue4/UnrealEngine && \ cd /home/ue4/UnrealEngine && \ git init && \ git remote add origin "$GIT_REPO" && \ git fetch --progress --depth 1 origin "$GIT_BRANCH" && \ git checkout FETCH_HEAD UE Dependenciesのインストール Setup.sh スクリプト を実行してUEに必要なパッケージをインストールします。 RUN --mount=type=cache,target=/home/ue4/gitdeps,uid=1000,gid=1000 sudo apt-get update && \ ./Setup.sh --exclude=Android --exclude=Mac --exclude=Win32 --exclude=Win64 UEのソースビルド .git ディレクト リを削除し、 Unreal Build Tool ( UBT )を利用して、UEソースをビルドします。 RUN ./Engine/Build/BatchFiles/Linux/Build.sh UnrealHeaderTool Linux Development -SkipBuild RUN ./Engine/Build/BatchFiles/RunUAT.sh ... 最終イメージの作成 UEの実行ファイルを新しいクリーンなイメージにコピーし、最終的な成果物にします。 COPY --from=builder --chown=ue4:ue4 /home/ue4/UnrealEngine/LocalBuilds/Engine/Linux /home/ue4/UnrealEngine ... 2. Windows コンテナイメージ構築方法の検討 Linux のDevelopment Dockerfileを解析した上で、UEを実行するコンテナを作成する方法を理解しました。 その中でも、最も重要なのはUEの ソースコード を コンパイル することです。 Windows システムでUEをインストールする際、 Epic Games Launcher という GUI ツールがありますが、このツールはコンテナ内では使用できません。 したがって、 Windows コンテナにUEを搭載するには、 ソースコード からの コンパイル のみ可能です。 Linux コンテナの構築プロセスを参考にして、以下の三つの主要プロセスを設計しました。 ① ソースコード の コンパイル 環境の設定と必要なツール・ライブラリのダウンロード Windows には、 Linux と同様に コマンドライン からソフトウェアをインストールできるツール Chocolatey があります。 まずはそれをインストールします。 そして、 Chocolatey を利用してソースビルドと実行用の Visual Studio 2019 DirectX Vulkan .Net Framework などのツールをインストールします。 ※ Visual Studio のバージョンについては、公式の推奨バージョンがあり、 公式ドキュメント を確認して選定してください。 ② UEの ソースコード のダウンロードと コンパイル ソースコード のダウンロードは、 Linux のDockerfileの処理を参考にします。 ソースコード の コンパイル には、UEのソース内にある \Engine\Build\BatchFiles\RunUAT.bat ビルドツールを使用します。 また、イメージサイズを縮小するために、 デバッグ 時にのみ使用されるDebugSymbolsやプロジェクト作成時に含まれるテンプレートプロジェクトおよびサンプルを削除します。 ③ コンパイル 済みの実行ファイルを新しいクリーンなイメージに移動して構築を完了 このプロセスは、 Linux のDockerfileの処理を参考にします。 また、 Windows のRuntimeイメージの Dockerfile も確認すると、 vendor-specific graphics APIs を有効にするための Powershell スクリプト があります。それも忘れずコンテナ内にコピーします。 ※ Windows のコア アーキテクチャ に関連しているため、詳細はこの ブログ を確認してください。 3. Windows コンテナ用のDockerfileの作成 上記に検討したプロセスに従って、Dockerfileを作成します。 ステップ1: ソースコード の コンパイル 環境の設定と必要なツール・ライブラリのダウンロード 必要な コンパイル 環境を設定し、関連ツールとライブラリをダウンロードする スクリプト は以下のとおりです: ARG BASEIMAGE= "mcr.microsoft.com/windows/server:ltsc2022" FROM ${BASEIMAGE} as prerequisites SHELL [ " cmd ", " /S ", " /C " ] # Install Chocolatey RUN powershell -NoProfile -ExecutionPolicy Bypass -Command " $env :chocolateyVersion = '1.4.0'; Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) " && echo . && echo .RUN directive complete. Docker will now commit the filesystem layer to disk. && echo .Note that for large filesystem layers this can take quite some time. && echo .Performing filesystem layer commit... && echo . # Install the rest of our build prerequisites and clean up afterwards to minimise image size COPY install-prerequisites.ps1 C:\ ARG VISUAL_STUDIO_BUILD_NUMBER=16 RUN powershell -ExecutionPolicy Bypass -File C:\install-prerequisites.ps1 %VISUAL_STUDIO_BUILD_NUMBER% && echo . && echo .RUN directive complete. Docker will now commit the filesystem layer to disk. && echo .Note that for large filesystem layers this can take quite some time. && echo .Performing filesystem layer commit... && echo . install-prerequisites.ps1 の内容は以下です。 # variable and importing the Chocolatey profile module. $env:ChocolateyInstall = Convert-Path " $( ( Get-Command choco).Path ) \..\.." Import-Module " $env:ChocolateyInstall \helpers\chocolateyProfile.psm1" # Install the chocolatey packages we need choco install -- no-progress -y git --params "'/GitOnlyOnPath /NoAutoCrlf /WindowsTerminal /NoShellIntegration /NoCredentialManager'" # pdbcopy.exe from Windows SDK is needed for creating an Installed Build of the Engine choco install -- no-progress -y choco-cleaner python vcredist-all windows-sdk-10-version-1809-windbg # Reload our environment variables from the registry so the `git` command works Update-SessionEnvironment # Gather the required DirectX runtime files, since Windows Server Core does not include them Invoke-WebRequest -Uri "https://download.microsoft.com/download/8/4/A/84A35BF1-DAFE-4AE8-82AF-AD2AE20B6B14/directx_Jun2010_redist.exe" -OutFile " $env:TEMP \directx_redist.exe" Start-Process -FilePath " $env:TEMP \directx_redist.exe" -ArgumentList "/Q" , "/T: $env:TEMP " -Wait expand " $env:TEMP \APR2007_xinput_x64.cab" -F :xinput1_3.dll C:\Windows\System32\ expand " $env:TEMP \Jun2010_D3DCompiler_43_x64.cab" -F :D3DCompiler_43.dll C:\Windows\System32\ expand " $env:TEMP \Feb2010_X3DAudio_x64.cab" -F :X3DAudio1_7.dll C:\Windows\System32\ expand " $env:TEMP \Jun2010_XAudio_x64.cab" -F :XAPOFX1_5.dll C:\Windows\System32\ expand " $env:TEMP \Jun2010_XAudio_x64.cab" -F :XAudio2_7.dll C:\Windows\System32\ # Retrieve the DirectX shader compiler files needed for DirectX Raytracing (DXR) Invoke-WebRequest -Uri "https://github.com/microsoft/DirectXShaderCompiler/releases/download/v1.6.2104/dxc_2021_04-20.zip" -OutFile " $env:TEMP \dxc.zip" Expand-Archive -Path " $env:TEMP \dxc.zip" -DestinationPath " $env:TEMP " Copy-Item -Path " $env:TEMP \bin\x64\dxcompiler.dll" C:\Windows\System32\ Copy-Item -Path " $env:TEMP \bin\x64\dxil.dll" C:\Windows\System32\ # Gather the Vulkan runtime library Invoke-WebRequest -Uri "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-runtime-components.zip?u=" -OutFile " $env:TEMP \vulkan-runtime-components.zip" Expand-Archive -Path " $env:TEMP \vulkan-runtime-components.zip" -DestinationPath " $env:TEMP " Copy-Item -Path "*\x64\vulkan-1.dll" -Destination C:\Windows\System32\ $visual_studio_build = $args [ 0 ] $windows_sdk_version = 20348 Invoke-WebRequest -Uri "https://aka.ms/vs/17/release/vs_buildtools.exe" -OutFile " $env:TEMP \vs_buildtools.exe" # NOTE : Microsoft.NetCore.Component.SDK only exists for VS2019+. And it is actually *needed* only for UE5 $vs_args = @( "--quiet" , "--wait" , "--norestart" , "--nocache" , "--installPath" , "C:\BuildTools" , "--channelUri" , "https://aka.ms/vs/ $visual_studio_build /release/channel" , "--installChannelUri" , "https://aka.ms/vs/ $visual_studio_build /release/channel" , "--channelId" , "VisualStudio. $visual_studio_build .Release" , "--productId" , "Microsoft.VisualStudio.Product.BuildTools" , "--locale" , "en-US" , "--add" , "Microsoft.VisualStudio.Workload.VCTools" , "--add" , "Microsoft.VisualStudio.Workload.MSBuildTools" , "--add" , "Microsoft.VisualStudio.Component.NuGet" , "--add" , "Microsoft.VisualStudio.Component.VC.Tools.x86.x64" , "--add" , "Microsoft.VisualStudio.Component.Windows10SDK. $windows_sdk_version " , "--add" , "Microsoft.Net.Component.4.5.TargetingPack" , "--add" , "Microsoft.Net.Component.4.6.2.TargetingPack" , "--add" , "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites" , "--add" , "Microsoft.NetCore.Component.SDK" , "--add" , "Microsoft.NetCore.Component.Runtime.3.1" ) # Install the Visual Studio Build Tools workloads and components we need Start-Process -FilePath " $env:TEMP \vs_buildtools.exe" -ArgumentList $vs_args -Wait # Clean up any temp files generated during prerequisite installation Remove-Item -LiteralPath " $env:TEMP " -Recurse -Force New-Item -Type directory -Path " $env:TEMP " # This shaves off ~300MB as of 2021-08-31 choco-cleaner if ( Test-Path " $env:APPDATA \NuGet" ) { Remove-Item -LiteralPath " $env:APPDATA \NuGet" -Recurse -Force } # Display a human-readable completion message Write-Output "Finished installing build prerequisites and cleaning up temporary files." ステップ2:UEの ソースコード のダウンロードと コンパイル UEの ソースコード をダウンロードするためには、Epicの GitHub で登録開発者になる必要があります。詳細は 公式ガイド を参照してください。 git clone コマンドを実行する前に、 GitHub アカウントにログインし、システムにログイン状態を保存してください。 FROM prerequisites as source # Enable verbose output for steps that patch files? ARG VERBOSE_OUTPUT=0 ARG GIT_REPO= "https://github.com/EpicGames/UnrealEngine.git" # The git branch/tag/commit that we will checkout ARG GIT_BRANCH= "5.1" # Clone the UE5 git repository using the host-supplied credentials WORKDIR C:\ RUN mkdir C:\UnrealEngine && ` cd C:\UnrealEngine && ` git init && ` git remote add origin %GIT_REPO% && ` git fetch --progress --depth 1 origin %GIT_BRANCH% && ` git checkout FETCH_HEAD && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo. # Run post-clone setup steps # (Note that the `-no-cache` flag disables caching of dependency data in `.git/ue4-gitdeps`, saving disk space) WORKDIR C:\UnrealEngine RUN Setup.bat -no-cache --exclude = Android --exclude = Mac --exclude = Linux && echo . && echo .RUN directive complete. Docker will now commit the filesystem layer to disk. && echo .Note that for large filesystem layers this can take quite some time. && echo .Performing filesystem layer commit... && echo . # Remove the sample `XXX` example platform cod RUN rmdir /s /q C:\UnrealEngine\Engine\Platforms\XXX 2 > NUL || exit 0 && echo . && echo .RUN directive complete. Docker will now commit the filesystem layer to disk. && echo .Note that for large filesystem layers this can take quite some time. && echo .Performing filesystem layer commit... && echo . # escape=` FROM source as builder # Set the changelist number in Build.version to ensure our Build ID is generated correctly ARG CHANGELIST COPY set-changelist.py C:\set-changelist.py RUN python C:\set-changelist.py C:\UnrealEngine\Engine\Build\Build.version %CHANGELIST% && echo . && echo .RUN directive complete. Docker will now commit the filesystem layer to disk. && echo .Note that for large filesystem layers this can take quite some time. && echo .Performing filesystem layer commit... && echo . # Remove the .git directory to disable UBT `git status` calls and speed up the build process RUN if exist C: \U nrealEngine \. git rmdir /s /q C: \U nrealEngine \. git && echo . && echo .RUN directive complete. Docker will now commit the filesystem layer to disk. && echo .Note that for large filesystem layers this can take quite some time. && echo .Performing filesystem layer commit... && echo . # Create an Installed Build of the Engine WORKDIR C:\UnrealEngine RUN .\Engine\Build\BatchFiles\RunUAT.bat BuildGraph ` -target="Make Installed Build Win64 " ` -script=Engine/Build/InstalledEngineBuild.xml ` -set:HostPlatformOnly=true ` -set:WithDDC=true ` -set:VS2019=true && ` (if exist C:\UnrealEngine\LocalBuilds\InstalledDDC rmdir /s /q C:\UnrealEngine\LocalBuilds\InstalledDDC) && ` rmdir /s /q C:\UnrealEngine\Engine && echo. && echo.RUN directive complete. Docker will now commit the filesystem layer to disk. && echo.Note that for large filesystem layers this can take quite some time. && echo.Performing filesystem layer commit... && echo. ステップ3: コンパイル 済みの実行ファイルを新しいクリーンなイメージに移動して構築を完了 コンパイル 済みのファイルを新しいコンテナイメージに移動し、最終イメージの容量を削減するためにクリーンアップを行います。 # Copy the Installed Build into a clean image, discarding the source tree FROM prerequisites as minimal # Copy the Installed Build files from the builder image COPY --from=builder C:\UnrealEngine\LocalBuilds\Engine\Windows C:\UnrealEngine COPY --from=builder C:\UnrealEngine\Components\DDC C:\UnrealEngine WORKDIR C:\UnrealEngine # Enable NVIDIA API Support COPY enable-graphics-apis.ps1 C:\ RUN powershell -ExecutionPolicy Bypass -File C: \e nable-graphics-apis.ps1 && echo . && echo .RUN directive complete. Docker will now commit the filesystem layer to disk. && echo .Note that for large filesystem layers this can take quite some time. && echo .Performing filesystem layer commit... && echo . 以上で、Dockerfileの作成は完了しました。 そして、以下のコマンドを実行し、ビルドします。 $ docker build -t unreal-engine-dev-windows-5.1 . 4. Windows コンテナのテスト テスト1:コンテナを利用してプロジェクトを編集する Runtimeコンテナとは異なり、今回は Unreal Editorもイメージに含めました。 これにより、プロジェクトを開いて開発作業が行えます。 テスト前に、 Unreal Editor GUI を使用してUEプロジェクトを作成します。 ※コマンドを使用してプロジェクトの作成も可能ですが、UE プラグイン のインストールは GUI で行う方が便利ですので、今回は GUI を使用してプロジェクトを作成しました。 Unreal Editorを開き、テンプレートを使用して WinContainerTest という新しいプロジェクトを作成します。 作成が完了したら、Pixel Streaming プラグイン を有効にします。 メニューバーから Edit ⇒ Plugins を選択し、検索ボックスに Pixel Streaming を入力します。 プラグイン をチェックして Unreal Editorを再起動し、インストールを完了します。 全部完了したら、コンテナを使用してこのプロジェクトを起動し、Web上で確認できるかを確認します。 以下のDockerコマンドを実行して、プロジェクトをコンテナ内の Unreal Editorで開きます: $ docker run --rm -ti \ --isolation process --device class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 \ -v "D:\Unreal Projects\WinContainerTest:C:\WinContainerTest" \ -p 8080:80 --entrypoint "cmd.exe" unreal-engine-dev-windows-5.1:latest \ /S /C C:\\UnrealEngine\\Engine\\Binaries\\Win64\\UnrealEditor-Cmd.exe \ C:\\wincontainertest\\WinContainerTest.uproject -AudioMixer \ -RenderOffscreen -stdout -FullStdOutLogOutput -unattended \ -EditorPixelStreamingStartOnLaunch=true ※ここで注意していただきたい点は以下のとおりです: Windows でコンテナの GPU サポートについて GPU リソースを取得するために、以下のパラメータを追加する必要 --isolation process --device class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 参照文献: WindowsコンテナでのGPUアクセラレーション 起動パラメータについて: -EditorPixelStreamingStartOnLaunch=true パラメータを使用すると、バックグラウンド起動時に自動的にPixel Streamingサービスが開始されます -stdout -FullStdOutLogOutput パラメータを使用すると、フルログが出力されます -unattended パラメータを使用すると、UEプロセスが終了したときに DialogBoxW や MessageBoxW GUI ポップアップを呼び出さず、正常に閉じられます プロジェクトのロードが完了したら、ログにPixelStreamingサービスの開始ログが確認できます。 この時点で、ブラウザを開いて URL 127.0.0.1:8080 を入力すると、UEプロジェクトの編集画面が表示されます。 この Webブラウザ 上で、遠隔操作で Unreal Editorを使用してプロジェクトを開発することができ、非常に便利でしょう。 テスト2:コンテナを使用してアプリケーションをパッケージングする コマンドライン を開き、以下のDockerコマンドを実行します: $ docker run --rm -ti -v "D:\Unreal Projects\WinContainerTest:C:\WinContainerTest" \ --entrypoint "cmd.exe" unreal-engine-dev-windows-5.1:latest /S /C \ C:\\UnrealEngine\\Engine\\Build\\BatchFiles\\RunUAT.bat BuildCookRun \ -clientconfig=Development -serverconfig=Development \ -project=C:\\WinContainerTest\\WinContainerTest.uproject \ -utf8output -nodebuginfo -allmaps -noP4 -cook -build -stage \ -prereqs -pak -archive \ -archivedirectory=C:\\WinContainerTest\\Packages \ -platform=Win64 完了後、 [project]/Packages フォルダで、パッケージされたファイルが確認できます。 問題集 今回のコンテナを使用しているときに、いくつかの問題が発見されました、ここで共有いたします。 新規作成されたUEプロジェクトは、 GUI で一度も開いたことがない場合、コンテナで直接開くことができません。 これは、プロジェクトを起動する前に、最新のエディターDLLを取得する必要があるためです。 解決するには、開く前に、コンテナでプロジェクトのエディターターゲットを一回 コンパイル してください。 bash Build/BatchFiles/Build.bat <ProjectName>Editor Win64 Development <PathToProjectFile>.uproject -WaitMute 参考文献: https://blog.mi.hdm-stuttgart.de/index.php/2017/02/11/uat-automation/ コンテナでプロジェクトを開く速度が遅い。 これは、キャッシュ( DDC )を再作成する必要があるためです。 Shared DDC を設定することで解決できます 参考文献: Derived Data Cache Shared DDC の設定方法 まず、プロジェクト用の DDC を作成します。 以下のコマンドを実行すると、プロジェクトフォルダーに Project/DerivedDataCache/DDC.ddp キャッシュファイルが生成されます。 $ Engine\Binaries\Win64\UnrealEditor.exe ProjectName -run=DerivedDataCache -fill -DDC=CreatePak 次にShared DDC のパスを指定します。 [ProjectPath]/Config/DefaultEngine.ini の最後に以下のコードを追加します。 #Default Engine.ini [ DerivedDataBackendGraph ] Shared = ( Type = FileSystem , ReadOnly = false , Clean = false , Flush = false , DeleteUnused = true , UnusedFileAge = 10 , FoldersToClean = 10 , MaxFileChecksPerSec = 1 , Path = % GAMEDIR %DerivedDataCache/ DDC .ddp , EnvPathOverride = UE -SharedDataCachePath , EditorOverrideSetting = SharedDerivedDataCache , CommandLineOverride = SharedDataCachePath ) ※Pathをプロジェクトフォルダー内の DerivedDataCache/DDC.ddp を設定してください。 Shared = ( Type = FileSystem , ... Path = % GAMEDIR %DerivedDataCache/ DDC .ddp , ... ) おわりに 今回の記事では、 Unreal Editorを含める Windows コンテナイメージの構築方法をご紹介しました。 次の 後編 で、この Windows コンテナイメージをEKS用の Windows AMIに統合し、 Windows ノードとして稼働させる方法を紹介します。 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間をお待ちしています! 電通総研の採用ページ 参考文献 Unreal Engine Containers Overview Known Limitations ue4-docker Setting Up Visual Studio Unreal Engine Dockerfiles Amazon EKS Unreal Editor interface Derived Data Cache Automate deployment with the Unreal Engine using the Unreal Automation Tool (UAT) Enabling vendor-specific graphics APIs in Windows containers 執筆: @chen.sun 、レビュー: @akutsu.masahiro ( Shodo で執筆されました )
アバター
こんにちは、 電通 総研金融ソリューション事業部の岡崎です。 今回は3Dモデルにアニメーションをつけるために、 Blender を使用して、アセット内にアー マチュア (ボーン)を作成して アニメーションを動かすまでの作成方法をご紹介します。 検証環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 4070 Ti Blender :3.6.4 実装手順 アー マチュア の作成 アー マチュア の各ボーンの名称を変更 アー マチュア とメッシュの結合 アニメーションの作成 1. アー マチュア の作成 まずはアニメーションをする元となるアセットを用意します。 今回は簡易的に作った二足歩行の動物のアセットを使用します。 画面上部ファイルからインポートを選択肢、任意のFBXファイルをインポートします。 インポートが完了したら画面左上のモード切り替えから「オブジェクトモード」を選択します。 「Shift + A」を押して追加ウィンドウを表示させて「アー マチュア 」を選択します。 ボーンが生成されました。 次に、メッシュの内部にアー マチュア を配置する際に最前面に表示できるように設定します。 プロパティタブのオブジェクトデータプロパティを押下します。 ビューポート表示の最前面にチェックを入れます。 これでアー マチュア が最前面に表示される様になります。 それではアー マチュア を使ってボーン構造を作成します。 モードを編集モードに切り替えます。 ボーンの色がオレンジに表示され、編集できる様になりました。 アー マチュア の位置を腰の位置まで移動します。 このボーンを基準に胴体、手足、頭などのボーンを追加します。 まずボーンが左右対称に追加できる様に設定します。 ビューポート上でキーボードの「N」を押下して、ツールメニューが表示されるので、「X軸ミラー」をオンにします。 次にボーンを追加します。 ボーンの先端の丸を選択して、「E」を押下し、マウスを移動するとボーンが追加されます。 同様の方法で、キャプチャのように背中、首、頭を作成します。 次に首から腕を作成します。 首の根本を選択して、「Shift + E」を押し、分岐のボーンを作成し、 ボーン追加の時と同様の手順で、マウスを移動させてボーンを追加します。 肩より先は、通常のボーンの追加方法で手の先まで作成します。 続いて腰から足を生やします。 腰のボーンの根本を選択します。 腕の時と同様に、「Shift + E」を押し、分岐のボーンを作成します。 さらに「E」でボーンを追加して足を作成します。 今回のモデルは耳もあるので、耳にもボーンを追加しておきます。 ボーンが完成した様に見えますが、腰と足のボーンはまだ接続できていません。 ボーンは細い先端の部分から追加作成する場合は連結されますが、 根本から作成した場合は連結しない性質があります。 (ボーンをずらしてみると連結していないのがわかります) ですので、腰のボーンに足のボーンが連動する様に設定します。 まずは足のボーンを選択します。 次に腰のボーンを「Shift」を押しながら追加選択します。 次に「CTRL + P」を押してオフセットを保持を選択します。 これで連結ができる様になりました。 試しにボーンを移動してみると、今度は破線が表示されるようになりました。 ボーンが連結されていることがわかります。(編集モードでは連結してみることはできません) 2. アー マチュア の各ボーンの名称を変更 ここでは、作成したボーンの名称を変更します。 ここまでで作成したボーンは下記キャプチャのような構造になっています。 編集モードのまま腰のボーンを選択します。 プロパティタブのボーンのプロパティを編集します。 キャプチャの「Bone」の部分を「Hip」に変更しました。 ちなみに、ボーンの名称を表示させるためには、オブジェクトデータプロパティの「名前」の欄にチェックを入れます。 同様に任意の名前を付けていきます。 私は下記キャプチャのように 命名 しました。 3. アー マチュア とメッシュの結合 現在はまだアー マチュア とメッシュには連結していません。 ここではアー マチュア をメッシュ内に埋め込み、連結させる方法を紹介します。 まずはオブジェクトモードを選択し、メッシュを選択して 続けて、「Shift」を押しながらアー マチュア を追加選択します。 次に「CTRL + P」を押して 「アー マチュア 変形>自動のウェイトで」を選択します。 これにより、アー マチュア が変形された時、メッシュも同時に変更される様になります。 4. アニメーションの作成 いよいよアニメーションを作成します。 フレームごとにボーンを曲げて動きを付けていきます。 画面下部の対象フレーム選択欄を「1」にします。 次にモード選択画面からポーズモードを選択します。 「A」を押すとボーンがすべて水色になります。 これは全てのボーンが選択されている状態です。まずはこのデフォルトのポーズを登録しておきます。 「I」を押してキーフレーム挿入メニューから「位置・回転・スケール」を押します。 これで1フレーム目のボーン形状とメッシュの形状が保存されました。 次に画面下部の対象フレーム選択欄を「20」にします。 ここで20フレーム目の動きを作成します。 任意のボーンの位置や回転を変えてポーズを変えていきます。 私は「spine1」の背骨を少し前に回転させて、お辞儀のポーズを作成しました。 同様に「A」を押してボーンを全て選択した状態にして 「I」を押してキーフレーム挿入メニューから「位置・回転・スケール」を押します。 同様に任意のフレームに任意の動きを作成します。 これでアニメーションの作成ができました。 アー マチュア の作成方法とアニメーションの作成方法の紹介は以上になります。 おわりに 今回は Blender を使用して、メッシュにアー マチュア (ボーン)を作成して、アニメーションを作成する方法を学習し、紹介しました。 ボーン編集やアニメーション機能により、UEなど外部の ゲームエンジン でも独自のキャ ラク ターアニメーションを追加することができます。3DCGの表現の幅が大きく広がりますので、引き続きアニメーションも学習していきたいと思います。 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! 電通総研採用ページ 参考文献 https://docs.blender.org/manual/ja/dev/modeling/modifiers/deform/armature.html https://www.ay3s-room.com/entry/blender-bone-armature https://vook.vc/n/5770 執筆: @okazaki.wataru 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
グループ経営ソリューション事業部で、会計プロダクト「 Ci*X Financials 」の製品開発を担当している高崎です。 唐突ですが、皆さんは自身の スキルアップ のために、どのようなことに取り組んでいますか? 例えば、書籍を購入して自己学習をしたり、社内外の勉強会や研修に参加したり、自身が学んだことを誰かに教えたりなど様々なことに取り組んでいるかと思います。 これらの方法でも スキルアップ は可能ですが、コンフォートゾーンを抜け出すということを意識して行動することで、より効果的に スキルアップ が可能です。 コンフォートゾーンを抜け出すという行動について、私の実体験を交えて、紹介したいと思います。 コンフォートゾーンとは コンフォートゾーン とは、自分にとって快適で慣れ親しんだ状態や行動の領域を指します。 コンフォートゾーンにとどまることは、安心感をもたらしますが、成長や学習は起こりません。 コンフォートゾーンを越えた先に、 ラーニングゾーン があります。 ラーニングゾーンは、新しいスキルや知識を獲得するために挑戦する領域です。 ここでは、少し不安や緊張を感じるかもしれませんが、成長が促進されます。 ラーニングゾーンのさらに先には、 パニックゾーン があります。 パニックゾーンは、非常に新しい状況や挑戦的な状況で、不安や恐怖を感じる領域です。 ここでは、ストレスが高まり、学習や成長が難しい場合があります。 自己成長を促進するためには、コンフォートゾーンからラーニングゾーンへの移行を意識的に行い、新しい経験や知識を積極的に追求することが大切と言われています。 コンフォートゾーンから抜け出す方法 では、具体的にどうすればコンフォートゾーンからラーニングゾーンへ移行できるのでしょうか? 私の実体験から、自己学習の範囲でラーニングゾーンへ移行するのは難しいと感じています。 参考として、私が実行してきた方法をいくつか紹介します。 これまで担当したことがない仕事の担当に手を挙げ、主担当としてその仕事をやり遂げる 担当しているプロジェクトの中での課題を自分でみつけ、その解決を主担当としてやり遂げる 自分がやりたい仕事(これまで経験がないこと)が現在の担当業務の範囲では経験することが難しい場合は、上司に希望を伝え続け、チャンスが来れば、その担当に アサイ ンしてもらう 社内公募などで他部署への異動のチャンスがあれば手を挙げる 転職する ※最終手段です・・ これらの方法をとると、否が応でも自身の力を上げないとやり遂げられないので、ラーニングゾーンへの移行が可能になります。 ただし、気を付けないといけないのは、自身の実力に対して高すぎる目標や、周囲に助けてくれる人がいない場合は、パニックゾーンに陥ってしまいます。(これも実体験からです・・) 重要なのは「自分の意思でコンフォートゾーンから抜け出す」という点です。他人に背中を押されても、なかなかコンフォートゾーンを抜け出せません。 自身の足りないものは何か、それを補うためには何をしないといけないのか、を分析しておく必要があります。 それを自分で考えることが難しい場合は、周囲に頼りになる同僚・上司がいれば、相談してみるといいと思います。 自分では考えつかなかった、自身の欠点や伸びしろを見つけられるかもしれません。 スキルアップ できた例 私がどのようにしてコンフォートゾーンを超えて、 スキルアップ できたかの一例を紹介します。 私は 電通 総研に2021年に中途入社したのですが、配属されたプロジェクトではテスト環境のインフラ管理者が1名しかいない状況でした。インフラは AWS を使用しているのですが、私のこれまでのキャリアとして、インフラではなくアプリケーション開発がメインだったので、インフラ力を上げる良い機会だと思いインフラ管理の担当者に立候補しました。 ※ここでコンフォートゾーンを超えて、ラーニングゾーンに入りました インフラの運用を行っていく中で、テスト環境として使用しているEC2( Amazon EC2 ) インスタンス が増えてきて、デプロイ作業や ミドルウェア の管理が大変になってきたので、アプリケーションのDockerコンテナ化やCI/CDパイプラインの構築を行いました。構築にあたって、書籍での自己学習や、 AWS の公式ドキュメント・ チュートリアル から基礎を学びました。 いろいろと失敗を重ねながら、手探りで構築を進めましたが、なんとか形にすることができました。 ※Dockerコンテナ化やCI/CDパイプラインを構築した理由は他にもあるのですが、また別の機会に詳しく話したいと思います 今ではインフラのみではなく、プロジェクト内のDevOpsを推進する役割を担うまで スキルアップ することができました。 最後に ここからは宣伝になりますが、私が開発を担当している「 Ci*X Financials 」は2021年11月にローンチした、新しいプロダクトです。 まだまだ成長過程のプロダクトですので、コンフォートゾーンを抜け出すチャンスがたくさんあります。 自身の成長が 顧客満足 に直結するプロダクトなので、とてもやりがいを感じられる仕事です。 興味がある方はぜひご応募ください! 私たちは一緒に働いてくれる仲間を募集しています! 次世代会計プロダクト開発プロジェクトマネージャー(Ci*Xシリーズ) 次世代会計プロダクト開発プロジェクトリーダー(Ci*Xシリーズ) 次世代会計プロダクト開発品質保証マネージャー(Ci*Xシリーズ) 次世代会計プロダクト開発ITアーキテクト(Ci*Xシリーズ) 次世代会計プロダクトDevOpsエンジニア(Ci*Xシリーズ) 最後まで読んでいただき、ありがとうございました。 少しでも誰かの スキルアップ の助けになれたら嬉しいです。 執筆: @takasaki.keisuke 、レビュー: 英 良治 (@hanabusa.ryoji) ( Shodo で執筆されました )
アバター
はじめに こんにちは、X イノベーション 本部 AITCの鴨谷です。 私はAITCの コンサルティング チームに所属しており、日々データ分析や 機械学習 モデルの開発に取り組んでいます。 今回は、AITCのチームで参加したKaggleのHome Credit-Credit Risk Model Stabilityコンペ( https://www.kaggle.com/competitions/home-credit-credit-risk-model-stability ) についてお話しします。2024年4月から6月にかけて行われたこのコンペで、私たちのチームは81位に入り、銀メダルを獲得しました。 この記事では、そのコンペでの私たちの取り組みや結果について紹介します。 メンバー 阿田木(Kaggle Master) 久木宮(Kaggle Expert) 松清 鴨谷 コンペの概要 このコンペの目標は、どのローン申込者がローンの返済を滞納する可能性が高いかを予測することです。 対象データは、各ローン申込者に関する内部情報および外部情報の CSV データです。 金融 ドメイン において、主催者は単純な予測精度だけでなく、予測モデルが時間を経ても安定しているかどうかにも重きを置いており、評価にはAUCに加えてテストセット全体での予測モデルの精度の安定性も考慮するカスタムメトリックが採用されています。 特に、第3項の0.5*std(residuals) が重要であり、各週(WEEK_NUM)ごとのスコアを安定させ、スコアが減点されないようなアプローチを考える必要がありました。 チームのアプローチ 今回の「Home Credit - Credit Risk Model Stability」コンペでは、我々のチームは二つのアプローチを軸に取り組みました。それは、「 債務不履行 分類モデル」と「Adversarialモデル」です。 債務不履行 分類モデル まず、純粋にコンペの趣旨に沿ったアプローチとして、「 債務不履行 分類モデル」を構築しました。このモデルは、 債務不履行 の有無(目的変数)を2値分類するための分類器を学習させるもので、以下のようなプロセスを経て作成されました。 - データの前処理 :欠損値が多い特徴量の削除、カテゴリ変数の エンコーディング 、特徴量エンジニアリングを実施しました。 - モデル選定 :LightGBM、XGBoost、CatBoostといった勾配ブースティングモデルを試行し、性能を比較しました。 - 評価 :AUC(曲線下面積)を主な評価指標として用い、交差検証によりモデルの安定性を確認しました。CVとLBが相関しなかったため、LBのスコア上昇をベースに検証を進めました。 最終的に、以下のモデルをアンサンブルして 債務不履行 分類モデルを構築しました: LightGBM × 13 CatBoost × 6 XGBoost × 1 このアンサンブル手法により、我々は 債務不履行 のリスクを高精度で予測できるモデルを構築することに成功しました。 Adversarialモデル 次に、我々は「Adversarialモデル」というアプローチを採用しました。このアプローチは、短期的な予想精度を悪化させることで、評価指標におけるペナルティ項の影響を緩和し、期間全体的なモデルのバランスを改善させることを目的としています。具体的には、以下のような手法を用いました。 トレインとテストの分離 :トレインデータを0、テストデータを1とラベル付けし、モデルを学習させ、トレインとテストを分離するモデルを作成しました。 データの識別 :このモデルを用いて、 閾値 0.97以下(トレインに近いデータがより直近のデータ)のスコアを持つデータを識別しました。 スコア調整 :識別されたデータのスコアを意図的に悪化させることで、ペナルティ項の影響を緩和し、全体的な評価スコアを向上させました。 このアプローチにより、短期的な予測精度は一時的に低下するものの、全体的なモデルのバランスを改善し、最終的な評価スコアを向上させることができました。 上位ソリューションとの差分 ここでは、このコンペで上位入賞した参加者のソリューションを紹介します。代表して1位のyuunieeさんのソリューション( https://www.kaggle.com/competitions/home-credit-credit-risk-model-stability/discussion/508337 ) を紹介します。 1st Solution Phase 1 - Machine Learning こちらは我々の「 債務不履行 分類モデル」と同様に、 債務不履行 の有無(目的変数)を2値分類するための分類器を学習させるアプローチです。 精度は我々と比較してかなり高く、Phase 1のみで公開LB上位の性能が出ているようです。 以下のようなプロセスを経て作成されています。 CV戦略 : StratifiedGroupKFoldを使用。CVの違い(0.001〜0.005)はLBとの相関が低かったが、0.01以上の違いは高い相関があった。 特徴量エンジニアリング : Max、Min、 Avg 、Var、First、Last、Max-Min Differenceなどの基本的な統計量を利用。 モデル選定 : LGBM、CatBoost、DNN(LightAutoMLライブラリ使用)を試行。CatBoostが最も優れている。 LGBMはCatBoostに比べてやや劣るものの、アンサンブルには有用。 DNNはDenselightモデルを使用し、シンプルなモデルがデータの性質に対して適している。 Phase 2 - Metric Hack こちらは我々のアプローチとは異なり、既存のWEEK_NUMとの相関の高い特徴量を用いて、隠されたテストデータのWEEK_NUMを推定し、スコアを補正するアプローチです。 データの識別 : date_decisionとmin_refreshdate_3813885Dの差異がWEEK_NUMと高い相関(0.9以上)を持っていることに着目し、テストデータの未知のWEEK_NUMの代わりとして用いることでデータを識別。 スコア調整 : DEVIDE=1/2、REDUCE=0.03の値を用いてスコアを調整。これにより、短期的な予測精度を悪化させつつ、長期的な予測精度を改善した。 その他の上位ソリューション 結果と反省 今回のコンペの結果は、Public 18位/Private 81位でした。 Public LBではスコアの上昇に追いつき、金メダル一歩手前(金圏は17位)まで行くことができましたが、最終的にPrivate LBで順位を落としてしまう結果となりました。 しかし、Publicで金メダル圏内からPrivateでメダル圏外に落ちてしまったチームも多くいる中、そこまで大きく順位を落とさず、銀メダルを獲得できたのは大きな成果であり、私たちのチームが安定したモデルを構築できていたことの証だと思っています。 おわりに 今回のコンペは非常に学びの多い経験となりました。 チームとしても個人としても、多くの技術的な課題に直面し、それを乗り越えることで成長することができました。 今後も技術力向上を目指し、コンペに参加する予定です。AITCは常に新しい挑戦を続け、より良いソリューションの提供に努めています。次のコンペでもチーム一丸となり、メダル獲得を目指します。 私たちのチームと一緒に働いてくれる仲間を募集しています。興味がある方はぜひご連絡ください。 電通総研 AIトランスフォーメーションセンター 採用情報ページ 執筆: 鴨谷 嘉人 (@yoshito_kamotani) 、レビュー: @yamada.y ( Shodo で執筆されました )
アバター
こんにちは。コミュニケーションIT事業部 ITソリューション部の英です。 普段はWebアプリや スマホ アプリの案件などを担当しています。あと、趣味でAIを勉強しています。 突然ですが、AIの勉強をしていると k-means法 と k近傍法 って混同しませんか? 不意に尋ねられた際にぱっと答えられる自信がありません。 前回はk-means法について解説したので、今回はk近傍法の検証をしましょう。 k-means法: クラスタリング 手法で、データをk個のグループに分ける、 教師なし学習 k近傍法:あるデータ点を、その点に最も近いk個の既知のデータ点(近傍)の多数決で分類する、 教師あり学習 → 前回の記事 この記事で学べること 分類手法 k近傍法(k-NN) 次元削減手法 t-SNE (t-distributed Stochastic Neighbor Embedding) k近傍法とは 分類や回帰に使われるシンプルな 教師あり学習 アルゴリズム です。未知のデータポイントを与え、その周囲のk個のデータポイントのクラス(正解ラベル)に基づいて分類します。距離計算を行い、最近傍のデータポイントの多数決で決定します。kの値はモデルの性能に影響し、小さい値は 過学習 、大きい値は汎化性能が向上します。 t-SNEとは 高次元空間のデータポイント間のペアワイズ類似度を確率分布としてモデル化し、低次元空間でも同様の類似度分布を再現するようにデータを配置します。 クラスタリング やパターンの視覚的理解に優れていますが、計算コストが高いです。今回の検証でもPCAよりt-SNEのほうが計算に時間を要しました。t-SNEは高次元空間でのペアワイズ類似度を ガウス分布 、低次元空間でのペアワイズ類似度をt分布でモデル化します。この手法により、データポイントAとBが高次元空間で近い場合、低次元空間でも近く配置される確率が高くなります。 "確率が高くなります"というところがポイントで、必ずしも近くに配置されることが保証されているわけではありません。 ここから本題 STEP1:学習用データの確認 前回の検証ではuser. csv という副産物が得られました。 CSV ファイルには誰がどのアイテムを閲覧または購入したのかという情報に加え、k-means法の クラスタリング 結果(正解ラベル)が含まれています。 今回はこの CSV ファイルをもとにk近傍法(k-NN)の学習を行い、サンプルデータを使って多クラス分類を行ってみます。 クラスタ 数は10個でしたから、そのいずれかに振り分けられることになります。 ※前回保存したデータに各アイテムの重みを追加しています ※user_idとlabelを除外し、特徴量として定義します STEP2:データの変換と保存 先ほどの CSV ファイルをもとにRecordIO形式のデータを生成します。 STEP3:S3へのアップロード 作成したデータをS3にアップします。 STEP4:Estimatorの作成 関数が古いと警告されていますが、knnのイメージは取得できます。このまま進めましょう。 k-NNのハイパーパラメータ ハイパーパラメータ 説明 設定例 feature_dim 次元数。入力データの特徴量の数を指定します。 500 k k値。最近傍の数を指定します。 10 sample_size サンプリングするデータの数を指定します。 200 predictor_type 予測の種類。分類 ( classifier ) または回帰 ( regressor ) のどちらかを指定します。 classifier 今回は500次元の1000個のデータポイントから200個取り出し、近傍10点のラベルで多数決(分類)をとります。 → ハイパーパラメータ STEP5:ト レーニン グの実行 ト レーニン グには数十分かかります。ステータスはSageMaker Studioで確認してください。 STEP6:モデルのデプロイ ト レーニン グが完了したので、推論エンドポイントとしてデプロイします。数十分かかります。 デプロイのステータスはSageMaker Studioで確認できます。 STEP7:モデル評価 ト レーニン グデータから一部を切り取ってテストデータとして定義し、予測結果と正解ラベルと一致しているかを確認しましょう。 各ラベルでそこそこの精度が出せていることが確認できます。 ※ラベル0,1,8はサンプルデータの偏りによって精度が低くなっています 評価指標の見方については過去の記事で解説しています。 → 評価指標について STEP8:可視化 次にt-SNEを使って可視化してみます。 テストデータを1点サンプリングし、テストデータと近傍の10点を強調して可視化します。 近傍の10点の正解ラベルを出力してみました。多数決なので、9:1でラベル6に振り分けられます。 可視化結果はこのようになりました。 test_dataは「×」で示しています。近傍点は大きめにプロットしています。 test_dataと近傍点が近くに配置されていることが分かります。 右下の点がuser_id=58のラベル4のデータです。 ※色は左下のLabelsを参照 STEP9:可視化(再検証) シード値を変更して別のデータポイントでも検証してみます。 random_stateを変更することで再検証できます。 test_data = features.sample(1, random_state=45) # 1点のみをサンプリング 近傍の10点の正解ラベルを出力してみました。多数決なので、8:2でラベル7に振り分けられます。 可視化結果は以下のとおり。 補足:t-SNEでは高次元空間で近い点が低次元空間でも近くなるように配置しようとしますが、すべての情報を正確に保持することはできません。そのため、近傍点が必ずしも視覚的に近くにプロットされるわけではありません。これは、次元削減の過程で一部の情報が失われたり、t-SNEが局所的な構造に重点を置くためです。 さいごに 今回はk近傍法(k-NN)の仕組みと実装方法について学びました。 前回の記事で解説したk-means法と組み合わせることで、ユーザーの クラスタリング を行い、それをもとに学習したk-NNの分類モデルを構築できます。 ECサイト のレコメンドシステムなどで活用すると良いかもしれませんね。その際には各 クラスタ の傾向を 言語化 するプロセスも必要となります。今回の検証では嗜向パターンを自分で定義しましたが、実データではそのようにはいきません。 これからも AWS ×AIの検証記事をたくさん書いていきます。 ↓ のスターを押していただけると嬉しいです。励みになります。 最後まで読んでいただき、ありがとうございました。 私たちは一緒に働いてくれる仲間を募集しています! コミュニケーションIT事業部 執筆: 英 良治 (@hanabusa.ryoji) 、レビュー: @takami.yusuke ( Shodo で執筆されました )
アバター
こんにちは、 電通 総研金融ソリューション事業部の岡崎です。 今回はUE5のMetaHumanとControlRigを使って簡単なアニメーションを作成する方法を紹介します。 アニメーションを本格的にゼロから作るためには、本来はUE以外のツールを使用して作成することが一般的ですが、 簡単な動きの場合はUEだけで作ることができます。 本記事ではMetaHumanがお辞儀をしたり、既存のアニメーションにアレンジを加えて、しゃがみながら歩行する方法などを紹介します。 検証環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 4070 Ti CPU:i9-12900H メモリ:24GB Game Engine: Unreal Engine 5.2.1 実装手順 MetaHuman、レベルシーケンスの準備 ControlRigを使用したアニメーションを作成 ControlRigからアニメーションシーケンスを作成 既存アニメーションをControlRigを使用して変更 1. MetaHuman、レベルシーケンスの準備 今回はMetaHumanに搭載されているControlRigを使用するので、まずはMetaHumanを用意します。 MetaHumanの用意の仕方は、前回の こちらの記事(UE5とLiveLinkを使ってMetaHumanの顔の動きを自由に生成する 前編) にて説明しているので、あわせてご覧ください。 今回のプロジェクト用に用意したレベルマップにMetaHumanを配置させます。 配置後、画面上部からレベルシーケンスを作成します。 今回はこのレベルシーケンス上でアニメーションを作成して、アニメーションシーケンスとしていつでも使えるように変更します。 シーケンサー エディターを開き左のリストにレベルに配置したMetaHumanを追加します。 今回は「BP_meta_male」をレベルに追加しているので、これを選択します。 シーケンサー エディターのリストに「BP_meta_male」があることを確認します。 2. ControlRigを使用したアニメーションを作成 ここでは「BP_meta_male」に任意の動きを作成します。 今回はMetaHumanにお辞儀をさせてみます。 シーケンサー エディターのリストの「BP_meta_male」を開くと「Body」と「Face」があるので、「Body」を選択して、「MetaHuman_ControlRig」を開きます。 (MetaHumanではなく、サードパーソンテンプレートのデフォルトキャ ラク ターを使用する場合は、「ControlRig」という項目があるので、そちらを選択することで同様の作業ができます) レベルシーケンスの詳細な操作方法は こちらの記事(UE5 レベルシーケンスやShot機能を使った動画制作手順) で説明しています。 MetaHumanの体の周りに赤やオレンジ、青などの枠が付いているのが確認できます。 この枠(輪っか)を回転させることで、腕や足、腰などの関節を動かしていくことができます。 まずは シーケンサー エディターのタイムカーソルを0秒のところへ移動させます。 ここでデフォルトの体勢を作ります。 お辞儀をする前に状態の体勢なので、腕を真っ直ぐ下に伸ばします。 腕や肩の関節にある輪っかを選択して、回転などをして任意の体勢を作ります。 自分の好みの体勢ができたらキーフレームを打ちます。 「MetaHuman_ControlRig」を選択して「S」を押します。 もしくはリストに表示されているキーフレーム追加ボタンからでもキーフレームを打つことができます。 お辞儀が終わった時の体勢でも、この体勢を使用するので、コピーしてタイムカーソルを3秒の位置に変更して貼り付けます。 コピーは右クリックのコピーで行えます。 コピーができたことを確認します。 ではお辞儀で頭を下げている体勢を作ります。 タイムカーソルで1秒の位置に変更します。 MetaHumanの腰の位置にある枠を選択して、前方に回転させます。 必要に合わせて顔の向きや手の位置なども変更します。 頭の下げた体勢を作成できたらキーフレームを追加します。 シーケンサー を再生させるとお辞儀している様子が作成できました。 ここまでの状態では、レベルシーケンス上では任意のアニメーションを作ることはできましたが、アニメーションを他のアクターで使いまわしたり、アニメーションブループリントに追加することはできません。 次に工程でアニメーションシーケンスというファイル形式で保存する方法を紹介します。 3. ControlRigからアニメーションシーケンスを作成 アニメーションシーケンスというのは、特定のスケルタルに対して、動きのみを保存してあるファイルになります。 このファイルを使うことで、同じスケルタル(ボーン構造)を使用したスケルタルメッシュでアニメーションを使いまわすことができます。 レベルシーケンスで作成したアニメーションからアニメーションシーケンスを作成する方法は、 シーケンサー エディター上で「BP_meta_male」の「Body」を選択して 右クリックから「リンクされたアニメーションシーケンスを作成」を選択することで作成できます。 保存するフォルダとアニメーションシーケンスの名前を設定します。 しかし こちらの記事(UE5とLiveLinkを使ってMetaHumanの顔の動きを自由に生成する 後編) で紹介した通り、UE5.2でレベルシーケンスからアニメーションシーケンスを作成しようとするとフリーズしてしまいます。 プロジェクト設定からRHIの設定を変更することでフリーズを回避できるので、アニメーションシーケンスを作成する時だけ設定を変更します。 プロジェクト設定画面を開き検索窓に「RHI」と記入します。 ターゲットのRHIという欄があるので「DirectX12」から「Vulkan(SM5)」に変更します。 再起動をすることで設定が反映されます。 プロジェクト設定を変更することで、フリーズせずにアニメーションシーケンスを生成できます。 作成したアニメーションシーケンスを使用することで、他のMetaHumanにもお辞儀のアニメーションを使用できます。 使用する方法は、レベルシーケンスにMetaHumanを追加します。 (BP_woman2というアクターを配置しています) 次に「Body」の「MetaHuman_ControlRig」を削除します。 アニメーション追加ボタンから、作成したアニメーションシーケンスを追加することでアニメーションの再生をできます。 (アニメーションを再生させる場合はControlRigを削除しないといけないので、動きは基本全てアニメーションシーケンスに変更してからMetaHumanに再生させるのをおすすめします) 4. 既存アニメーションをControlRigを使用して変更 今までの工程ではゼロからアニメーションを作成しましたが、既存のアニメーションや外部サイトからダウンロードしたアニメーションと同様のクオリティのアニメーションを作るのはとても大変です。 なのでこの工程では、既存のアニメーションをControlRigを使用して、自分のプロジェクトに合った形に少し変更する方法を紹介します。 まずは使いたい既存のアニメーションを決めます。 こちらの記事 (UE5でMixamoのアニメーションをMetaHumanに適応させる方法) で外部サイトからアニメーションをダウンロードしてMetaHuman用にリターゲティングする方法も紹介しています。 今回はサードパーソンテンプレート内の歩行のアニメーションを使用します。 任意のMetaHumanをレベルシーケンスにセットして歩行のアニメーションシーケンスを追加します。 (BP_Cooperというアクターを配置しています) 前述した通り、ControlRigを削除しないとアニメーションシーケンスを使用できないので、ControlRigを一旦削除します。 アニメーションシーケンスは「MM_Walk_Fwd」を使用します。 次に、このアニメーションシーケンスをControlRigに焼き付けていきます。 「Body」を選択して、右クリックから「コン トロール リグにベイク」を選択します。 ControlRigを選択する画面が表示されるので、「MetaHuman_ControlRig」を選択します。 するとシーケンスエディターのタイムライン上で、アニメーションが毎フレームごとに全ての体の部分にキーフレームが打たれた形に変更されます。 ここからキーフレームを変更して任意のアニメーションに変更します。 今回はしゃがみながら歩行をするアニメーションに変更しようと思います。 キーフレームの全ての点を変更するのはとても大変なので、キーフレームを上書きする機能を使います。 「Body」の下にある「MetaHuman_ControlRig」を右クリックして「セクションを追加>加算」を選択します。 これにより、現在のアニメーションをベースに希望する動きを上書きできるようになります。 「MetaHuman_ControlRig」の下にもう一つ加算用の「MetaHuman_ControlRig」が追加されたことを確認します。 加算用に追加された「MetaHuman_ControlRig」を選択して、MetaHumanの腰にある枠を選択して、下に移動させます。 また、少し前屈みにもさせてみます。 加算のControlRigを動かすことで、アニメーションをベイクしたControlRigを毎フレームごとに動かさなくても、アニメーション全体が変更されるようになります。 このまま新しくできたほうの「MetaHuman_ControlRig」にキーフレームを打ちます。 レベルシーケンスを再生させると、しゃがんだまま歩行しているアニメーションができていることが確認できます。 最後にこのアニメーションを前の工程と同じようにアニメーションシーケンスに変更していきます。 以上で既存のアニメーションを自分の必要なアニメーションに変更して、アニメーションシーケンスに変更させる方法の紹介を終わります。 おわりに 今回はMetaHumanのControlRigを使ってアニメーションを作成する方法を紹介しました。 動画制作などを行っていると、キャ ラク ターにもう少し右を向いて欲しい!などの細かく動きを制御したい場面が出てきます。 こういった時に、今回学習した方法は、簡単にアニメーションシーケンスを作れるのでとても有効な手段だと感じました。 今後はゼロからアニメーションを作成する方法なども含めて、動画作成などに必要な技術の学習をさらに頑張っていこうと思います。 最後までご覧くださいまして、ありがとうございました! 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! 電通総研採用ページ 電通総研・最新テクノロジー事業企画・推進担当採用ページ 参考 https://dev.epicgames.com/documentation/ja-jp/unreal-engine/control-rig-in-unreal-engine?application_version=5.2 https://note.com/polycube1/n/nc6513f645a3c https://historia.co.jp/archives/35097/ 執筆: @okazaki.wataru 、レビュー: @akutsu.masahiro ( Shodo で執筆されました )
アバター
こんにちは、 電通 総研金融ソリューション事業部の岡崎です。 今回はUE5のレベルシーケンスを使用してデモ動画を作る方法を紹介します。 この記事では基礎的な内容として、アクターの配置方法や移動、アニメーションの設定方法の紹介を行います。 また、複数人で共同でレベルシーケンスを制作する際にコンフリクトが起こりにくい制作の方法として、 Shot機能を使用した方法なども紹介していきます。 検証環境/ツール OS: Windows 11 pro GPU : NVIDIA GeForce RTX 4070 Ti Game Engine: Unreal Engine 5.2.1 実装手順 レベルシーケンスファイルの作成 アクターの移動やアニメーションの設定 カメラの移動や 焦点距離 の設定 Shot機能を使ったレベルシーケンスの作成 シーケンス動画をプレイ時に再生する設定 1. レベルシーケンスファイルの作成 シーケンサー という機能は、カメラやアクターを自由に動かすことで、ゲーム中のデモ動画や映像制作の動画などを作成する際に使用する機能です。 今回はデモ動画を作る際に必要な機能を紹介します。 まずはレベルシーケンスファイルを作成します。 画面上部の動画ボタンを押して「レベルシーケンスを追加」を押します。 レベルシーケンスファイルができるので、自分は「LS_Test」と 命名 しました。 シーケンサー というウィンドウが出てくるので、画面下部に配置します。 (画面下部でなくてもいいですが、ViewPortの画面と シーケンサー の画面が同時に見えた方が作業がしやすいです) シーケンサー 編集画面で動画の時間を設定できます。 デフォルトではフレームレートで分割されています。用途に合わせてフレームレートから「秒」に変更などを行ってください。 今回は下記設定の箇所から「秒」の設定に変更しました。 次に、レベルシーケンス内で使用するカメラを追加します。 このカメラを使用して動画を撮影していきます。 シーケンサー エディターの上部にあるビデオカメラマークを押します。 シーケンサー エディター内のリストにに「CineCameraActor」が追加されました。 ここから撮影を開始していきます。 2. アクターの移動やアニメーションの設定 レベルシーケンスファイルとは、その名の通り、レベル(マップファイル)に対応したシーケンスファイルになります。 そのため、レベルシーケンスで何かアクターやアセットにアクセスしたい場合は、まずはそのアクターやアセットがレベル上に配置されている必要があります。 今回はレベルシーケンスの中で、サードパーソンテンプレートの中に入っているキャ ラク ターを移動させたりアニメーションを付与したりしていきます。 まずはレベル上にサードパーソンテンプレートのキャ ラク ターのアクターブループリントを配置します。 シーケンサー エディターの左側にあるトラック追加ボタンから、「 シーケンサ へのアクタ」を選びレベル上に配置したアクターブループリントを選択して、リストに表示させます。 これでレベルシーケンス上でアクターにアクセスができるようになります。 リストに表示された「ThirdPersonCharactor」をクリックした後にキーボードの「S」を押すことでキーフレームを打つことができます。 今回私は、1秒経った所にカーソルを持ってきて「S」を押し、キーフレームを打ちました。 キャプチャでオレンジの丸がついた部分がキーフレームを打った箇所になります。 秒数のカーソルを3秒のところへ移動させます。 キャ ラク ターを移動させたいポイントまで移動させて、再び「S」を押してキーフレームを作成します。 左下のシーケンスエディターの再生ボタンを押すことで、キャ ラク ターが移動しているのを確認できます。 ちなみにキーフレームのオレンジ色の丸にも意味があり、 このキーフレームの種類は動き始めと動き終わりをゆっくりにして、滑らかに移動するように設定されているキーフレームになります。 緩やかではなく、一次関数的に動くためには、キーフレーム上で右クリックを行い、リニアという種類のキーフレームを選択します。緑色の三角のキーフレームに変更されるので、場合によって使い分けてみてください。 キーフレームの詳細については UEの公式サイト を参照してください。 次に、キャ ラク ターにアニメーションを追加していきます。 シーケンスエディターの左側のリストから「ThirdPersonCharactor」をクリックして、右側のプラスボタンから 「アニメーション>任意のアニメーション(今回はMF_Walk_Fwd)」を選択します。 シーケンスエディターに「MF_Walk_Fwd」というラベルが追加されます。 このラベルが教示されている間だけアニメーションが再生されるので、キャ ラク ターが移動している部分にラベルを移動して長さも調節します。 再生ボタンを押すと、キャ ラク ターが移動している時だけ、歩きのアニメーションが再生されるのが確認できます。 歩いている時以外は、「MM_idle」のモーションを追加してみます。 これで歩く前のタイミングは待機のモーションになります。 さらに、待機モーションと歩行モーションを下記キャプチャのように重ねることで、2つの動きを自然な形で ブレンド してくれます。 次はカメラの動きや調整などを行っていきます。 3. カメラの移動や 焦点距離 の設定 シーケンサー エディターで「CineCameraActor」を選択します。 リスト上の「CineCameraActor」の右側にあるビデオカメラマークを押下します。 これで、撮影するカメラがどのような画角で撮影をしているのか見ることができます。 次に時間軸のカーソルを0秒のところへ移動します。 次にUEの基本操作と同じようにカメラの視点を動かして、撮影したい画角を決めます。 画角を決めたら先ほどと同じように、「S」を押下してキーフレームを作成します。 シーケンサー エディターのリストに「Transform」というカラムが作成され、オレンジ色のキーフレームが作成されたことを確認します。 次に任意の場所まで時間軸のカーソルを移動して、カメラの画角の位置も変更します。 先ほどと同じように「S」を押すことで、カメラの位置と画角をキーフレームに保存できます。 シーケンサー エディターのプレイボタンを押すことで、カメラの位置が時間軸に沿って変更されているのが確認できます。 カメラの位置や向きだけではなく、被写体深度や画角も決めることができます。 カメラで撮影する時に必要になってくる項目は下記になります。 ・CurrentAperture= F値 (どのくらいボケ感を出すか) ・CurrentFocalLength=視野角( 焦点距離 を選んでどの範囲の映像を撮影するか) ・マニュアル 焦点距離 (ピントをどこに合わせるか) 難しい説明は省きますが、基本的に F値 を小さくすると、物体にピントがあった際に背景はボケさせる演出などを作ることができます。 これにより、映像の効果として、その物体に集中して注意を向けることができます。 今回は「CurrentAperture」の数値をデフォルトのまま「2.8」としておきます。この数値は感覚としてボケ感がよく出る数値になります。 今回は手前にあるキャ ラク ターの手にピントを合わせて、他の部分をボケさせて、手に集中してもらう演出を作ります。 「マニュアル 焦点距離 」を、カメラから手までの長さ(センチメートル)に変更します。 ある程度ピントが合う位置が見つけられたらそこでキーフレームを打ちます。 今回は「70」を設定しました。 これにより、手に集中する演出が出来ました。 今回は変更をしませんでしたが「CurrentFocalLength」を変更することで画面の広さ(視野角)を変更できます。 デフォルトでは「35」となっており、数値を下げると広角に、数値を上げるとズームになります。 キーフレームを使って手が出てきたタイミングでピントを合わせてみます。 gif画像では画質が悪く分かりづらいですが、手元が映った瞬間に、手元にピントがあう実装をしています。 これでカメラの設定に関する紹介を終わります。 4. Shot機能を使ったレベルシーケンスの作成 最後にShot機能を使ったレベルシーケンスについて説明をします。 Shot機能を使うことで、ひとつのレベルシーケンスを複数のShotシーケンス(子要素)で構成することができます。 これにより、Shotシーケンス同士の入れ替えや修正が容易になる他、いくつかパターンを持たせて比較検討などをすることが可能になります。 今回私たちは、プロジェクトを複数人で作成していたので、 レベルシーケンスをShotとして分けることで、作業を分担しやすくコンフリクトが起こりにくくなることをメリットとして機能を使用しました。 Shot機能を使用するためには、画面上部の動画ボタンから「ショット付きレベルシーケンスを追加」を選択します。 設定画面で、親要素に当たるマスターシーケンスの名前や、保存するフォルダの場所、Shotの数などを設定することができます。 こちらは後から変更も可能です。 今回私は、「LS_TestWithShots」という名前でマスターシーケンスを作成して、「NumberOfShots」で「5」を記入して 5つのShotsで形成されるレベルシーケンスを作成しました。 保存先には下記キャプチャのように親のレベルシーケンスファイルとShotsが入ったフォルダが生成されます。 マスターシーケンスである「LS_TestWithShots」を開くと、5つのShotシーケンスを確認することができます。 それぞれのShotを選択することで、本記事で紹介したレベルシーケンスと同様に編集できます。 Shot間の接続部分は、アクターやカメラ コンポーネント の位置を同じにすることで、シームレスにShotの繋ぎ目を感じさせることなく次のShotに移動することができます。 またマスターシーケンス上では、それぞれのShotの長さを変更することもできます。 ドラッグすることでShotの入れ替えも可能です。 この機能を使うことで、ひとつのレベルシーケンスファイルで管理するよりも柔軟に編集が可能になります。 レベルシーケンスの基礎的な使い方の紹介は以上になります。 おわりに 今回はUE5のレベルシーケンスを使用して、簡単な動画作成の手順を紹介しました。 カメラの動きやアクターの動きを直感的に作成できるので、本格的な動画制作から、3D空間を移動する際の簡単なイメージ共有用資料などまで、さまざまな用途で使用することができそうだと感じました。 また、MetaHumanや高画質なアセットなどを使うことで、簡単に現実と見紛うほどのフォトリアルな動画撮影も撮影可能だったことに大変驚きました。 シーケンスエディター上ではまだまだ使用したことのない機能がたくさんあるので、今後も色々と試していきたいと思います。 最後までご覧くださいまして、ありがとうございました! 現在、 電通 総研は web3領域のグループ横断組織 を立ち上げ、Web3および メタバース 領域のR&Dを行っております(カテゴリー「3DCG」の記事は こちら )。 もし本領域にご興味のある方や、一緒にチャレンジしていきたい方は、ぜひお気軽にご連絡ください! 私たちと同じチームで働いてくれる仲間を、是非お待ちしております! 電通総研採用ページ 参考 https://dev.epicgames.com/documentation/ja-jp/unreal-engine/sequences-shots-and-takes-in-unreal-engine?application_version=5.2 https://mononoco.com/creative/ue/ue5-rngw-12 https://historia.co.jp/archives/20117/ 執筆: @okazaki.wataru 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
アバター
こんにちは。コミュニケーションIT事業部 ITソリューション部の英です。 普段はWebアプリや スマホ アプリの案件などを担当しています。あと、趣味でAIを勉強しています。 突然ですが、AIの勉強をしていると k-means法 と k近傍法 って混同しませんか? 不意に尋ねられた際にぱっと答えられる自信がありません。 なので、今回から2回に渡ってk-means法とk近傍法のそれぞれを実際に検証して身に付けようと思います。 k-means法: クラスタリング 手法で、データをk個のグループに分ける、 教師なし学習 k近傍法:あるデータ点を、その点に最も近いk個の既知のデータ点(近傍)の多数決で分類する、 教師あり学習 まず、今回は k-means法 を使って簡単な クラスタリング を行い、可視化してみようと思います。 次回は k近傍法(k-NN) について解説します。 この記事で学べること クラスタリング 手法 k-means法 次元削減手法 PCA (Principal Component Analysis) t-SNE (t-distributed Stochastic Neighbor Embedding) k-means法とは データをk個の クラスタ ーに分ける クラスタリング アルゴリズム です。まず、データポイントからk個の中心点をランダムに選びます。各データポイントは最も近い中心点に割り当てられます。その後、各 クラスタ の新しい中心点を計算し、データポイントの割り当てを再調整します。このプロセスを中心点の位置が変わらなくなるまで(収束するまで)繰り返します。主に パターン認識 やデータ解析に用いられます。 次元削減手法とは 高次元データをより低次元に変換し、データの本質的な特徴を保持しながら、計算の効率化や可視化を容易にする技術です。ノイズの除去やデータの圧縮にも有用です。また、次元削減を行うことで、人がデータを直感的に理解しやすくなります。人の目で認識できるのはせいぜい3次元空間までですから、高次元データを可視化したい場合にはこれらの手法を用いて次元を落とす必要があります。 PCAとは (Principal Component Analysis) データの分散を最大化する方向(主成分)を見つけ、それに基づいてデータを再表現する次元削減手法です。データの共分散行列を計算し、その 固有ベクトル と 固有値 を求め、 固有値 の大きい順に主成分を選びます。これにより、元の高次元データを少数の主成分で表現できます。主成分分析と呼びます。 t-SNEとは (t-distributed Stochastic Neighbor Embedding) 高次元空間のデータポイント間のペアワイズ類似度を確率分布としてモデル化し、低次元空間でも同様の類似度分布を再現するようにデータを配置します。 クラスタリング やパターンの視覚的理解に優れていますが、計算コストが高いです。今回の検証でもPCAよりt-SNEのほうが計算に時間を要しました。t-SNEは高次元空間でのペアワイズ類似度を ガウス分布 、低次元空間でのペアワイズ類似度をt分布でモデル化します。この手法により、データポイントAとBが高次元空間で近い場合、低次元空間でも近く配置される確率が高くなります。 ここから本題 ECサイト の購入や閲覧の履歴からユーザーを クラスタリング する検証を行います。 STEP1:ライブラリのインポート 必要なライブラリをインポートします。 STEP2:データ生成の準備 ユーザー数やアイテム数、グループ、アイテムのカテゴリ数などを定義します。 特定のグループには好みがあるものとし、好みのカテゴリに応じたアイテムを閲覧したり購入しやすいものとします。 STEP3:データ生成 全ユーザーと全アイテムを掛け合わせ、好みに応じて各アイテムの閲覧と購入させます。 STEP4:データフレームの生成 先ほど生成した閲覧と購入のデータをpandasのデータフレームに当てはめます。 STEP5:データの結合 データフレーム2つを1つのinteraction_dfとして結合します。 STEP6:interaction_matrixの作成 ユーザー(1000行)×アイテム(500列)のマトリクスを作成します。 閲覧を1、購入を2として重み付けして集計(sum)します。 STEP7: クラスタリング の実行 今回は分析する前から クラスタ 数が10個であることが分かり切っているため、n_clustersには10をセットします。(※STEP2を参照) わずか数秒で クラスタリング が完了しました。 STEP8: クラスタリング 精度の評価 クラスタリング 精度は3つの指標で数値的に評価できます。 Silhouette Score データポイントがどれだけ適切に クラスタ に分類されているかを評価します。スコアは-1から1の範囲で、1に近いほど良い クラスタリング です。 Calinski-Harabasz Score クラスタ 内の分散と クラスタ 間の分離のバランスを評価します。スコアが高いほど、 クラスタ 内のデータが緻密で、 クラスタ 間の分離が良いことを示します。 Davies-Bouldin Score クラスタ 内の密集度と クラスタ 間の分離度を評価します。スコアが低いほど、 クラスタ 内のデータが密集し、 クラスタ 間の分離が良いことを示します。スコアは0に近いほど良い クラスタリング です。 STEP9: クラスタリング 結果の保存 次回の記事で使用するため、結果を保存しておきます。 CSV ファイルの中身は以下のとおりです。 STEP10:PCAによる次元削減と可視化 まず、PCAで可視化してみます。 STEP11:t-SNEによる次元削減と可視化 次にt-SNEで可視化してみます。 STEP12:テストデータを加工して再実施 先ほどの例では クラスタ 同士が離れすぎており、あまり現実的なデータではありませんでした。 アイテムの購入や閲覧の確率を微調整して再度 クラスタリング を実施してみます。 「好みだけど買わない(見ない)、好みじゃないけど買う(見る)」の割合を増やします。 for user_id, preferences in user_preferences.items(): for item_id in item_categories_keys: # 各カテゴリに基づく確率設定 purchase_prob = 0.2 + 0.6 * random.random() # より広い範囲の確率設定 view_prob = 0.3 + 0.6 * random.random() # より広い範囲の確率設定 if item_categories[item_id] in preferences: # 好みに基づく確率で購入・閲覧 if random.random() < purchase_prob: purchase_history.append([user_id, item_id, item_categories[item_id], 'purchase']) if random.random() < view_prob: view_history.append([user_id, item_id, item_categories[item_id], 'view']) else: # その他のカテゴリも高確率で購入・閲覧 if random.random() < 0.3: # 0.1から0.3に変更 purchase_history.append([user_id, item_id, item_categories[item_id], 'purchase']) if random.random() < 0.4: # 0.2から0.4に変更 view_history.append([user_id, item_id, item_categories[item_id], 'view']) その結果がこちら。それっぽい クラスタリング ができているかと思います。 当然ながら各スコアは目に見えて低下します。 STEP13: クラスタ 数を変更して再実施 次は クラスタ 数を変更して可視化してみましょう。 クラスタ 数:5 クラスタ 数:15 このように比べてみると、 クラスタ 数が10だった頃がもっとも クラスタ 間の境目がはっきりしており、各 クラスタ の密度も高いことが分かると思います。 実データを取り扱う場合にはこのように クラスタ 数を変更し、可視化やスコアを用いて最適な クラスタ 数を見つけていくステップが重要になります。 さいごに k-meansによる クラスタリング と、次元削減手法のPCAとt-SNEを使った可視化を行いました。 お気づきかもしれませんが、今回はデータ準備の段階で クラスタ 数が10個であることが明確だったので簡単に クラスタリング ができています。実データを取り扱う際には クラスタ 数も含め、ハイパーパラメータを調整しながら検証してください。 → k-meansのハイパーパラメータ また、今回の検証の副産物として クラスタリング 済みのusers. csv が手に入ったので、次回はこれを教師データとしたk近傍法(k-NN)の検証をしたいと思います。 これからも AWS ×AIの検証記事をたくさん書いていきます。 ↓ のスターを押していただけると嬉しいです。励みになります。 最後まで読んでいただき、ありがとうございました。 私たちは一緒に働いてくれる仲間を募集しています! コミュニケーションIT事業部 執筆: 英 良治 (@hanabusa.ryoji) 、レビュー: @nagamatsu.yuji ( Shodo で執筆されました )
アバター