meteor-detect 流星自動検出の機能を Claude Code で C# へ移植し、「HDMIキャプチャ映像をNDIで送るアプリ」へ組み込んでみた
きっかけ
https://github.com/kin-hasegawa/meteor-detect
流星自動検出でお世話になっている、長谷川氏の作成されたmeteor-detect(Pythonで実装)。
ソースがGitHubで公開されているので、 これを Claude Code に解析してもらい、1つ前の記事で書いた「HDMIキャプチャの映像をNDIで送るアプリ」と統合を目論んでいました。
必要な機能を統合するために、オリジナルのPythonからC# へ移植が必要となります。
これが実現すれば、流星群の日にYouTube Live での配信がやりやすくなるのではと考えていました。
進め方を決める
最初に、Claude Code にはオリジナルのmeteor-detectの機能の洗い出しをお願いしました。
そこから自分が必要とする機能を抽出して、まずテスト用のプログラムで検証し、結果が良好であれば「HDMIキャプチャの映像をNDIで送るアプリ」側に移植する、という進め方にしています。
露出時間と保存ファイル
流星を検出する時間(露出時間)は、1秒から5秒までをGUI画面で切り替えられるようにしました(既定は4秒)。
流星検出時に保存するファイル名は yyyyMMdd_hhmmss.jpg の形式にして、名前順に並べたときに画像が先に並ぶようにしました。
差分画像が明るい
オリジナルPython 版にあった差分画像(_diff.jpg)も同時に出力してもらいました。
同じ映像が続いていれば全体に黒くなるはずなのに、結構明るい画像が出力されていたので、どのように画像を作っているのかをClaudeに解説してもらいました。
オリジナルPython版と比べて差分のペアの数が元より1つ多くなっていたことが原因だったようで、これはオリジナルPython版の処理に合わせて修正してもらいました。
また画像の上部に映像の一部欠けが発生していて、これが流星誤検知の原因になっていたため、映像の周囲 5px を検出対象から除外するようにしました(後にマスクを設定する場合にも除外対象とします)。
検出結果を確認する画面
左側のサイドパネルに、検出した時刻(その露出を開始した時刻)をリストに表示して、任意に再生して検出結果を確認できるようにしました。
比較明合成の画像、差分画像、動画の3種類の検出結果を切り替えて表示することができ、誤検知と判断した場合は、「誤検知」ボタンを押すことにより _del フォルダ(削除対象フォルダ)へ移動して検出リストから除外できるようにしました。

直線ではないものが検出される
オリジナルPython版では、1 本の直線状に走る光跡を流星とみなしているはずなのに、直線状でないものを何故か検出していました。
結果画像を見せて、判断が変であることを伝え修正してもらいました。
合わせて、検出した動画に露出開始からのタイムコード(yyyy/MM/dd hh:mm:ss.フレーム)が焼き込まれるようにしました。 ATOM Cam2 以外のカメラの場合、映像に日時が表示されないためです。
流星の動画でテストする
オリジナルPython版で流星検出された動画データを、正解データのサンプルとして提供しました。
検出した位置を赤色でマーキングしてもらうことで、判断が正しく行われたかを目視確認できるようにしました。
流れはじめと流れ終わりの細い部分がマーキングされていない状態だったので、淡い部分も検出されるようにパラメータを調整してもらいました。

モノクロとカラー
正解データのサンプル動画は ATOM Cam2 のモノクロ映像でしたが、実際に使用を考えているのは SONY α7S のカラー映像です。
輝度成分だけで検出すれば、モノクロでもカラーでも同程度の結果が得られるのではと考えて、相談したところ、その案で実装してもらうことになりました。
飛行機の誤検知
実際の撮影に近い映像データで試すと、飛行機の軌跡で誤検知されました。
移動速度のチェック機能を追加してもらい、極端に遅く移動するものを除外するように調整しました。
流星も 露出時間で分断されることがあり、飛行機と判断が難しい面もあるため、人間側で判断し手動削除する方向性に調整しています。
ATOMCam リアルタイム(ストリーミングモード)
オリジナルPython版に実装されていた機能で、ATOMCamのライブストリーミング(RTSPストリーミング映像)を映像ソースとして、リアルタイムで流星検知を行うモードを追加しました。
今までのライブ配信では、この機能を使ってリアルタイム検出結果を画面右下に表示していました。
これと置き換えてライブ配信が行える想定です。

YouTubeライブ配信映像からの検出は見送り
オリジナルPython版には、同じストリーミングプロトコルのYouTubeライブ配信映像(RTSPストリーミング映像)をソースとして流星検出を行う機能も実装されていました。
同じRTSPなので特に問題なく実装できるだろうと思っていましたが、YouTube 側のボット対策で、配信URLからでは映像が取得できず、追加の認証(PoToken)が必要だったり、Node.js 製のツールやヘッドレスブラウザの同梱などが必要となるようで、面倒な感じになってきたため、YouTubeライブ配信映像の取り込みは見送りました。
既存の動画ファイルを検出にかける(ファイルモード)
HDMIキャプチャからのリアルタイム流星検出機能に加えて、既存の録画済みの動画ファイルを指定して後日流星検出を実行するモードも追加しました。
キャプチャモードからファイルモードに切り替えて、動画ファイルと映像の録画開始日時を指定します。(この場合NDIへの送出は必要ないので行いません)。
入力映像ソースの FPS を判定して、録画日時(検出日時)をできるだけ正確に求めるようにしています。
ATOM Cam の録画フォルダを順に処理する(ATOMCam モード)
ファイルモードに似た機能として、ATOMCam モードも追加してもらいました。
オリジナルPythonコードにあった最も基本的な機能です。
フォルダを指定すると、配下の yyyyMMdd フォルダ、hh フォルダ、mm.mp4 を日時順に連続して処理します。
ダークモードにする
一通り機能が実装できたあとに、ウィンドウの配色をダークモードに変更してもらいました。
夜間の暗い状況で使用する前提なので、ライトモードでは画面が明るすぎて辛いので、ダークモード固定とします。
変更後コンボボックスとボタンの文字が配色の関係で読めなくなってしまったので、文字色や背景色を何度か調整が必要でした。
タイトルバーだけ変更されずライトモードのままだったりしていたので、ダークモードにできないのかと聞いたところ、これも対応してくれて、希望の配色にすることが出来ました。
アイコンを作る
プログラムのアイコンがデフォルトのままでさみしかったので、Claude Code にデザイン案を考えてもらいました。
モニターに映った星と流星を描き、その輪郭を右下に影のように 3 重のグラデーションで重ねる、というイメージをプロンプトで伝えました。
シアン系の色で、流星は火球のように目立たせる、星をもっと増やして大きくする、余白を詰める、縮小するときにぼやけないようにする、と何度も調整してもらい、最後に .ico へ出力しました。

検出結果からマスクを作る(マスク追加)
誤検知される場所を、差分画像から直接マスク画像を修正する機能を追加してもらいました。
現在のマスク(無ければ黒い画像)を土台にして、差分画像の赤く表示されている部分を白で加算し、保存したものを新しいマスクとして設定します。
流星検出で使うマスクが、そのタイミングで切り替わります。

マスクが追加された例

連番を焼き込んで書き出す(採番出力)
検出一覧の順に、連番を焼き込んだ画像と動画を、_num フォルダに書き出す機能を追加してもらいました。
フォント、サイズ、マージンを調整する設定ダイアログがあり、プレビューで確認できます。OS に入っているフォントを選べるようにもしてもらいました。
ダイアログを開くとプログラムが落ちる不具合が出ましたが、設定の初期化の順番が原因とわかり、すぐに修正してくれました。

