Dell Pro Max with GB10

大学生協で Nvidia DGX Spark が台数限定で売られていて年度末で予算が余っていたので買おうとしたら売り来てて店長さんに代わりに OEM 互換の Dell Pro Max with GB10 を紹介され、それを購入した。699,900円。

セットアップしようとしたら本体に USB-C 端子しかなく詰んだが、いろいろ探してみるとUSB-C -A アダプタなどがバラバラ出てきたのでキーボード、マウス、USBメモリなどをつなげられるようになり、先に進んだ。

なにかのはずみで GUIログインができなくなったので、OS再インストールしようかと思ってここからしばらくハマった。

めんどくさいので途中経過は省略するが「NVIDIA DGX Spark 公式」の方法によるシステムリカバリーというところに書かれている通りにやったらなんとか再インストールできた。なぜかはわからんが、windows で powershell のスクリプトでリカバリーイメージをUSBメモリに流し込まなくては boot option で usb なんちゃら partition 1 という選択肢が出てこない。この選択肢が出さえすれば OKらしく、welcome メッセージが出て、あとはすんなり進んだ。それ以外の dgx os installation などというそれっぽい選択肢を選んでもすべて CUI インストーラーしか立ち上がらず、途中でエラーが出て失敗する。

CreateUSBKey.cmd というスクリプトもそのままではなぜか動かず、中に書いてあるコマンドを直打ちして実行したら動いた。すべてがグダグダだった。

最初は rufus で isoモードで書き込んだのがいかんのだろうと思ったが dd モードで書き込んでもだめ。Dellのサイトにかかれているとおりに ubuntu で dd でイメージを流し込んだりいろいろ試したがすべてだめだった。

wifi ルーターかなにかで windows のノートPC と LAN 共有し、Nvidia Sync でつないで使うというやり方しか今ところ想定されていないような気がする。

MSI や Dell などが OEM で提供しているようだが、とにかく情報が少なすぎて、ユーザーも少なすぎて、今慌てて手を出すのはかなり地雷な気がするが、まあ私はなんとかなったのでもういいやって思ってる。

それでこれからなんだけど、まったく右も左もわからないので、LM Studio 入れようかと思ったら arm64 では動かないらしく、Docker 環境で ollama + Open Web UI で使うのがどうも標準らしいんだが、Docker のありがたみもよくわからんので、とりあえず ollama 入れて、gpt-oss:120b をコマンドラインでガリガリ使ってみようと思っている。いろんな流儀がありすぎてもうわけわからん。いろいろ教えこんで授業の AI アシスタント代わりに使えると良いのだが、たぶんそこまで行くのはずっと先だと思う。

めちゃめちゃ小さくて軽いので、家に持ち帰っていじろうかという気でいたのだが、今のところその気は失せた。すぐにどうこうなるというものではないし、家では家ですることがあるから大学に置きっぱなしにして、とりあえず学生とかに使わせるのでなく、自分だけでいろいろいじってみる。

有線LANでつないで固定IPアドレスで使えるともう少しやりようがあるんだけど、なぜかうまくいかない(イーサーのケーブル挿しても反応しない。多分OS初期設定の時に有線LANをつなぎっぱなしにしなきゃいけないんだが、学内ネットワークのproxy設定しないと外につながらなくてそこで詰む。ubuntu のインストールと同じ。仕方なく wifiルーターで無線LANにつないで初期設定すると有線は使えなくなる。有線か無線が排他的にしか使えない設定ではなかろうか。普通のubuntuだとあとから有線固定IP接続すれば使えるんだがなー)。無線LANで学内ネットワークにつないで ProxyPass で ubuntu の apache から見えるようにすることもできるんだけど、まずはスタンドアローンで使ってみるかなーって感じ。

ともかく現状、ネットで調べようとしても情報がまったく出てこないので、のんびりやるしかない。

google classroom の gem を ai assistant として使えるかどうか

Gemini との会話

あなたのプロンプト

google classroom の gem の使い方がよくわかりません。ai assistant として使うことは可能でしょうか。

Gemini の回答

Google Classroom における Gemini(旧称 Bard を含む AI 機能)は、単なるチャットツールを超えて、教師や生徒を強力にサポートする 「AI アシスタント」 として統合されています。

