競馬馬券を自動で解析・記録するアプリを自作してみた
keiba-ocr-next ― 競馬馬券を自動で解析・記録するNext.js × Supabase構成のOCRアプリ
概要
keiba-ocr-next は、紙の馬券や投票結果のスクリーンショットを自動で解析し、
どのレースの、どの馬券を、いくら購入したかをデータ化するWebアプリケーションです。
フロントエンドには Next.js(TypeScript)を採用し、
バックエンドには Supabase(PostgreSQL + Auth + Storage)を利用しています。
OCR処理には Google Vision API や独自の正規表現解析を組み合わせ、
AI補正により複雑な馬券構成(BOX・フォーメーション・流しなど)にも対応します。
背景
購入履歴や収支は各サイトで確認できたりしますが、僕自身は現地で買う紙馬券が好きで
ネットで買ったり、現地で買ったり、WINSで買ってきたりしています。
メモしたりしていたのですが、つい忘れてしまうことがあります。
また、馬券収支管理アプリ等は既存のものがありますが一々入力が面倒で結局使わなくなって
しまいます。
ないなら作れないかなと勉強がてら自分で購入履歴や紙馬券をOCRで解析し自動的に入力補助として
使うアプリを作ってみました。

「馬券を撮るだけで自動的に履歴化される仕組み」
を目指して設計しました。
また、管理画面で回収率も見やすいように期間、レース名、競馬場別でフィルタし、フィルタした状態での回収率も表示できるようにしています。

主な設計思想は以下の通りです。
- OCR結果をAIで補正し、人手を最小化する
- クラウドで完結する構成により、個人でも運用できる
- セキュリティ(RLS)とスケーラビリティを両立する
システムアーキテクチャ
[ユーザ端末]
│
├── Next.js (Vercel)
│ ├─ /api/ocr/parse → OCR処理(Vision API呼び出し)
│ ├─ /api/ocr/consume → 利用回数の更新(Supabase RPC)
│ └─ /api/billing/* → Stripeによる課金処理
│
└── Supabase
├─ PostgreSQL (bets, profiles, ocr_usage_monthly)
├─ Storage (画像保存)
├─ Auth (JWT認証)
└─ Row Level Security (ユーザごとにデータ分離)
フロントエンド構成(Next.js 14 / TypeScript)
- フレームワーク: Next.js App Router構成
- 言語: TypeScript
- UI: React + TailwindCSS
- 状態管理: SWR + Zustand
- ホスティング: Vercel
特徴として、Next.jsのサーバレスAPIを積極的に活用しています。
アップロードされた画像は一時的に Supabase Storage に保存され、
サーバレス関数 /api/ocr/parse でOCR処理を実行します。
SSR / ISR により、レース履歴画面の高速描画も実現しています。
バックエンド構成(Supabase)
SupabaseはPostgreSQLベースのオープンソースBaaSです。
keiba-ocr-nextでは以下の機能を利用しています。
-
Database: PostgreSQL 16
-
bets… 馬券記録(レース名、券種、購入金額、払戻金額など) -
ocr_usage_monthly… 月間OCR利用数のトラッキング -
profiles… ユーザ情報
-
- Auth: メールリンク・OAuth(Google等)認証
- Storage: 画像ファイル保存
-
RLS (Row Level Security):
- 各ユーザが自分のレコードのみ閲覧・更新可能
- Functions: Edge Functionsを用いた月次集計・課金処理連携
OCR処理とAI補正ロジック
- 画像をSupabase Storageに保存
- Vision APIでテキスト認識(日本語対応)
- 正規表現で券種・組み合わせ・金額を抽出
- GPTまたはGemini APIを利用し、文脈補完・構造化
- Supabaseへレコード挿入(betsテーブル)
フォーメーション・BOXなどのパターンをAIが判定することで、
OCR誤認や曖昧な表記を補正します。
例:
- 「2,3-4,5-6,7」 → 「三連複フォーメーション:1列目[2,3], 2列目[4,5], 3列目[6,7]」
- 「2-3-4」 → 「三連単1点」
技術スタック一覧
| カテゴリ | 技術・サービス |
|---|---|
| ホスティング | Vercel |
| フロントエンド | Next.js 14 / React / TypeScript / TailwindCSS |
| バックエンド | Supabase(PostgreSQL + Storage + Auth + RLS) |
| API連携 | Google Vision API, Stripe |
| 状態管理 | SWR / Zustand |
| OCR解析 | Vision API + 正規表現パーサ + GPT補正 |
| データモデル | bets, races, ocr_usage_monthly, profiles |
| 認証方式 | Supabase Auth (JWT) |
| 決済 | Stripe Subscriptions(Free / Premium) |
利用による効果
| 観点 | 内容 |
|---|---|
| 入力効率 | 手入力が不要。撮影のみで自動登録 |
| データ精度 | AI補正により誤読を最小化 |
| データ分析 | 券種別・レース別の勝率・回収率を自動集計 |
| セキュリティ | Supabase RLSでユーザデータを厳密に分離 |
| スケーラビリティ | サーバレス構成で自動スケール対応 |
今後の展望
- AIによる「買い方提案」機能の導入
- ChatGPTプラグイン/RAG連携による会話型レース分析
- netkeiba APIや地方競馬データとの自動突合
- 画像アップロードから全自動レース記録までのパイプライン化
Discussion