たいちょーの雑記

ぼくが3日に一度くらい雑記をかくところ

AWS Summit Japan 2026 参加記録

参加記録

いきました

Day 1

十分に早い時間にいったつもりだったがめちゃくちゃ並んでいた。指定席は取れなかった。 去年も1日目は取れなかったらしい(わすれてた)

立ち見の基調講演は途中で離脱していくつかブースを見て回ることにした。セッションリストから見るにわかっていたことだがAI絡みが多かった。まぁ流行りだもんな~。 しかしロボを制御する系はほとんど知見が無かったのでかなり面白かった。あとはどんなチューニングをしているかとかも参考になる話が多かった

去年より認定試験の数を増やしたのでステッカーも増えてうれしかった

Day 2

この日は指定席につけた。去年もそうだったらしい。座れたのでクッションもゲットできてよかった。 でも腹が痛くなって途中で離脱した。トイレがやたら混むので困る

セッションではアーキテクチャ道場が良かった。今年も楽しみにしていた。 ただ今回はやや早口だったような気もする。運用で解くと構造で解くという言葉が印象に残っていて、また今度意識できればいいなという感じ

おわり

なんだかんだブースでディスカッションするのが楽しいですね。JAWSとかに行けばこういう機会増やせるかもとか思っている。
そろそろ認定全冠もしたいね。

A.I VOICE Editor を操作するMCPサーバーを書いてみる

書いてみよう。

モチベ

良い感じな音声をAIに生成してもらいたい…。いまどき普通にできます。
でもA.I VOICEを使った合成はさすがにできないと思った(調べてない)のでMCPサーバーをC#で書いてみます

使うのは A.I VOICE Editor が公開している API。リファレンスは以下のサイトで確認できます。

aivoice.jp

A.I VOICE Editor がインストールされていれば、インストールディレクトリ以下の AI.Talk.Editor.Api.dll を使うことでAPIが使えます。 ちなみに C# で書く場合はターゲットフレームワーク .NET Framework でなければなりません

書いたもの

実装したものはこちら。一旦stdioのみサポートしています

github.com

clone後以下のような感じでmcpを設定してやれば、生成したテキストをAPI経由で合成できます

$ cd ./path/to/AI.Voice.Editor.McpServer
$ dotnet build -c Release -p:Platform=x64
$ claude mcp add --transport stdio ai-voice-editor-tool -- /path/to/bin/x64/Release/net481/AI.Voice.Editor.McpServer.exe

できることは以下の通り。APIで提供されている機能の半分ぐらいは実装しています

  • 再生
  • 合成して保存
  • テキストモードの話者を設定
  • テキストモードのテキストを設定
  • リスト形式の編集
  • 話者一覧の取得

例:

具体的な実装の話

ModelContextProtocolのC# SDKを使っています。ILogger<T>とかはいつもの感じでDIで取得できるので楽でした。

www.nuget.org

後はAPIリファレンスとにらめっこし、愚直にToolを生やすだけでした。
動的にロードした後もいい感じに型を効かせたいので、自前でAPIライブラリが提供するインターフェースと互換のあるインターフェースを生やしました。あとはそれを糊付けするクラスが生えてるぐらいで、それ以外は難しいことはしていません。ところで、このような糊付けをするクラスを生やす実装パターンをAdapterパターンというらしいですね*1。知りませんでした。

そのうちSSE対応したいなという気持ちです。

おわり

これで適当に投げつけたURLから要約を作ってボイロに喋ってもらえるってわけです。うれしいですね

最近はVoicePeakの面々も気になっており、割と機運って感じです。かりせん可愛いよね。

xUnitの`TheoryData<T>` を使う

xUnitのパラメーターライズドテストでも型をいい感じにしたい

いまさらなめちゃくちゃ備忘録

xUnitでパラメーターライズドテスト(テーブル駆動テスト)を書くときは [Theory] アトリビュート[InlineData], [MemberData], [ClassData] を使って書ける。以下は [InlineData]を書くパターン。

public class AdderTest
{
    [Theory]
    [InlineData(3, 4, 7)]
    [InlineData(-2, 2, 0)]
    public void TestAdd(int a, int b, int expected)
    {
        var adder = new Adder();
        var result = adder.Add(a, b);
        Assert.Equal(expected, result);
    }
}

しかしながらちょっと計算で入力などを作りたくなると [InlineData] ではできなくなる

public class AdderTest
{
    [Theory]
    [InlineData(Math.Abs(3), 4, 7)] // CS0182
    public void TestAdd(int a, int b, int expected)
    {
        var adder = new Adder();
        var result = adder.Add(a, b);
        Assert.Equal(expected, result);
    }
}

こういうときは [MemberData][ClassData]を使ってやればよい。インターネットを検索すると以下のような例がある。

