ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-05-04中級

Veo 3 APIで動画生成アプリを Antigravity で作る — 実装から公開まで

Google Veo 3 APIを使った動画生成アプリをAntigravityで実装する方法を解説。API呼び出し・UI設計・課金フローまで、個人開発者がゼロから作れる実践的なガイドです。

Veo 33動画生成Google AI4Antigravity338アプリ開発13API6個人開発89

Veo 3 を「試してみた」段階から「これでアプリを作りたい」に気持ちが動いたのは、8秒の動画を見た瞬間でした。アニメーションの滑らかさや光の扱いが、1年前の動画AIとは段違いで、「プロダクトに組み込める品質になってきた」と感じたからです。

ここではVeo 3 API を Antigravity で呼び出して動画生成アプリを作る方法を、実装の詳細まで踏み込んで解説します。「Veo 3 とは何か」の説明は既にある記事に譲り、ここでは「どう作るか」に集中します。

作るアプリの全体設計

今回作るのは、テキストプロンプトを入力すると Veo 3 で動画を生成して表示する iOS アプリです。シンプルに見えますが、動画生成APIは「リクエストを投げてすぐ動画が返ってくる」型ではなく、非同期ポーリング型という特性があります。これを理解してから設計しないと、UI が破綻します。

ユーザー → プロンプト入力 → API へリクエスト
                              ↓
                        ジョブID取得(即時)
                              ↓
                        ポーリング(5〜30秒)
                              ↓
                        動画URL取得 → 表示

この非同期フローを Antigravity に伝えると、ステート管理とUI更新のコードをまとめて提案してくれます。

API 呼び出しの実装

Veo 3 API は Gemini API の一部として提供されています。まず Antigravity にプロジェクト構造を作ってもらいます。

Antigravityへの指示:
「Veo 3 APIを呼び出してテキストから動画を生成するiOSアプリを作ります。
SwiftUIを使い、プロンプト入力→生成中表示→動画再生の流れを実装してください。
APIはGoogle AI Studio経由でアクセスします」

Antigravity が生成するコアの API クライアントはこのような形になります。

import Foundation
 
struct Veo3APIClient {
    private let apiKey = "YOUR_API_KEY"
    private let baseURL = "https://generativelanguage.googleapis.com/v1beta"
    
    // 動画生成ジョブを開始する
    func startVideoGeneration(prompt: String) async throws -> String {
        let url = URL(string: "\(baseURL)/models/veo-003:generateVideo?key=\(apiKey)")!
        
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let body: [String: Any] = [
            "contents": [["parts": [["text": prompt]]]],
            "generationConfig": [
                "durationSeconds": 8,
                "aspectRatio": "16:9",
                "resolution": "720p"
            ]
        ]
        
        request.httpBody = try JSONSerialization.data(withJSONObject: body)
        
        let (data, _) = try await URLSession.shared.data(for: request)
        let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
        
        // ジョブIDを返す(完了まで数十秒かかる)
        return json["name"] as! String
    }
    
    // ジョブのステータスを確認する
    func checkJobStatus(jobName: String) async throws -> VideoJobStatus {
        let url = URL(string: "\(baseURL)/\(jobName)?key=\(apiKey)")!
        let (data, _) = try await URLSession.shared.data(from: url)
        let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
        
        let done = json["done"] as? Bool ?? false
        if done {
            let response = json["response"] as? [String: Any]
            let candidates = response?["candidates"] as? [[String: Any]]
            let videoUri = candidates?.first?["video"] as? [String: Any]
            let uri = videoUri?["uri"] as? String
            return .completed(videoURL: uri)
        }
        
        return .processing
    }
}
 
enum VideoJobStatus {
    case processing
    case completed(videoURL: String?)
    case failed
}

ポーリングループの実装

Antigravity に「非同期ポーリングで完了を待つロジックを作って」と指示すると、次のような ViewModel を提案してくれます。

@MainActor
class VideoGenerationViewModel: ObservableObject {
    @Published var status: GenerationStatus = .idle
    @Published var videoURL: URL?
    @Published var errorMessage: String?
    
    private let client = Veo3APIClient()
    
