當跑者結束今天的訓練,最希望能把剛跑完的數據記錄下來。傳統運動 APP 為了取得使用者的里程與配速,必須去向 Garmin 或 Strava 申請商業開發者 API,走過冗長的審核與 OAuth 2.0 授權流程。
但這次,我們可以嘗試用不一樣的解法——「多模態視覺解析 (Multimodal Vision)」。
管你是用 Garmin、COROS、Apple Watch,甚至是在健身房跑跑步機,只要拍張照或螢幕截圖上傳給 KAKERU,後端的 Gemini 視覺大腦就能瞬間看懂畫面中的配速、距離、心率,並給予專屬教練評語。今天我們就要把這個實現在 APP 中!
要在 React Native 中實現這套多模態辨識系統,資料流如下:
[手機相簿 / 拍照]
↓ (expo-image-picker 壓縮品質並轉 Base64)
[前端 React Native]
↓ (POST /analyze-chart)
[後端 Spring Boot]
↓ (轉發 Base64 + 嚴格 JSON Prompt)
[Gemini Vision 大腦]
↓ (回傳純 JSON: 距離、配速、心率、評語)
[前端 CheckInModal] ➔ 彈出辨識結果卡片與防呆驗證!
首先,打開終端機安裝 Expo 官方的圖片選擇套件:
npxexpoinstallexpo-image-picker
接著在打卡元件中撰寫挑選圖片的邏輯。為了節省網路傳輸頻寬並符合 Gemini API 的要求,我們設定 quality: 0.7 壓縮品質,關閉強制正方形裁切以完整讀取長條截圖,並直接請套件回傳 base64:
// 1. 開啟相簿並選取截圖
constpickImage=async ()=> {
constresult=awaitImagePicker.launchImageLibraryAsync({
mediaTypes: ['images'],
allowsEditing:false,// 允許直接選取完整跑錶長截圖,不強制正方形裁切
quality:0.7,// 適度壓縮以加快網路傳輸
base64:true,// 關鍵:直接取得 Base64 編碼
});
if (!result.canceled) {
setImageUri(result.assets[0].uri);
setBase64Image(result.assets[0].base64);
}
};
結果如圖:
在後端 (Spring Boot),我們呼叫 Gemini 的多模態端點,並透過 Prompt 鎖死它的輸出格式與防呆機制:
你現在是一位世界級的馬拉松 AI 教練。
跑者剛剛完成了一項訓練,並上傳了他的跑錶數據或跑步機面板截圖。
請分析這張圖片,提取出關鍵數據,並給予跑者一句 30 字以內的專業鼓勵與復盤。
【嚴格要求】
你「必須」且「只能」回傳以下格式的純 JSON 結構(若非運動數據或無法辨識請填 0):
{
"actualDistanceKm": 數值 (若非運動數據或無法辨識請填 0),
"averagePace": "字串,例如 05:30 (若無法辨識填 00:00)",
"averageHeartRate": 數值 (若無法辨識請填 0),
"coachFeedback": "給跑者的專業評語或無法辨識之提示"
}
前端將 Base64 發送給後端 API,收到 AI 整理好的 JSON 後,我們加上關鍵的防呆驗證——如果跑者誤傳了食物或風景照片,AI 回傳的距離為 0 km,我們將攔截並提示,避免誤判:
consthandleAnalyzeAndSubmit=async ()=> {
if (!base64Image) {
Alert.alert('提示','請先上傳圖片才能進行 AI 解析!');
return;
}
setIsAnalyzing(true);
try {
// 呼叫後端多模態視覺端點 (POST /analyze-chart)
constaiResult=awaitanalyzeWorkoutImage(base64Image);
// 🛡️ 防呆驗證:若 AI 判定里程為 0,代表圖片非運動數據或無法辨識
if (!aiResult.actualDistanceKm||aiResult.actualDistanceKm<=0) {
Alert.alert('⚠️ 無法辨識',aiResult.coachFeedback||'未偵測到跑步數據,請確認圖片清晰!');
return;
}
// 辨識成功!彈出成果與教練評語
Alert.alert(
'🎉 數據解析成功!',
`【實跑距離】:${aiResult.actualDistanceKm} km\n`+
`【平均配速】:${aiResult.averagePace}/km\n`+
`【平均心率】:${aiResult.averageHeartRate} bpm\n\n`+
`【教練評語】:${aiResult.coachFeedback}`
);
}catch (error) {
Alert.alert('解析失敗','教練眼睛有點茫,請稍後再試。');
}finally {
setIsAnalyzing(false);
}
};
上傳真實跑錶截圖後,成功彈出 AI 解析結果與教練評語的 Alert 畫面:
上傳食物或風景照片時,觸發防呆攔截「無法辨識有效跑步數據」的畫面:
今天我們利用 Gemini 的多模態 (Multimodal) 能力,繞過了第三方運動平台的 API 授權地獄。
隨著今天多模態圖片解析的實裝,KAKERU 的「Phase 2 前端核心功能開發」也正式告一段落!從個人的資料設定、課表生成、動態微調診療室,到今天的跑錶視覺辨識,我們已經實現並驗證了所有 AI 核心功能的可行性。
然而,當這款 APP 要從一個「功能雛形」邁向「Production 產品」時,我們原本的資料結構與單純的 4 週假資料將面臨嚴峻考驗。
明天(Day 23)將展開 Phase 3 終極進化:週期引擎升級!實作 UUID 匿名身份隔離,並加入 賽事日期選擇器,自動推算長達 24 週的備賽大週期。我們明天見!