Mac(Metal)だけで、動画→3D Gaussian Splatting
CUDAの付いたNVIDIA GPUが無くても、Macだけで動画をガウシアン・スプラット(3DGS)にできます。実際にM1 Maxで動かし、詰まった箇所と直し方まで残します。
ffmpegでフレーム化 → COLMAPでカメラ位置推定 → Brush(Rust/wgpu, Metal対応)で学習 → .ply。量産だけクラウドのCUDAへ逃がす。ローカルは無料。
使うもの
- ffmpeg — 動画からフレーム抽出(
brew install ffmpeg) - COLMAP — Structure-from-Motionでカメラ位置を復元(
brew install colmap/MacはCUDA無し=CPU) - Brush — Metalで動く3DGS学習器。
gsplatやNerfstudioはCUDA前提でMPS非対応なので、ローカルはこれ一択(ArthurBrussee/brush、Rustでcargo build --release -p brush-cli) - splat-transform —
.plyを軽量.spzへ/プレビュー生成(npx @playcanvas/splat-transform)
流れ
動画 → [ffmpeg] フレーム → [COLMAP] SfM(カメラ位置) → 歪み補正
→ [Brush] 3DGS学習(Metal) → .ply → [splat-transform] .spz / 公開
実際に詰まった3つ(ここが本題)
1. COLMAP 4.x でGPUフラグが改名されている
ネット上の手順は古い名前のことが多いです。COLMAP 4系では次のように変わっています。
| 旧 | 新(4.x) |
|---|---|
| --SiftExtraction.use_gpu | --FeatureExtraction.use_gpu |
| --SiftMatching.use_gpu | --FeatureMatching.use_gpu |
2. Mac版COLMAPの既定マッチャがSIGSEGVで落ちる
CUDA無しでビルドされたHomebrewのCOLMAPは、既定のマッチング経路が落ちます(十分な特徴点があっても)。CPUブルートフォースを明示すると通ります。
colmap sequential_matcher --database_path db.db \
--FeatureMatching.use_gpu 0 --SiftMatching.cpu_brute_force_matcher 1
3. COLMAPは“断片モデル”に分割することがある
sparse/0が必ずしも最大とは限りません。登録画像数が最多のモデル(=images.binが最大)を選ぶようにします。
BEST=$(for d in sparse/*/; do [ -f "$d/images.bin" ] && \
echo "$(stat -f%z "$d/images.bin") $d"; done | sort -rn | head -1 | awk '{print $2}')
じつは“撮り方”が9割
公開映像を5本試して 成功3・失敗2。差はコードでなく素材でした。
| 素材 | 結果 | 要因 |
|---|---|---|
| 砂漠地形(日中) | ✅ 41/41 | 静止・順光・高テクスチャ・視差 |
| 石塔(順光・周回) | ✅ 32/32 | 近景の立体物+強い視差 |
| 岩稜(日中) | ✅ 42/42 | 同上 |
| 記念像(逆光・ビル街) | ✗ | 遠景で視差不足・反復パターン・逆光 |
| 海の岩塔(夕日) | ✗ | 波が動く(非剛体)・逆光・空/海が大半 |
合言葉は「静止・順光・高テクスチャ・視差」。避けるのは、動く水・逆光/夕日・遠景・反復する人工物(ガラス張りビル)・無地/鏡面。周回(オービット)素材はexhaustive_matcherが安定します。
手順(コマンドの骨子)
# 1) フレーム抽出(4K素材は縮小しておくとCOLMAPが速い)
mkdir -p frames
ffmpeg -i in.mp4 -vf "fps=3,scale='min(iw,1152)':-2" -q:v 2 frames/%04d.jpg
# 2) 特徴抽出(CPU)
colmap feature_extractor --database_path db.db --image_path frames \
--ImageReader.single_camera 1 --ImageReader.camera_model OPENCV \
--FeatureExtraction.use_gpu 0
# 3) マッチング(Mac対策のCPUブルートフォース。周回はexhaustive)
colmap sequential_matcher --database_path db.db \
--FeatureMatching.use_gpu 0 --SiftMatching.cpu_brute_force_matcher 1
# 4) 再構成 → 歪み補正
colmap mapper --database_path db.db --image_path frames --output_path sparse
colmap image_undistorter --image_path frames --input_path sparse/0 \
--output_path dataset --output_type COLMAP
# 5) Brushで学習 → .ply(絶対パスで出力先を指定するのが安全)
brush-cli dataset --total-train-iters 30000 --max-resolution 1600 \
--export-every 30000 --export-path "$PWD/out/" --export-name "scene_{iter}.ply"
結果
M1 Maxで、学習は7,000stepなら約5分、30,000stepでも十数分。3点の作例はこちら(ブラウザで歩けます)。
軽量化して公開
生の.plyは数十〜百MB。.spzにすると約1/10(例:115MB→11MB)。そのまま SuperSplat にドラッグで表示・公開できます。
npx @playcanvas/splat-transform out/scene_30000.ply -N scene.spz
# .html(自己完結ビューア)や .webp(プレビュー)も出力可
Sketchfabは2026年時点で3DGSをスプラットとしてネイティブ描画しません(点群表示になる)。露出はSuperSplat / Luma埋め込みを使います。
量産はクラウドCUDAへ
ローカルは少量向き。数を作るなら NerfstudioのsplatfactoをクラウドのRTX4090で回します。前処理込みで1シーン30〜50分、概ね $0.17〜0.30。月30本でも数百〜千円台。中断あり価格(Vast.ai)はチェックポイント再開前提で。
素材のライセンス(これが一番大事)
「公開されている」=「使える」ではありません。3DGS化は二次的著作物なので、元映像に再利用ライセンスが要ります。
- OK:CC0 / パブリックドメイン / CC-BY(要・出典明記)/ 明示許諾。Wikimedia Commons、Internet Archive、PLATEAU などのオープンデータ。
- NG:YouTubeの一般公開動画(公開でも著作権は残る)、権利不明素材。
- 被写体(彫刻・意匠)・施設管理権・写り込む人物にも配慮。作例ごとに出典とライセンスを必ず明記。
— 手を動かした記録として。質問や「この場所を見たい」があれば こちら へ。
← UTSUSHI トップへ