結論から申し上げますと、Gemini は 授業準備の自動化、学習支援、フィードバックの作成 など、多岐にわたる用途でアシスタントとして活用可能です。

具体的にどのように使えるのか、主な機能とメリットを整理しました。


1. 教師向け:授業準備の強力なパートナー

教師は Classroom 内の専用メニューから Gemini を呼び出し、以下のようなタスクを数秒で実行できます。

  • 指導案(レッスンプラン)の作成: 学年や主題を入力するだけで、学習目標やタイムラインのドラフトを作成します。
  • テスト・クイズの自動生成: 授業内容に基づいた理解度チェック用の問題を生成し、Google フォームへ書き出すことも可能です。
  • 教材のレベル調整: 難しい文章を特定の読解レベル(例:小学生向け)に書き換えたり、要約したりできます。
  • ルーブリック(評価指標)の作成: 課題の採点基準を AI と対話しながら素早く構築できます。

2. 生徒向け:パーソナライズされた学習ガイド

18歳以上の生徒(高等教育機関など)は、学習を深めるためのアシスタントとして Gemini を利用できます。

  • ガイド付き学習(Guided Learning): 単に答えを教えるのではなく、ヒントやステップを示すことで、生徒自身が自力で正解にたどり着けるよう促します。
  • NotebookLM との連携: クラスの資料をアップロードし、それに基づいたポッドキャスト風の音声要約や、対話型の図解を作成して復習に役立てられます。
  • 試験対策: Gemini Canvas を使い、自分専用の練習問題やフラッシュカード(暗記カード)を自動生成できます。

3. 「Gem」を使ったカスタマイズ(AI エージェント)

特定の役割を持たせた AI 「Gem」 を作成し、Classroom 内で共有することも可能です。

Gem の種類役割・活用例
学習パートナー生徒の質問に対し、ソクラテス式問答で考えさせる。
クイズ・マスター特定のトピックについて、習熟度に合わせて問題を出してくれる。
ブレスト・パートナープロジェクトのアイデア出しをサポートする。
現実世界コネクター学んでいることが社会でどう役立つか、具体例を提示する。

導入にあたっての注意点

  • 対象ユーザー: 現在、多くの機能は 18 歳以上 のユーザーを対象としています。
  • 言語設定: 一部の最新機能は英語先行でロールアウトされることがありますが、基本的な対話やコンテンツ作成は日本語でも十分可能です。
  • 管理設定: 学校の管理者が Google 管理コンソールで Gemini の使用を有効にする必要があります。

[!TIP] Google Classroom の左側メニューや課題作成画面にある 「Gemini」アイコン、または classroom.google.com/ai から直接これらの機能を試すことができます。

まずは、授業の「導入のアイデア(Hook)」や「小テストの作成」など、小さなタスクから AI に任せてみてはいかがでしょうか?

具体的なプロンプト(指示文)の書き方や、特定の教科での活用事例について詳しく知りたいものはありますか?

あなたのプロンプト

unreal engine を使ったゲーム制作の演習を行おうと思っています。 gem に学生からの質問に答えてもらうことはできますか。その答えを教員が確認し必要があれば修正することはできますか。

Gemini の回答

Unreal Engine(UE)のような専門性の高い実習において、Gemini のカスタム機能である 「Gem」 を活用することは非常に効果的です。

結論から申し上げますと、「UE 専門の学習アシスタント Gem」 を作成して学生に配布し、そのやり取りを教員が確認・フォローするという運用が可能です。

具体的なステップと活用イメージを解説します。


1. Unreal Engine 専用の「Gem」を作成・配布する

まず、教員が Unreal Engine の知識を詰め込んだ専用の AI アシスタント(Gem)を作成します。

  • 役割(指示)の設定: 「あなたは Unreal Engine 5 の専門講師です。学生からの C++ や Blueprint、ライティング、最適化に関する質問に、ヒントを出しながら答えてください。すぐに正解のコードを出すのではなく、考え方を導くようにしてください」といった指示を与えます。
  • 知識(ナレッジ)の追加: 独自の講義資料(PDF)や、プロジェクトのコーディング規約などをアップロードしておくと、それに基づいた回答ができるようになります。
  • 配布: 作成した Gem は Google Classroom の「授業」タブから、課題や資料として学生に共有できます。

2. 教員による「確認と修正」の運用方法

現在の Google Classroom の仕様では、AI が出力した回答をリアルタイムで直接書き換える機能はありませんが、以下の方法で**「教員による介入と品質管理」**が可能です。

A. 学生の利用状況の確認

Google Classroom の管理画面から、どの学生が Gem を利用したか(開いたか)を確認できます。また、学生に「Gem との対話履歴のリンク」や「スクリーンショット」を課題として提出させることで、AI がどのようなアドバイスをしたかを後からチェックできます。

B. 誤情報の修正とフォロー(重要)

AI は時として Unreal Engine の古いバージョン(UE4)の情報を出したり、誤った Blueprint ノードを提案したりすることがあります。

  • 全体フィードバック: 学生が提出したログを見て、「Gem がこう言っていたが、最新の UE5.x ではこの手法が推奨される」といった補足をクラス全体に行う。
  • 個別指導: 特定の学生が AI の誤情報で詰まっている場合、Classroom のコメント機能で直接正しい指示を出す。

3. 演習での具体的なメリット

Unreal Engine の実習では「コンパイルエラーが取れない」「ライティングが真っ暗」といった個別トラブルが多発し、教員一人では対応が追いつかないことがよくあります。

  • 1次対応を Gem に任せる: 「エラーログを Gem に貼って原因を聞いてみて」と指示することで、単純なミスによる足止めを減らせます。
  • 教員は高度な指導に集中: 教員は、AI では回答が難しい「ゲームバランスの調整」や「クリエイティブな表現」の指導に時間を使えるようになります。

注意事項

  • アカウント制限: 学生が Gem を利用するには、学校側が Google Workspace for Education の設定で Gemini および Gem の共有を有効にしている必要があります。
  • 年齢制限: 現在、教育向け Gemini は原則として 18 歳以上 のユーザーが対象です。

次は、学生に配布するための「Unreal Engine 指導用プロンプト(指示文)」のサンプルを作成してみましょうか?

あなたのプロンプト

授業の教材としてはおもに youtube 動画資料を使う予定です。gem は動画の内容を理解できるでしょうか。

Gemini の回答

結論から申し上げますと、Gemini(特に Google Classroom と連携したもの)は YouTube 動画の内容を非常に高い精度で理解し、学習支援に活用することが可能です。

教員が YouTube を教材として使う際、Gemini をアシスタントとして使うと、以下のような具体的な運用ができます。

1. YouTube 動画の内容をベースにした回答

Gemini に YouTube の URL を読み込ませる(またはプロンプトに含める)ことで、AI はその動画の書き起こしデータや視覚情報を解析します。

  • 学生の質問への回答: 「この動画の 5 分あたりで説明されていた『Blueprints の変数設定』について、もっと詳しく教えて」といった質問に、動画の内容に基づいて答えることができます。
  • 要約の作成: 長いチュートリアル動画の重要なポイントを箇条書きでまとめさせ、学生の予習・復習資料にできます。

2. Google Classroom での具体的な活用ステップ

YouTube 動画を教材にする場合、以下のような流れで Gem を作成・運用するのがスムーズです。

  1. 「教材参照用 Gem」の作成: Gem の指示文(System Prompt)に、「提供する YouTube 動画の内容を最優先して解説してください」と記述します。
  2. リンクの提供: Google Classroom の課題や資料として YouTube リンクを投稿する際、一緒にその動画を解析させるための Gem のリンクも共有します。
  3. 理解度チェックの自動生成: 教員が Gemini に対し、「この YouTube 動画の内容に基づいて、5 問の選択式クイズを作って」と指示すれば、動画に基づいた確認テストを即座に作成できます。

3. 注意点と「教員による確認」のコツ

動画の内容を理解できるとはいえ、Unreal Engine のようなテクニカルな分野では以下の点に注意が必要です。

  • バージョン情報の乖離: YouTube 動画が古いバージョン(例:UE4)の場合、Gemini も古い情報を正解として扱ってしまうことがあります。
    • 対策: 「この動画は UE4 ですが、現在の演習は UE5 なので、差異がある場合は補足してください」と Gem に指示しておくと精度が上がります。
  • ハルシネーション(もっともらしい嘘): 動画で言及されていないことを、一般的な知識と混同して答えることがあります。
    • 対策: 前述したように、学生に「Gem とのやり取り」を Classroom のコメント欄やドキュメントで報告させることで、教員が「ここは動画の説明と違うよ」と修正を入れる運用が望ましいです。

