MoonTV:Vibe Codingを試してみた

MoonTV:Vibe Codingを試してみた

MoonTVはNext.jsとReactで作った動画集約プラットフォームで、連続ドラマなどを手軽に楽しむためのものです。LibreTVを改善しようとしたことが始まりで、数か月の開発を経て多くの関心と利用を集めています。Cursorのおかげで効率よく開発できた一方、複数環境への対応や複雑なデータ依存関係には苦労しました。ユーザーが増える中、フィードバックを受けて改善を続けています。

半年ほど前からLibreTVを追っていました。各種収集サイトの動画をまとめて検索・再生できるプロジェクトです。彼女がドラマを見るための環境を用意したくて注目し、その後HTML5プレイヤーの変更など、コードの貢献もかなりしました。仕組みにも詳しくなりましたが、使ううちに欠点も見えてきました。完全なフロントエンド構成なので視聴履歴などはブラウザーのlocalstorageに保存され、ブラウザーを変えると消えます。すべて素のJSで、いろいろな人の手が入りコードも混沌としていました。静的チェックがないため、触るのが怖い箇所も多く、大改修は難しい状態でした。

数か月後、同僚からCursorがAlipay払いに対応したと聞いて、一気にやる気が出ました。それまではTraeを使っていましたが、モデルの能力が低いうえ、混雑時は待ち行列があります。その後有料化され、無料版では300〜400人待ちも珍しくなく、ほぼ使い物になりません。すぐにCursor Proを1か月契約し、LibreTVの書き直しで試すことにしました。

フロントエンド経験がまったくない私のVibe Codingが始まりました。大半のコードはCursorとの対話でそのまま完成し、こうしてMoonTVが生まれました。

MoonTechLab
MoonTechLab/LunaTV
本项目采用 CC BY-NC-SA 协议,禁止任何商业化行为,任何衍生项目必须保留本项目地址并以相同协议开源
10.5K 9.1KNOASSERTION

まだ1か月ですが、すでに4.6K Star、5.4K Forkです。Starも付けずにただ乗りする人がいるようです。推移は下のとおりで、中国で海賊版動画の需要が大きいことが分かります。iQIYI、Youku、Tencent Videoのユーザーをないがしろにする施策と、あの高い壁のおかげでしょう。 Starの推移

Next.jsとReactを使い、Vercel、Cloudflare Pages、Dockerにデプロイできます。保存先はlocalstorage、Redis、Cloudflare D1の3種類。RedisとD1ではアカウントごとのデータ分離やブラウザー間同期に対応し、使いやすい管理画面もあります。今後はUpstash連携も予定しています。

私にとって初のVibe Coding、初のフロントエンド/フルスタック、そして初の比較的まじめなオープンソースプロジェクトでした。「フルスタック」はNode/JS界隈でばかり聞く言葉な気がします。Cursorのおかげで、MoonTV開発の大半はコードを書く作業からレビューへ変わりました。要件を話せば実装してくれます。ただ、その「話す」にも多少のコツがあります。

最初の難関は、文字どおり最初にありました。フロントエンドは何も分からず、流行の技術も名前だけ知っている程度です。新しいものを使おうと、Serverlessと相性のよいNext.jsとTailwind CSSを選びました。フォルダーを作り、AIに初期化を頼んだのですが、午後の半分を費やして何度試しても動きません。大体はスタイルが消え、テキストを積み上げたような画面になります。理由も分からず結局あきらめ、GitHubの雛形を土台にして、ようやく開発を進められました。

本格的な開発は順調でした。主にClaude Sonnet 4.0とGPT O3を使い、傾向もよく分かりました。Sonnet 4.0はプロジェクト全体の大きな変更向きです。小さな修正でも全体をリファクタリングしようとすることがあり、新機能の実装に向いています。GPT O3は小修正が得意で、変更範囲を狭く保ち、あちこちのファイルを無秩序に変更しません。既存機能のバグ修正向きです。

