1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🚧 Kotlin Multiplatform(KMP)でVJソフトを開発しようとして失敗した話 その1

Last updated at Posted at 2025-02-23

🚧 Kotlin Multiplatform(KMP)でVJソフトを開発しようとして失敗した話

📌 はじめに

映像と音楽を同期させてリアルタイムで操作できる VJソフトKotlin Multiplatform(KMP) を使って開発しようとしました。しかし、プラットフォームごとの制約やライブラリの互換性 などの問題に直面し、最終的には開発を断念することになりました。

本記事では、どのような構成を目指し、どのような課題に直面し、どう解決しようとしたか を詳しく解説します。


🎯 なぜKMPを使おうとしたのか?

VJソフトは音楽と映像をリアルタイムで同期させるアプリのため、Android/iOS/Desktopで共通のロジックを持たせる ことが理想でした。KMPを採用することで、以下のメリットを期待しました。

✅ 期待したメリット

  • ビジネスロジック(音楽のBPM解析、映像シンクロ)を共通化
  • UIは各プラットフォームで独自実装するが、データ処理は統一
  • 1つのコードベースで管理し、メンテナンス性向上

しかし、実際には以下の課題に直面し、KMPを適用するのが困難になりました。


🎯 VJソフトに必要な機能とKMPの課題

🔹 必須機能

  • 音楽・映像の再生・停止・シーク
  • 音楽のBPMに合わせた映像エフェクトの適用
  • 複数の映像・音声の同期とミックス

🔸 KMPでの課題

  • プラットフォームごとにメディア再生APIが異なり、統一が難しい
  • メタデータ取得方法がOSごとに異なる
  • JavaFXがAndroid/iOSと競合し、KMPの統合が困難
  • 依存関係の整理が難しく、Clean Architectureを維持しにくい

❌ 躓いたポイント

① KMPで音楽・映像の再生を統一するのが難しい

発生した問題

  • Android → ExoPlayerはシークやピッチ調整のカスタマイズが必要
  • iOS → AVFoundationはObjective-C/Swiftの依存が強く、KMPでの連携が難しい
  • Desktop → JavaFX Media APIはリアルタイム処理に向かない
  • FFmpeg/GStreamer → KMPの公式ラッパーが未成熟で、各OSごとにNativeライブラリが必要

結果:KMPでの完全統一を断念し、各プラットフォームごとの実装に切り替え

📦 project-root
 ┣ 📂 composeApp        # アプリのエントリポイント(UIの管理)
 ┃ ┣ 📂 commonMain    # アプリの初期化処理
 ┃ ┣ 📂 androidMain   # Android用のUIと実装
 ┃ ┣ 📂 iosMain       # iOS用のUIと実装(後から対応予定)
 ┃ ┗ 📂 desktopMain   # Desktop用のUIと実装(JavaFXを使用)
 ┣ 📂 sharedModule      # KMPで共通化するモジュール
 ┃ ┣ 📂 data           # データの管理(ファイルの読み込み、メタデータ取得)
 ┃ ┣ 📂 domain         # ビジネスロジック(UseCaseなど)
 ┃ ┣ 📂 di             # 依存関係の管理
 ┃ ┗ 📂 presenter      # ViewModelの管理
 ┃ ┃ ┣ 📂 commonMain    # Android & iOSで共通のViewModel
 ┃ ┃ ┣ 📂 androidMain   # Android固有のViewModel
 ┃ ┃ ┣ 📂 iosMain       # iOS固有のViewModel
 ┃ ┃ ┗ 📂 desktopMain   # Desktop固有のViewModel
 ┣ 📂 data_desktop      # Desktop向けのファイル処理(JavaFXを利用)

ポイント

  • Android/iOS共通UI(Jetpack Compose Multiplatform) を採用。
  • Desktop(JavaFX)別モジュール(data_desktop) に分離。
  • ビジネスロジック(domain)OS非依存 にする設計。
  • データ管理(data)OSごとの違いに対応するため、ファイル取得やメタデータ取得をプラットフォーム別に実装
  • DI(di)依存関係を管理し、将来的に Desktop の依存関係を切り分けられるよう設計

👉 この構成により、Android/iOS で共通の UI を使いながら、Desktop では JavaFX を使う柔軟な設計を目指しました。


② JavaFXがAndroid/iOSと競合する

発生した問題

  • Unresolved reference: javafx
  • The 'java' plugin has been applied, but it is not compatible with the Android plugins.

試したこと

  • ✅ gradle.properties にJavaFXの設定 → Gradle Daemon起動エラー
  • compose.desktop.applicationDefaultJvmArgs--module-path を設定 → プラグイン競合エラー
  • Desktop専用のdata_desktop モジュールを作成KMPでの統一は断念

結果:Android/iOSとDesktopを同じサブモジュールで扱うのを断念し、Desktop専用モジュールを作成。


③ KMPの依存関係の整理が難しい

発生した問題

  • data モジュールが domain のクラスを参照すると依存関係が逆転
  • repository を data に置くと domain に依存し、クリーンアーキテクチャが崩れる

具体的な影響

  • 音楽ファイルの取得ロジックが複雑化
  • BPM解析や映像のシーク処理をdomain層で統一できなくなった
  • 結果としてKMPのメリット(共通化)が減少

解決策

DTOを導入して、data層がdomainに依存しない設計に変更
Repositoryのinterfaceをdomainではなくdata側に配置

// data 層の DTO
data class MediaFileDto(val uri: String, val title: String, val duration: Long)

// domain 層のモデル
data class MediaFile(val uri: String, val title: String, val duration: Long)

// data 層の Repository
interface MediaRepository {
    fun getMediaFile(uri: String): MediaFileDto
}

class MediaRepositoryImpl(private val dataSource: MediaFileDataSource) : MediaRepository {
    override fun getMediaFile(uri: String): MediaFileDto {
        return dataSource.loadMediaFile(uri)
    }
}

但し上述の解決策には下記のデメリットも存在します。

・リアルタイム性が求められるVJソフト では、音楽のBPMと映像を同期させるために、フレーム単位でデータ変換が必要です
・音楽メタデータの取得・変換 も、プラットフォームごとに異なる処理が走るため、毎回DTOを経由するのが負担になります
・こうした要素が積み重なり、パフォーマンスのボトルネックになる可能性があります

結論

・KMPでVJソフトを開発しようとしたが、現時点では難易度が高い
・音楽・映像の再生はプラットフォームごとに対応する必要がある
・JavaFXの統合が困難で、DesktopはKMPを諦める選択に
・依存関係の整理が難しく、開発コストが増加
👉 KMPは便利だが、VJソフトのようなマルチメディアアプリには課題が多いと実感した。

🔍 次回予告:低レイヤーまで考慮したマルチプラットフォーム開発の課題

今回の記事では、KMPを活用したVJソフト開発の課題について解説しました。しかし、そもそも ソフトウェアが実際にハードウェア上でどのように動作するのか を理解することが、より適切な開発手法を選択する上で重要です。

次回は、ソフトウェア開発者が実装したコードがAPI LayerからSystem Library、Kernelを経てハードウェアに実行される仕組み を踏まえ、マルチプラットフォーム開発におけるアプローチを探ります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?