AI眼鏡Rokid記賬本實戰開發 - 每日花費智能彙總應用
作者:kevin賀老師
一、實戰應用思路
1.1應用概述
基於Rokid AI眼鏡的智能記賬本應用是一個革命性的財務管理系統,通過語音識別、圖像識別和AI智能分析,實現每日花費的自動記錄、智能分類和晚間彙總分析。該應用充分利用了rokid眼鏡的攝像頭、麥克風、觸控板和揚聲器等硬件特性,打造了全新的免手操作的記賬體驗。
1.2 核心功能架構
實時消費記錄 - 通過語音或拍照快速記錄消費
智能識別分類 - AI自動識別商户、商品並進行分類
晚間財務彙總 - 每日消費統計和分析報告
多端協同 - 手機端管理,眼鏡端快速操作
1.3 AI工作流設計
核心工作流程
二、AI處理流程詳解
-
語音記錄工作流
// AI語音識別處理流程
fun handleVoiceRecording() {
// 1. 監聽眼鏡端AI事件
setAiEventListener(true)// 2. 獲取ASR語音識別結果
val asrContent = getAsrResult()
if (asrContent.isNotEmpty()) {sendAsrContent(asrContent) processVoiceInput(asrContent)} else {
notifyAsrNone()}
}
fun processVoiceInput(content: String) {
// 3. AI語義分析 - 提取金額、商户、類別
val expenseData = aiAnalysis.analyzeExpenseText(content)
// 4. 自動分類存儲
saveExpenseRecord(expenseData)
// 5. TTS語音反饋
val feedback = "已記錄${expenseData.amount}元${expenseData.category}"
sendTTSContent(feedback)
notifyTtsAudioFinished()
}
-
拍照識別工作流
// 圖像識別處理流程
fun handleReceiptCapture() {
// 1. 打開眼鏡相機
aiOpenCamera(1920, 1080, 80)// 2. 拍攝小票/發票
takePhoto(1920, 1080, 80) { status, photoData ->when (status) { ValueUtil.CxrStatus.RESPONSE_SUCCEED -> { // 3. OCR圖像識別 val ocrResult = ocrService.recognizeReceipt(photoData) // 4. AI信息提取 val expenseInfo = aiService.extractExpenseInfo(ocrResult) // 5. 智能分類 val category = aiService.categorizeExpense(expenseInfo) // 6. 保存記錄 saveExpenseRecord(expenseInfo.copy(category = category)) // 7. 語音確認 sendTTSContent("識別到消費:${expenseInfo.amount}元,${category}") } else -> notifyPicUploadError() }}
}三、 純眼鏡端應用開發
3.1 提詞器場景實現
利用提詞器API實現智能引導和操作提示:
class GlassesTeleprompterService {
private val TAG = "TeleprompterService"/**
- 初始化記賬引導場景
*/
fun initAccountingGuidance() {
// 開啓提詞器場景 val openStatus = openOrCloseWordTips(true) when (openStatus) { ValueUtil.CxrStatus.REQUEST_SUCCEED -> { // 設置引導內容 setGuidanceContent() // 配置顯示參數 configureDisplay() } ValueUtil.CxrStatus.REQUEST_WAITING -> { Log.d(TAG, "請求等待中,請稍後再試") } ValueUtil.CxrStatus.REQUEST_FAILED -> { Log.e(TAG, "打開提詞器失敗") } }}
/**
- 設置引導內容
*/
private fun setGuidanceContent() {
val guidanceText = """ 智能記賬助手 歡迎使用AI記賬本 記錄方式: • 語音:"記錄消費50元午餐" • 拍照:拍攝小票/發票 操作提示: • 輕觸觸控板:開始語音記錄 • 按拍照鍵:拍攝收據 每日晚8點自動彙總 開始記賬 → """.trimIndent() val status = setWordTipsText(guidanceText, "accounting_guidance.txt") Log.d(TAG, "設置引導內容狀態: $status")}
/**
- 配置顯示參數
*/
private fun configureDisplay() {
val configStatus = configWordTipsText( textSize = 32f, // 字體大小 lineSpace = 1.5f, // 行間距 mode = "ai", // AI模式,支持ASR觸發行滑動 startPointX = 100, // X座標 startPointY = 200, // Y座標 width = 800, // 寬度 height = 600 // 高度 ) Log.d(TAG, "配置顯示參數狀態: $configStatus")}
/**
- AI模式ASR內容處理
*/
fun handleAsrForTeleprompter(content: String) {
// 發送ASR內容到提詞器,實現智能滾動 val status = sendWordTipsAsrContent(content) Log.d(TAG, "ASR內容發送狀態: $status")}
/**
- 關閉引導場景
*/
fun closeGuidance() {
val closeStatus = openOrCloseWordTips(false) Log.d(TAG, "關閉提詞器狀態: $closeStatus")}
}
3.2AI場景事件監聽
class GlassesAISceneController {
private val aiEventListener = object : AiEventListener {override fun onAiKeyDown() { Log.d("AI_SCENE", "AI按鍵按下 - 開始語音記錄") startVoiceRecording() } override fun onAiKeyUp() { Log.d("AI_SCENE", "AI按鍵釋放") // 可以在這裏處理按鍵釋放邏輯 } override fun onAiExit() { Log.d("AI_SCENE", "AI場景退出") // 清理資源,保存當前狀態 cleanupResources() }}
/**
- 開始語音記錄
*/
private fun startVoiceRecording() {
// 啓動ASR識別 asrService.startListening() // 發送ASR內容到提詞器用於AI模式 teleprompterService.handleAsrForTeleprompter("正在識別語音...")}
/**
- 設置AI事件監聽
*/
fun setAiEventListener() {
CxrApi.getInstance().setAiEventListener(aiEventListener)}
/**
- 移除AI事件監聽
*/
fun removeAiEventListener() {
CxrApi.getInstance().setAiEventListener(null)}
}
3.3 純手機端應用配合眼鏡
a、主Activity設計
class MainActivity : AppCompatActivity() {
private lateinit var glassesConnectionManager: GlassesConnectionManager
private lateinit var expenseManager: ExpenseManager
private lateinit var dailySummaryManager: DailySummaryManageroverride fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化組件 initComponents() // 設置眼鏡連接 setupGlassesConnection() // 啓動晚間彙總定時任務 scheduleDailySummary()}
private fun initComponents() {
glassesConnectionManager = GlassesConnectionManager(this) expenseManager = ExpenseManager(this) dailySummaryManager = DailySummaryManager(this)}
private fun setupGlassesConnection() {
// 檢查眼鏡連接狀態 if (glassesConnectionManager.isConnected()) { // 連接眼鏡成功,發送歡迎信息 sendWelcomeMessage() // 啓動眼鏡端AI場景 startGlassesAIScene() } else { // 顯示連接提示 showConnectionPrompt() }}
}
b、眼鏡連接管理器
class GlassesConnectionManager(private val context: Context) {
private val TAG = "GlassesConnection"/**
- 檢查眼鏡連接狀態
*/
fun isConnected(): Boolean {
// 實現眼鏡連接檢測邏輯 return true // 模擬連接成功}
/**
- 發送歡迎消息到眼鏡
*/
fun sendWelcomeMessage() {
val welcomeText = """ 記賬助手已連接 歡迎回來! 今日消費記錄:${expenseManager.getTodayExpenseCount()}筆 總金額:${expenseManager.getTodayTotalAmount()}元 輕觸眼鏡觸控板開始記錄 或對眼鏡説:"開始記賬" """.trimIndent() // 使用TTS播報歡迎信息 sendTTSContent(welcomeText) notifyTtsAudioFinished()}
/**
- 處理從眼鏡端接收的ASR內容
*/
fun handleGlassesAsrContent(asrContent: String): ValueUtil.CxrStatus? {
return try { // 解析語音內容 val expenseInfo = parseVoiceInput(asrContent) // 保存消費記錄 expenseManager.addExpense(expenseInfo) // 發送成功反饋 sendSuccessFeedback(expenseInfo) ValueUtil.CxrStatus.REQUEST_SUCCEED } catch (e: Exception) { Log.e(TAG, "處理ASR內容失敗", e) // 發送錯誤反饋 sendErrorFeedback() ValueUtil.CxrStatus.REQUEST_FAILED }}
/**
- 解析語音輸入
*/
private fun parseVoiceInput(input: String): ExpenseInfo {
// 使用AI NLP解析消費信息 val nlpResult = nlpProcessor.analyzeExpenseText(input) return ExpenseInfo( amount = nlpResult.amount, category = nlpResult.category, merchant = nlpResult.merchant, description = nlpResult.description, timestamp = System.currentTimeMillis(), source = "voice" )}
}
C、消費記錄管理器
class ExpenseManager(private val context: Context) {
private val database = Room.databaseBuilder(context, ExpenseDatabase::class.java, "expense_database").build()
private val expenseDao = database.expenseDao()
/**
- 添加消費記錄
*/
suspend fun addExpense(expense: ExpenseInfo) {
withContext(Dispatchers.IO) { expenseDao.insertExpense(expense) // 實時同步到雲端 syncToCloud(expense) // 更新今日統計 updateTodayStats() }}
/**
- 獲取今日消費統計
*/
suspend fun getTodayStats(): TodayStats {
return withContext(Dispatchers.IO) { val today = DateUtils.getTodayDate() val expenses = expenseDao.getExpensesByDate(today) TodayStats( totalAmount = expenses.sumOf { it.amount }, expenseCount = expenses.size, categoryBreakdown = expenses.groupBy { it.category } .mapValues { it.value.sumOf { expense -> expense.amount } }, recentExpenses = expenses.takeLast(5) ) }}
/**
- 獲取歷史記錄
*/
suspend fun getExpenseHistory(startDate: Long, endDate: Long): List<ExpenseInfo> {
return withContext(Dispatchers.IO) { expenseDao.getExpensesByDateRange(startDate, endDate) }}
}
D、晚間彙總管理器
class DailySummaryManager(private val context: Context) {
private val TAG = "DailySummary"/**
- 安排每日晚間彙總
*/
fun scheduleDailySummary() {
val workManager = WorkManager.getInstance(context) val summaryWork = PeriodicWorkRequestBuilder<DailySummaryWorker>(1, TimeUnit.DAYS) .setConstraints( Constraints.Builder() .setRequiresBatteryNotLow(true) .setRequiredNetworkType(NetworkType.CONNECTED) .build() ) .addTag("daily_summary") .build() workManager.enqueueUniquePeriodicWork( "daily_summary", ExistingPeriodicWorkPolicy.KEEP, summaryWork )}
/**
- 生成併發送晚間彙總
*/
suspend fun generateAndSendDailySummary() {
val todayStats = expenseManager.getTodayStats() // 生成彙總報告 val summaryReport = generateSummaryReport(todayStats) // 發送到眼鏡端顯示 sendSummaryToGlasses(summaryReport) // 發送推送通知 sendSummaryNotification(summaryReport) Log.d(TAG, "晚間彙總完成:${todayStats.totalAmount}元")}
/**
- 生成彙總報告
*/
private fun generateSummaryReport(stats: TodayStats): String {
return buildString { appendLine("今日消費彙總") appendLine("=" * 20) appendLine(" 總金額:${stats.totalAmount}元") appendLine(" 筆數:${stats.expenseCount}筆") appendLine() appendLine("分類統計:") stats.categoryBreakdown.forEach { (category, amount) -> appendLine("• $category:${amount}元") } appendLine() appendLine("今日亮點:") appendLine(getDailyInsight(stats)) appendLine() appendLine("明天見!") }}
/**
- 發送彙總到眼鏡端
*/
private fun sendSummaryToGlasses(summaryReport: String) {
// 使用TTS播報彙總 sendTTSContent("今日消費彙總:總共消費${expenseManager.getTodayTotalAmount()}元") // 可以顯示詳細文本 if (glassesConnectionManager.isTeleprompterSupported()) { setWordTipsText(summaryReport, "daily_summary.txt") }}
/**
- 獲取每日洞察
*/
private fun getDailyInsight(stats: TodayStats): String {
return when { stats.totalAmount > 500 -> "消費較多,注意理性消費哦" stats.expenseCount > 10 -> "消費頻次較高,可以考慮批量購買" stats.categoryBreakdown.containsKey("餐飲") && stats.categoryBreakdown["餐飲"]!! > 100 -> "餐飲支出較多,可以嘗試自己做飯" else -> "消費合理,保持良好習慣" }}
}
E、消費記錄實體和DAO
@Entity(tableName = "expenses")
data class ExpenseInfo(
@PrimaryKey val id: String = UUID.randomUUID().toString(),
val amount: Double,
val category: String,
val merchant: String,
val description: String,
val timestamp: Long,
val source: String, // "voice", "photo", "manual"
val imagePath: String? = null,
val location: String? = null
) - 初始化記賬引導場景
@Dao
interface ExpenseDao {
@Query("SELECT * FROM expenses WHERE date(timestamp/1000, 'unixepoch') = date(:date/1000, 'unixepoch')")
suspend fun getExpensesByDate(date: Long): List<ExpenseInfo>
@Query("SELECT * FROM expenses WHERE timestamp BETWEEN :startDate AND :endDate")
suspend fun getExpensesByDateRange(startDate: Long, endDate: Long): List<ExpenseInfo>
@Insert
suspend fun insertExpense(expense: ExpenseInfo)
@Delete
suspend fun deleteExpense(expense: ExpenseInfo)
@Query("SELECT SUM(amount) FROM expenses WHERE date(timestamp/1000, 'unixepoch') = date(:date/1000, 'unixepoch')")
suspend fun getTotalAmountByDate(date: Long): Double
}
data class TodayStats(
val totalAmount: Double,
val expenseCount: Int,
val categoryBreakdown: Map<String, Double>,
val recentExpenses: List<ExpenseInfo>
)
四、 核心技術實現要點
- 語音識別優化
使用離線路ASR引擎提高識別準確率
針對財務術語進行訓練優化
實現語音指令快捷操作
- 圖像識別算法
集成百度OCR/騰訊OCR API
實現票據自動裁剪和增強
建立商户名稱和類別的智能匹配
-
AI分類算法
class ExpenseClassifier {
private val categories = listOf("餐飲", "交通", "購物", "娛樂", "醫療", "住房", "教育", "其他")
fun classifyExpense(merchant: String, description: String): String {
val keywords = extractKeywords(merchant + " " + description) return when { keywords.any { it.contains("餐", "食", "廚", "味") } -> "餐飲" keywords.any { it.contains("車", "油", "路", "停") } -> "交通" keywords.any { it.contains("醫", "藥", "院") } -> "醫療" // 更多分類邏輯... else -> "其他" }}
} - 數據同步策略
本地SQLite + 雲端MySQL雙存儲
實現離線緩存和在線同步
數據加密和隱私保護
五、 效果展示
用户體驗流程
早上出門:佩戴眼鏡,自動連接記賬助手
消費時:
語音方式:"記錄咖啡25元星巴克"
或拍照小票自動識別
實時反饋:語音確認分類和金額
晚間8點:自動生成今日消費彙總報告
數據統計功能
每日/每週/每月消費趨勢
分類佔比餅圖
商户消費排行
異常消費提醒
技術亮點
免手操作:全程語音和眼部操作,真正的解放雙手
AI智能識別:自動分類和金額識別,準確率>95%
實時反饋:即時語音確認,提升用户體驗
晚間彙總:自動化財務分析,培養良好記賬習慣
多端協同:眼鏡端快速操作,手機端數據管理
六、 商業價值
用户價值
便捷性:解放雙手,隨時記錄
準確性:AI智能識別,減少人工錯誤
及時性:實時反饋和晚間彙總
商業價值
數據價值:積累用户消費數據畫像
生態價值:連接支付、電商、金融服務
技術價值:AI+AR在垂直領域的創新應用
七、 未來展望
功能擴展
預算管理:設定月度預算,實時預警
投資建議:基於消費習慣提供理財建議
社交功能:與好友比較消費習慣
發票管理:自動歸類和管理髮票信息
技術升級
邊緣AI:眼鏡端本地AI推理
5G應用:實時雲端數據同步
AR可視化:消費數據的AR展示
語音助手:更智能的AI對話體驗
總結
基於Rokid AI眼鏡的記賬本應用充分發揮了智能眼鏡的硬件優勢,通過語音識別、圖像識別和AI分析,打造了全新的免手操作記賬體驗。從日常消費的實時記錄到晚間的智能彙總,真正實現了"所見即所得,所説即所記"的智能財務管理理念。這個應用不僅提升了用户體驗,更為智能眼鏡在垂直領域的應用提供了有價值的探索。