もちろんAIの手に余る問題もありました。再生ページは状態遷移が複雑で、データ同士に依存や関連があります。AIの実装では依存関係が網のようになり、話数や再生元を切り替えるだけで、最終的にプレイヤーが5〜6回も初期化されてちらつきました。いろいろなモデルでも直せず、自分で依存データの伝播経路を整理して、ようやく解消できました。

さらにニッチな問題もあります。多くのプレイヤーではm3u8動画のAirPlayやChromecastが無効ですが、ちょっとした工夫で強制的に有効にできます。AIに頼むと不可能と言われたり、間違った案を出されたり、別のプレイヤーならできるから交換しようと言われたりします。ネットを探し回り、hls.jsの片隅にあったこのissueで、ようやくAirPlayを有効にできました。現状のAIが解けるのは主に一般的な問題です。あまりにニッチな問題や、人間にも解けない問題まで期待するのは、まだ早そうです。

もっと大きな苦労は、複数のプラットフォームと環境への対応でした。当初からVercel、Cloudflare Pages、Dockerを想定していました。Next.jsがそのまま動くVercelは問題が少ないものの、Cloudflare Pagesはnext-on-pagesでコードを変換するため、互換性の問題がよく出ます。Dockerはさらに複雑です。API処理などはNode環境で動きますが、Next.jsは認証などのミドルウェア用にedge環境も持ちます。メモリも共有しないため、依存関係と使えるAPIを厳密に分ける必要があります。クライアント側も複雑で、とくにWebKitが難所です。iOSとiPadOSのブラウザーはすべてWebKitで、APIやCSSの挙動がChromiumと大きく異なり、専用の対応が必要になります。

LibreTVから生まれたので、最初の告知はLibreTVの交流グループで行い、議論の場もそのまま使いました。自分から宣伝したのはほぼlinux.doだけで、大きな更新時にchangelogを投稿する程度です。そのうち、Xでフォローしている人やTelegramの技術チャンネル、さらにYouTube、Bilibili、小紅書の投稿者まで、自発的にMoonTVの導入方法を紹介してくれるようになりました。

利用者が増えるとissueも押し寄せます。大まかには2種類です。大半はBug report。コードにバグは付き物ですし、ましてAIが書いたものですからね、と責任転嫁しておきます。Feature Requestも2種類に分かれます。まともな要望はプロジェクトをよくするためのもので、レイアウト、操作、データ連携などです。一番歓迎できないのは収益化機能の要求です。導入して有料サービスにしたいのでしょうが、機能がなく自分でも作れないのでFRを出すわけです。楽をしてただ乗りしたい人は少ないほどありがたいです。以前、同種のissueを大量に出し、ban後もTelegramに来てしつこく絡む人がいました。本当に迷惑でした。ほかに無効なバグ報告もあります。READMEを読まずにデプロイに失敗したり、自分の回線の問題で検索できなかったりして、issueで騒ぎます。この手のものは、交流グループの通りすがりの人まで一言悪態をついていくほどです。

名前が知られると、周辺プロジェクトも生まれます。MoonTVにはAndroid TV専用のOrionTVというクライアントがあり、MoonTVをバックエンドにして視聴履歴を同期できます。交流グループではAndroid版やiOS版を作った人もいます。もちろんiOS版は各種制限でストア公開できません。

zimplexing
zimplexing/oriontv
一个基于 React Native TVOS 和 Expo 构建的播放器,旨在提供流畅的视频观看体验。
5.5K 1.9KTypeScript

以上です。本当は7月初め、まだ2K Starだったころに書き終える予定でしたが、ずっと先延ばしにしました。記事を書くよりコードを書くほうが面白いですからね。私は一度何かに取りかかると、食事中も寝るときもずっと考えてしまいます。夜中の2〜3時にバグを思い出して起きて直すのも珍しくありません。2週間連続で毎日6時間ちょっとしか寝ず、昼も夜も作業していました。

Microsoft Flight Simulator 2024をあれこれ試す
macOS 26とiPadOS 26を試してみた