4. おすすめの運用スタイル

YouTube 動画をメイン教材にするなら、**「動画を視聴しながら、わからない用語や操作を Gem にリアルタイムで質問させる」**という形式が、学生の自学自習を最も促進します。

教員の方は、最初にその YouTube 動画の URL を Gemini に読み込ませてみて、**「この動画から学生が躓きそうなポイントを 3 つ挙げて」**と聞いてみてください。それに対する回答の正確さを見ることで、Gemini の理解度を事前にテストすることができます。

あなたのプロンプト

学生からの質問を集約して FAQ のようなものを作ることはできますか。

Gemini の回答

はい、学生からの質問を集約してFAQを作成することは、GeminiとGoogle Classroomを組み合わせることで非常に効率的に行えます。

具体的な手順と、おすすめの管理方法を提案します。

1. Gemini を使った FAQ の自動生成

学生からの質問(Classroomのコメントや、Gemとの対話ログなど)をGeminiに読み込ませることで、以下の作業を自動化できます。

  • 質問の分類と整理: 「Blueprint関連」「ライティング関連」「エラー対処」のように、散らばった質問をカテゴリー別に整理します。
  • 回答のドラフト作成: 過去の回答やYouTube教材の内容に基づいて、FAQ形式(Q&A)の文章を生成します。
  • 「よくある質問」の抽出: 複数の学生が躓いているポイントを自動的に特定し、優先的にFAQに載せるべき項目を提案させることができます。

2. Google Classroom での FAQ 公布・共有

整理したFAQは、以下の形で学生に提供するのが一般的です。

  • Classroom の「資料」として投稿: 「UE5演習 FAQ集」という名前で資料を作成し、いつでも参照できるようにします。
  • 専用の Gem を更新する: FAQの内容を Gem の「知識(ナレッジ)」として追加(アップロード)することで、次から学生が Gem に質問した際に、最新のFAQに基づいたより正確な回答を返せるようになります。

3. 教員による運用イメージ

例えば、1週間の演習が終わった後に、以下の操作を行うのがスムーズです。

  1. 学生から出た質問や、Gem の利用ログを Gemini に貼り付ける。
  2. **「今週の質問から、来週の学生が役立ちそうな FAQ を 5 つ作って」**と指示する。
  3. 生成された内容を教員が確認・修正し、Classroom にアップロードする。

このように、学生のリアルな躓きポイントを蓄積していくことで、回を追うごとに強力な「自学自習用アシスタント」が出来上がっていきます。

まずは、学生が躓きそうな項目をいくつかリストアップした「FAQ候補リスト」を作成しました。これをもとに詳細な解説を作成していくことも可能です。

Google Keep UE5演習FAQ候補(学生の質問集約)Blueprintのコンパイルエラー:変数の型不一致についてライティングが真っ暗になる原因とSky Lightの設定スタティックメッシュのコリジョン設定方法GitHub連携時のプラグイン除外設定パッケージ化(ビルド)時のエラー対処法

あなたのプロンプト

gem と学生の対話ログを教員が確認する方法を教えてください。

Gemini の回答

Google Classroom や Gemini の標準機能において、学生と AI(Gem)のやり取りを教員がリアルタイムで自動的に監視する専用画面は、現在のところ存在しません。 これはプライバシー保護の観点によるものです。

そのため、演習としてログを確認し、教員がフィードバックを行うには、**「学生側から共有・提出してもらう」**という運用フローを構築するのが一般的です。以下の3つの現実的な方法をご紹介します。


1. 対話履歴の「リンク共有」を課題として提出させる

Gemini には、特定のチャット履歴を公開リンクとして書き出す機能があります。

  • 学生側の操作: Gemini との対話が終わったら、画面下の「共有」アイコン(上向き矢印)をクリックし、「公開リンクを作成」を選択します。
  • 提出方法: 生成された URL を Google Classroom の課題の「添付」として提出させます。
  • 教員のメリット: 教員はそのリンクをクリックするだけで、学生がどのような質問をし、AI がどう答えたかをすべて閲覧できます。

2. Gem の回答を Google ドキュメントにエクスポートさせる

Gemini の回答には「Google ドキュメントにエクスポート」というボタンがあります。

  • 学生側の操作: 重要なアドバイスや解決策が出た際、その回答をドキュメントに書き出します。
  • 提出方法: そのドキュメントを Google Classroom の課題として提出します。
  • 教員のメリット: 教員は提出されたドキュメントに対し、「コメント機能」を使って直接修正や補足を書き込めます。「ここは UE4 の古いノードだね、UE5 ではこっちを使おう」といった具体的な赤入れが可能です。

3. 「リフレクション(振り返り)課題」として集約する

これが FAQ 作成に最も役立つ方法です。

  • 運用の流れ: 演習の最後に、「AI に聞いたことと、その結果(解決したか、間違っていたか)」を Google フォームや Classroom の質問機能で回答させます。
  • FAQ への活用: 教員は集まった回答をスプレッドシートで一覧化し、Gemini に読み込ませて「共通の悩み」を抽出します。

教員による「確認と修正」のサイクル例

教員が介在するワークフローを組むなら、以下のような形が理想的です。

ステップアクション
1. 質問学生が Unreal Engine のエラーを Gem に相談する。
2. 提出学生が「解決までのログ(リンク)」を Classroom に投稿する。
3. 確認教員がログを巡回。AI が間違った指示をしているものを発見。
4. 修正Classroom の返信機能で「Gem の回答 2 つ目は無視して、このドキュメントを参照して」と介入。
5. 共有似たミスが多い場合、そのログを元に FAQ を作成してクラス全体に配布。

管理者設定の確認

この運用を行うには、学校の Google 管理者が 「Gemini のリンク共有機能」 を有効にしている必要があります。

注意点: 学生が 18 歳未満の場合、学校用アカウントでの Gemini 利用には保護者の同意や管理者による特別な許可設定が必要になるケースがあるため、事前に IT 担当部署へ確認することをお勧めします。

まずは、学生に「対話ログのリンクを提出してください」と指示するための「課題テンプレート(説明文)」を作成してみますか?

あなたのプロンプト

たとえば学生が unreal editor の blueprint のスクリーンショットを撮ってそれを gem にみせたら何が間違っているのか gem は答えられますか。

Gemini の回答

はい、Gemini は画像認識能力(マルチモーダル機能)を持っているため、Blueprint のスクリーンショットから間違いを指摘することは可能です。

Unreal Engine の演習において、これは非常に強力なサポートになります。具体的にどのようなことができるのか、また活用のコツをまとめました。

1. Gemini が Blueprint の画像から判別できること

学生がスクリーンショットをアップロードして質問すると、Gemini は以下のような点を確認できます。

  • 接続ミス(断線): ノードの実行ピン(白い矢印)やデータピンが正しくつながっていない箇所。
  • 型の不一致: 例えば「Float(浮動小数点)」を入れるべき場所に「Integer(整数)」をつなごうとしてエラーが出ている状態など。
  • ノードの選択ミス: 似た名前の別のノード(例:Get Player CharacterGet Player Controller)を間違えて使っているケース。
  • 変数設定の不備: 変数の詳細パネル(Details)が写っていれば、デフォルト値や「インスタンス編集可能」などの設定ミスも指摘できます。

2. 精度を高めるための「学生への指示」

画像だけをポイっと投げるよりも、以下のような情報を添えて質問するように学生に伝えると、回答の正確性が格段に上がります。

  • 「何がしたいのか」を併記する: 「キャラクターをジャンプさせたいのですが、この Blueprint で動かないのはなぜですか?」のように目的を書く。
  • エラーメッセージを添える: コンパイルエラーが出ている場合は、そのメッセージもテキストでコピーするか、画像に含める。
  • 全体が見えるように撮る: ノードの一部だけでなく、全体の流れが見えるようにスクリーンショットを撮る。

3. 教員が「確認・修正」する際のポイント

前述の通り、教員がこのやり取りを確認するには、学生に 「画像付きの対話ログ(リンク)」 または 「画像と AI の回答をまとめたドキュメント」 を提出させる必要があります。

教員が確認する際は、以下の点に注目してください。

  • AI の誤診チェック: Gemini が「このノードは存在しません」と言っても、実は最新の UE5 で追加されたノードである場合があります。その際は「AI が間違っているよ、これは最新の仕様だよ」と学生に伝えてください。
  • FAQ への転用: 「多くの学生が同じノードの接続ミス画像をアップしている」ことがわかれば、その画像を FAQ に載せて「ここが間違いやすいポイントです」とクラス全体に周知できます。

結論

「Blueprint の画像を見せて相談する」という使い方は、UE 演習において最も推奨される Gemini の活用法の一つです。

教員側の負担を減らすためにも、「まずは Gem に画像を見せて、解決しなければ先生にログを見せて質問してね」というルールにすると、学生の自己解決能力も高まります。

万葉集の歌をすべてAIに学習させればAIは万葉語で歌が詠めるようになりますか。

gemini3 に質問

たとえば万葉集の歌をすべてAIに学習させればAIは万葉語で歌が詠めるようになりますか。

結論から申し上げますと、技術的には十分に可能であり、現在のAI(特に大規模言語モデル)はすでにそのレベルに到達しつつあります。

万葉集の全4,500首以上を学習させることで、AIは当時の語彙、文法、そして「万葉びと」特有の感性やリズムをシミュレートできるようになります。

しかし、単に「言葉を並べる」ことと、「万葉の心で詠む」ことの間には、AIならではの面白さと限界があります。その仕組みを整理して解説します。


1. AIが「万葉語」を習得する仕組み

AIは統計的なパターン学習によって、以下のような要素を身につけます。

  • 語彙と文法: 現代では使われない助詞や助動詞(「〜けむ」「〜らむ」など)の使い方、万葉集特有の古い言葉選びを学習します。
  • 枕詞(まくらことば)の法則: 「あかねさす」が「紫」や「日」にかかるといった、特定の言葉の結びつきを確率的に理解します。
  • 五七五七七のリズム: 短歌の定型を、単なる文字数ではなく、心地よいリズムのパターンとして把握します。

2. 万葉集「だけ」を学習させることの効果

もし他の現代的な知識を一切与えず、万葉集のデータのみを特化して学習させた場合、AIは**「驚くほど純度の高い万葉風の歌」**を詠むようになるでしょう。

  • メリット: 現代語が混ざらないため、タイムスリップしたような古風な表現が可能です。
  • デメリット: 万葉集に登場しない概念(例:現代の「スマートフォン」や「鉄道」など)を詠もうとすると、語彙がないためフリーズするか、強引に当時の言葉(「文を運ぶ板」など)に置き換えようとします。

3. AIが詠む歌の「限界」と「可能性」

AIは非常に精巧な「万葉風の歌」を作れますが、人間と決定的に違う点が一つあります。

AIは「実体験」を持っていない

万葉歌人の多くは、実際に見た風景や、誰かを想う切実な感情を歌に込めました。AIは「『月』という言葉の次には『照らす』という言葉が来やすい」という確率計算で歌を作ります。

しかし、逆に人間には思いつかないような、万葉語の斬新な組み合わせ(言葉のコラージュ)を生み出すこともあります。これは、古典文学の新しい解釈や創作のヒントとして非常に有用です。


万葉風AIの作例(イメージ)

もし現代の風景を万葉語で詠ませたら、こんな歌を出すかもしれません。

「令和の 街のともし火 あかねさす 昼にも勝り 夜を照らすかも」 (令和の街の明かりは、日の光よりも明るく、夜を照らしていることよ)

このように、形式と雰囲気は完璧に「万葉調」にすることが可能です。


次の一歩として、もしよろしければ私が今、万葉集のスタイルであなたに一首詠んでみましょうか? 何かお題(好きなものや今の気分など)を教えていただければ、万葉語で表現してみます。

unreal から voicevox をしゃべらせる2

webrick で rubyスクリプトで rest api サーバーを立ち上げて、voicevox にアクセスできるようにした(powershell で rest api サーバーを書いていたがそれをやめて ruby だけで書いた)。voicevox2.rb

require 'net/http'
require 'uri'
require 'json'
require 'webrick'

def speak(text, speaker)
  puts text, speaker
  uri = URI.parse("http://localhost:50021/audio_query")
  uri.query = URI.encode_www_form({ "text" => text, "speaker" => speaker })
  headers = {
    "Content-Type" => "application/json",
    "User-Agent" => "vox-client:0.1",
  }
  response = Net::HTTP.post(uri, "", headers)
  case response
  when Net::HTTPSuccess
    result = JSON.parse(response.body)
  else
    puts "audio query error: #{response}"
  end
  uri = URI.parse("http://localhost:50021/synthesis")
  uri.query = URI.encode_www_form({ "speaker" => speaker })
  response = Net::HTTP.post(uri, response.body, headers)
  if response.code == '200'
    File.open("output#{speaker}.wav", "wb") do |f|
      f.write(response.body)
    end
  else
    puts "synthesis response error"
  end
end

# サーバーの設定
server = WEBrick::HTTPServer.new(
  Port: 6001,
  BindAddress: '0.0.0.0'
)

# POST /talk というパスへの処理を定義
server.mount_proc '/talk' do |req, res|
  # POSTメソッド以外は受け付けない
  if req.request_method == 'POST'
    begin
      # 1. リクエストボディを読み込んでJSONパース
      data = JSON.parse(req.body)
      
      # 2. "message" キーを取り出して表示
      message = data["message"]
      puts "[#{Time.now}] 受信メッセージ: #{message}"
      speak(message, 1)
      # powershell で output*.wav を鳴らす
      system("powershell -ExecutionPolicy Bypass -command .\\sound1.ps1")
      # 3. ステータスコード 204 (No Content) を設定
      res.status = 204
    rescue => e
      puts "エラーが発生しました: #{e.message}"
      res.status = 400 # 不正なリクエスト
    end
  else
    res.status = 405 # Method Not Allowed
  end
end

# Ctrl+C で安全に停止するための設定
trap('INT') { server.shutdown }

# サーバー起動
puts "Server started on http://localhost:6001"
server.start

ruby (もしくは python) でできることは powershell でやる必要は無いなと思う。powershell でしかできないこと(windows固有の、wavを再生するとか)だけを powershell に投げれば良いのではないか。いや、それが当たり前なんだろうけど。

unreal から voicevox をしゃべらせる

voicevox を立ち上げると rest api サーバー(localhost:50021)が常駐するので、そこへ文字列と話者(ずんだもんとか四国めたんなど)を渡せばその文字列をしゃべらせることができる。unreal から voicevox の rest api サーバーへ varest プラグインを通じて直接アクセスすれば良さそうに思えるのだが、その後 voicevox が生成した wav ファイルを鳴らすという処理も行う必要がある。この部分のこまごまとした作業を blueprint で書くのは難しい。wavファイルをwindowsで再生するというそれだけの単純作業にしても、powershell から呼ぶのが一番安全確実である。

そこで powershell で rest api サーバーを立てて、unreal はそのサーバーにいったんデータを送り、そこから ruby なり python なり別の powershell なりのスクリプトを呼び出して、voicevox の rest api サーバーを間接的に呼び出したり wavファイルを再生するのが一番よかろうということになった。

私は ruby が好きなので、できるだけ ruby で書けるところは ruby で書きたいと思った。python は結局使わずに済んだ。

次の ruby スクリプトはコマンドラインの引数に文字列を渡して voicevox サーバーを呼び出し最終的に powershell スクリプトで voicevox が生成した wavファイルを再生するというものである。

voicevox1.rb

require 'net/http'
require 'uri'
require 'json'

def speak(text, speaker)
  puts text, speaker
  uri = URI.parse("http://localhost:50021/audio_query")
  uri.query = URI.encode_www_form({ "text" => text, "speaker" => speaker })
  headers = {
    "Content-Type" => "application/json",
    "User-Agent" => "vox-client:0.1",
  }
  response = Net::HTTP.post(uri, "", headers)
  case response
  when Net::HTTPSuccess
    result = JSON.parse(response.body)
  else
    puts "audio query error: #{response}"
  end
  uri = URI.parse("http://localhost:50021/synthesis")
  uri.query = URI.encode_www_form({ "speaker" => speaker })
  response = Net::HTTP.post(uri, response.body, headers)
  if response.code == '200'
    File.open("output#{speaker}.wav", "wb") do |f|
      f.write(response.body)
    end
  else
    puts "synthesis response error"
  end
end

query_text = ARGV[0]
speak(query_text, 1)
# powershell で output*.wav を鳴らす
system("powershell -ExecutionPolicy Bypass -command .\\sound1.ps1")

そして次の powershell スクリプト sraserv02.ps1 は unreal から呼び出す rest api サーバーであり、unreal から渡された文字列をその都度 ruby スクリプトに渡すというだけのものである。じゃあ最初から rest api サーバーも ruby で書いてしまえばよかったんじゃないのと思うが、もう動いてしまったのでとりあえず今のところはこれでよしとする。

$port = 6001
$prefix = "http://localhost:$port/"
$text_encoding = [System.Text.Encoding]::UTF8

$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add($prefix)
$listener.Start()

Write-Host "REST API Server listening on $prefix"
Write-Host "Press Ctrl+C to stop."

try {
  while ($true) {
    $context  = $listener.GetContext()
    $request  = $context.Request
    $response = $context.Response

    $path = $request.Url.AbsolutePath
    $method = $request.HttpMethod

    Write-Host "$method $path"

    $result = $null
    $status = 200

    if ($method -eq "POST" -and $path -eq "/talk") {
      # POST /talk
      # {"message": "string to talk" }
      $reader = New-Object IO.StreamReader($request.InputStream, $text_encoding)
      $body = $reader.ReadToEnd()
      $reader.Close()
      $result = $body | ConvertFrom-Json
    } else {
      $status = 404
      $result = @{ error = "Not found" }
    }
        
    Write-Host $result.message
    # ruby で voicevox に言葉を送る
    ruby voicevox1.rb $result.message
  }
}
finally {
  $listener.Stop()
  $listener.Close()
}

で、最後はただ単にwavファイルを再生するだけの powershell スクリプト sound1.ps1。

(New-Object Media.SoundPlayer "output1.wav").PlaySync()

pardon は unreal 側からまず ollama に質問してその答えを reply に渡す。

reply は ruby スクリプトで書いた localhost:6001 の rest api サーバーにアクセスして voicevox を喋らせる。

MediaWiki と wordpress に広告を入れる

MediaWiki はパソコンとスマホで画面サイズが変わるとレイアウトがバシバシ変わるので、広告を入れにくい。広告を入れる場所はだいたい限られてくる。

どこに入れるかは結局テーマを直接ガリガリいじるのが良さそうだ。Timeless というテーマは非常にシンプルで、includes/TimelessTemplate.php をいじればだいたいできる。phpがわかってれば全然むずかしくない。

wordpress はやはり広告を入れるのにはよく考えて設計されている。blockベースになったのも広告やらさまざまなプラグインやガジェットを入れやすくするためだろう。とりあえず wordpress を使っておくのが安心ではあるが、編集のしやすさでは Mediawiki のほうがずっと優れている。

あいかわらず英語ページへのアクセスはほとんどない。多言語化プラグインにも全然ありがたみがない。所詮英語で書く著者は世界にいくらでもいるということか。どうすりゃいいんだろうね。

WAF (Web Application Firewall)

google Adsense や楽天アフィリエイトの javascript をウィジェットのカスタムHTMLに入れようとすると、入ったりエラーが出たりする。エラーというのがただしい JSONレスポンスではないとかそんなやつ。サイトによって出たり出なかったりするので、テーマを入れ替えたりとかいろいろやってみたのだが、結局サーバーの WAF というものの設定を切ればサクッと入るのだった。サーバー(ドメイン)ごとに WAF を設定してたりしてなかったりしたせいで動作が異なっていただけだった。

wordpress のテーマの sidebar.php とか footer.php に直接 javascript で書き込めば動いていたので、キャッシュか何かが悪さしてるのかなーと思っていたら違った。

ていうか個人で AdSense とか楽天アフィリエイトとかやってる人いるのかな。大変すぎじゃね?

ていうか今の楽天の広告ほとんど米じゃね(笑)。