public class AdderTest
{
    [Theory]
    [MemberData(nameof(TestAdd2_Data))]
    public void TestAdd(int a, int b, int expected)
    {
        var adder = new Adder();
        var result = adder.Add(a, b);
        Assert.Equal(expected, result);
    }

    public static IEnumerable<object[]> TestAdd_Data()
    {
        yield return new object[] { 5, 5, 10 };
        yield return new object[] { -3, -7, -10 };
        yield return new object[] { 10, 0, 10 };
    }
}

ただこれ TestAdd2_DataシグネチャIEnumerable<object[]> なので yield return する object[]int 以外が入っていてもコンパイルエラーにはならず、実行時まで判明しない。せっかく型があるのにもったいない…。

この件に関していろんな人が似たような課題を感じていて、ggるといろいろ出てくる。それらを見たうえで個人的に書くときは以下のようにして何とかしていた。

public class AdderTest
{
    [Theory]
    [MemberData(nameof(TestAdd2_Data))]
    public void TestAdd2(int a, int b, int expected)
    {
        var adder = new Adder();
        var result = adder.Add(a, b);
        Assert.Equal(expected, result);
    }

    public static IEnumerable<object[]> TestAdd2_Data()
    {
      return new List<(int, int, int)> // List<(int,int,int)> なので要素に間違った型を入れるとコンパイルエラーになってうれしい
      {
        (3, 5, 8),
        (-3, -6, -9),
        (0, 5, 5),
        (1.1, 1, 1) // CS1503
      }.Select(t => new object[] { t.Item1, t.Item2, t.Item3 });
    }
}

うーん。これでもいいけどなんかスッキリしない気持ち。

TheoryData<T>

api.xunit.net

TheoryData<T>はこういう時に使える便利なもの。これ一体いつからあったんだ…。*1

public class AdderTest
{
    [Theory]
    [MemberData(nameof(TestAdd_Data))]
    public void Test_Add(int a, int b, int expected)
    {
        var adder = new Adder();
        var result = adder.Add(a, b);
        Assert.Equal(expected, result);
    }

    public static TheoryData<int, int, int> TestAdd_Data() => new() // すごいすっきり
        {
            { 1, 2, 3 },
            { -1, -1, -2 },
            { 0, 0, 0 },
        };
}

TheoryData<T> であればOKで、以下のように TheoryData<T>を継承した型でも良い

public class AdderTest
{
    [Theory]
    [ClassData(typeof(TestAdd_DataClass))]
    public void Test_Add(int a, int b, int expected)
    {
        var adder = new Adder();
        var result = adder.Add(a, b);
        Assert.Equal(expected, result);
    }

    class TestAdd_DataClass : TheoryData<int, int, int>
    {
        public TestAdd_DataClass()
        {
            Add(10, 20, 30);
            Add(-5, 5, 0);
            Add(100, 200, 300);
        }
    }
}

良さそう。

まとめ

今更知った TheoryData<T> について備忘録を書いた。これで楽ができそう

*1:xUnitのリポジトリを見ていたらどうやら2014年時点で既にあったっぽい…

github.com

AWS Summit Japan 2025 参加記

6/25,6/26の両日とも行ってきました。

Day 1

割と早めに行ったつもりだったけど基調講演の指定席は座れず。クッションは貰えたから良いかという感じ サテライトは字幕が出てて面白かった。一部区間で止まってたのでちょっと困った

基調講演のあとはセッションをいくつか入れていたので聞きに行った。最近は育成に関する話に割と興味があったので、Villageで話を聞こうと思ってたんだけど認定試験系はなかった?見つけられなかっただけかも。 それ以外の話もたくさんできたので良かった。

普段運用やら監視やらをやってるせいで、そういうツールをつくってるところのブースはふむふむと聞いていた。まあ去年も聞いたのばかりだったけど。普段はCloudWatchで十分!とか思ってるけど、デモを見るとやっぱいいよなあってなる。もっとスモールスタートしやすいといいんだけどな。

セッションはSCSKさんと四国銀行さんのやつが印象に残った。いい話だな〜と思いながら聞いていた。

ついでに去年は注文できなかったserverlesspressoを注文できて嬉しかった

アンチパターン神殿と、サービスアイコンのポーカーみたいなやつも面白かった

Day 2

この日は指定席に着けた。ただ、基調講演もいいのだけど、割と拘束時間が長く、この時間でいろんなブース行けるよなあとは思ってしまった。

セッションは絶対聞きたかったAurora DSQLの解説を聞いた。去年Limitless Databaseの話をきいたときもすげーって思ったけど、DSQLもすげーって思った。Level400?とかだったと思うけどわかりやすくてよかったし、他のサービスで使われてる信頼性のある仕組みが基盤になってるのも良いなって思った

Step Functionsのも良かった。使ったこと無かったけど使ったほうが良さそうに思えた。

あとはブースやらディスカッションやらしてた。普段リモートで引きこもってるとこういう場が貴重でありがたい。

おわり

楽しかったです。来年は認定増やしてたくさんステッカーもらいたいです。

雑記 2025-05-10

焼きそば

焼きそばが好きである。脂まみれになった麺のソース焼きそばも、結局何味か分からない塩焼きそばも、焼きそばパンも。 ちょうど昨日のお昼も焼きそばだった。中途半端に余ったお野菜がたくさんあったので全部突っ込んだ。何入れても成立する懐の広さも好きなポイント。

雨が降ってると眠い。天候によって体調が変化する人もいるが、これもそれだと勝手に思ってる。天候だけではなく、雨音も良い。雨音がよく聞こえるように窓際に布団を敷いている。健全なASMRを自然発生させる算段である。 しかしながら、雨音を聞きながら眠ろうとすると、昔眠気に負けて友人との約束を飛ばしたことを思い出す。よく思い出すおかげで同じことをしないわけだが、連鎖していろいろ思い出し、枕ジタバタしがちなので割とお困りでもある。

逆転裁判2

やった。面白かった。次は3

おわり

イヤホン壊れた。困ったなあ

雑記 2025-04-20

本棚

本棚を買った。部屋が寂しかったから。 買った本棚は自分で組み立てるタイプ。棚板をネジでとめるのだが説明書によるとドライバーでやりなさいとのこと。とてもじゃないがそんな事やってられないので電動ドライバーを取り出した。お陰で手首を痛めずに済んだ。一家に一台。ありがとう。

ところで、組み立てたはいいが入れるものがないことに気づいた。部屋が寂しかったドリブンで買ったので、いれるものについて何も考えていなかったのである。まぁそのうち埋まるでしょう

逆転裁判

逆転裁判1をやった。めちゃめちゃ面白かった。久しぶりに夜ふかししてゲームした。懐かしい体験だった。 次は逆転裁判2…でもユミアも積んでるんだよな…

タルタルソース

おいしい。どういうわけか自分で作ったタルタルソースなのにおいしい。おいしいけどそれだけで食べるものでもないので、タルタルソースといえばみたいなメニューを連打している。かたよる。

おわり

そろそろTauriとか使ったデスクトップアプリでも作りたいな

NANDく化シェル芸

シェル芸を難読化することを研究する難読化シェル芸。アイデアをメモっていたものの実装まではやってなかったシリーズから語感がいいNANDく化シェル芸やってみました。既出だったら本当にすみません。

NAND

NANDはNOT ANDです。真理値表は以下の通り。

A B A NAND B
0 0 1
1 0 1
0 1 1
1 1 0

さっそくですがNANDく化の例を見てみましょう。以下は date コマンドになります

$ echo -n  $'\xdb\xdb\x9f\xfe\xde\x9e\x8f\x8f\x8b\xbe\xde\xfa' | julia -E 'a=read(stdin);String(UInt8[~reduce(&, a[i:i+3-1]) for i in 1:3:length(a)])' | bash
Thu Feb 20 21:33:04 JST 2025

解説

NANDく化ではN個のバイト値をbit-wise NANDして文字を計算するのを繰り返しています。先の例でいうと、3個のバイト値をbit-wise NANDして文字を計算しています

つまり

~(0xdb & 0xdb & 0x9f) => 0x64 => d
~(0xfe & 0xde & 0x9e) => 0x61 => a
~(0x8f & 0x8f & 0x8b) => 0x74 => t
~(0xbe & 0xde & 0xfa) => 0x65 => e

というわけです。例では echo でバイト列をstdoutに書いて、Juliaでチャンク毎にNANDしているというわけです

では入力のバイト列はどうやって特定しているかというと以下のような計算を1バイトずつやっています

func encode(input byte, cnt int) []byte {
  and := ^input
  res := make([]byte, cnt)

  for i := 0; i < 8; i++ {
    bit := 1 & and
    and = and >> 1

    if bit == 1 {
      // そのビットが 1 ならばすべてが1でなければならない
      for j := 0; j < cnt; j++ {
        res[j] |= 1 << i
      }
    } else {
      // そのビットが 0 ならば最低でも1つは 0 でなければならない
      // 逆にいうと 0~cnt-1 個のビットが 1 であってもよい
      for _, idx := range rand.Perm(cnt)[:rand.Intn(cnt)] {
        res[idx] |= 1 << i
      }
    }
  }

  return res
}

byteからruneに変えるともう少し広い範囲で遊べるかもですね

おわり

感想としてはもうすこしNANDならではみたいなことができればなーという感じです。これORでもいいですからね…。

とはいえ、久しぶりに考える時間をとれたのは良かったです。楽しかったです。