    func generateVideo(prompt: String) async {
        status = .starting
        
        do {
            let jobName = try await client.startVideoGeneration(prompt: prompt)
            status = .processing(progress: 0)
            
            // ポーリング(最大60秒、5秒間隔)
            for attempt in 1...12 {
                try await Task.sleep(nanoseconds: 5_000_000_000)
                
                let result = try await client.checkJobStatus(jobName: jobName)
                
                switch result {
                case .processing:
                    let progress = Double(attempt) / 12.0
                    status = .processing(progress: progress)
                    
                case .completed(let urlString):
                    if let urlString, let url = URL(string: urlString) {
                        videoURL = url
                        status = .completed
                    } else {
                        status = .failed
                        errorMessage = "動画URLの取得に失敗しました"
                    }
                    return
                    
                case .failed:
                    status = .failed
                    errorMessage = "動画の生成に失敗しました"
                    return
                }
            }
            
            // タイムアウト
            status = .failed
            errorMessage = "生成がタイムアウトしました。もう一度お試しください"
            
        } catch {
            status = .failed
            errorMessage = error.localizedDescription
        }
    }
}
 
enum GenerationStatus: Equatable {
    case idle
    case starting
    case processing(progress: Double)
    case completed
    case failed
}

UI 設計のポイント

Antigravity に UI を作ってもらうとき、「生成中の体験設計」を明示するとよいです。動画生成には数十秒かかるため、ユーザーが「止まっている」と誤解しないように進捗を可視化する点が肝心です。

Antigravityへの指示:
「生成中は以下を表示してください:
- プログレスバー(ポーリング回数ベース)
- 'Veo 3 が動画を生成中です...' というアニメーション付きテキスト
- キャンセルボタン
生成完了後はアニメーションでビデオプレーヤーが表示されるようにしてください」

課金設計について考えておくこと

Veo 3 API はトークン単位ではなく秒単位の課金になります(2026年5月現在、正確な料金は Google AI Studioで確認してください)。

ユーザー向けアプリに組み込む場合、自分のAPIキーを使うとコストがユーザー数に比例して増大します。実用的な選択肢としては、ユーザーに自分のAPIキーを入力してもらうパターンか、アプリ内課金で生成クレジットを販売するパターンが現実的です。

Antigravity に「アプリ内課金と Veo 3 のクレジット消費を紐付ける設計にして」と指示すると、StoreKit との統合コードも提案してくれます。

実装を始める前の確認事項

Veo 3 API を個人のアプリに組み込む前に、Google の利用規約と生成コンテンツのポリシーを確認してください。特に「生成された動画をApp Storeで配布するアプリで使う場合のライセンス」については、条件が変わることがあるため、公式ドキュメントを常に参照することをおすすめします。

技術的に動くものを作るのに1日もあれば十分です。ただ、ビジネスとして継続できる設計にするには、APIコストとユーザー体験のバランスを最初から考えておく必要があります。そこに時間をかける価値は十分あります。

個人開発12年の現場で実感したこと

線引きするときの3つの判断軸

  • 失敗時の影響が金銭やユーザー体験にどれだけ波及するか
  • 復旧オペレーションが明文化されているか
  • 観測ログから人間が再現できる粒度に整っているか
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

アプリ開発2026-05-06
Antigravity × Google AI で動かすソロ開発スタジオ — 設計から審査申請までを一人で回す自動化パイプライン
Antigravity 2.0 と Antigravity CLI を中核に、Stitch・Veo 3 を組み合わせ、アプリの設計から実装・テスト・素材生成・ストア申請までを一人で自動化するパイプラインを実装レベルで解説します。権限委譲の線引きと運用の落とし穴も扱う上級者向けの内容です。
アプリ開発2026-07-05
自己デバッグのエージェントに、本番の広告を叩かせない — AdMob 無効トラフィックを断つ三層の遮断
Antigravity 2.0 の実ブラウザ自己デバッグが本番の AdMob 広告を描画すると、無効なトラフィックとして計上されます。テスト広告の強制・ネットワーク遮断・preflight ゲートの三層で、広告に触れない検証環境を作る手順を、実測値とともにまとめました。
アプリ開発2026-07-01
音を出すアプリのリリース前チェックを、音声描画とエージェントで仕組み化する
6/26 の更新で Antigravity が音声ファイルを描画できるようになりました。癒し系アプリで音を扱ってきた経験から、音量・クリップ・長さ・無音の事前チェックをエージェントの検証ループに組み込む設計を、実際のスクリプトとともに紹介します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →