# 例句口說練習整合規格 ## 📋 概述 本文檔詳細規劃 DramaLing 詞彙學習系統中新增「例句口說練習」功能的完整技術規格,包含前端組件、後端 API、Microsoft Azure Speech Services 整合,以及系統架構設計。 --- ## 🎯 功能目標 ### 學習價值 - **主動練習**: 從被動識別進階到主動口說輸出 - **發音矯正**: 使用 AI 評估發音準確度和流暢度 - **語境應用**: 在完整例句中練習單詞使用 ### 用戶體驗 - **視覺引導**: 顯示例句圖片幫助理解語境 - **即時反饋**: 提供發音評分和改善建議 - **無縫整合**: 與現有複習系統完美融合 --- ## 🖥️ 前端規格 ### 現有組件分析 **文件位置**: `note/archive/components/review/review-tests/SentenceSpeakingTest.tsx` **組件結構**: ```typescript interface SentenceSpeakingTestProps extends BaseReviewProps { exampleImage?: string onImageClick?: (image: string) => void } // 核心功能 - 顯示例句圖片 - 錄音按鈕 (🎤 開始錄音) - 目標例句顯示 - 結果回饋區域 ``` ### 前端功能升級需求 #### 1. **錄音功能實現** ```typescript // 需要添加的功能 interface AudioRecordingState { isRecording: boolean audioBlob: Blob | null recordingTime: number isProcessing: boolean } // Web Audio API 錄音實現 const startRecording = async () => { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }) const mediaRecorder = new MediaRecorder(stream) // 實現錄音邏輯 } ``` #### 2. **評分結果顯示** ```typescript interface PronunciationResult { overallScore: number // 總分 (0-100) accuracyScore: number // 準確度 fluencyScore: number // 流暢度 completenessScore: number // 完整度 prosodyScore: number // 韻律 (語調/節奏) feedback: string[] // 改善建議 transcribedText: string // 語音轉文字結果 } ``` #### 3. **UI 互動流程** 1. 顯示例句圖片 + 目標例句 2. 用戶點擊錄音按鈕 → 開始錄音 (顯示錄音動畫) 3. 再次點擊 → 停止錄音 → 上傳音頻 4. 顯示載入動畫 → 顯示評分結果 5. 根據評分自動給出信心等級 --- ## 🔧 後端規格 ### Microsoft Azure Speech Services 整合 #### 1. **NuGet 套件需求** ```xml ``` #### 2. **配置管理** ```csharp public class AzureSpeechOptions { public const string SectionName = "AzureSpeech"; public string SubscriptionKey { get; set; } = string.Empty; public string Region { get; set; } = "eastus"; public string Language { get; set; } = "en-US"; public bool EnableDetailedResult { get; set; } = true; public int TimeoutSeconds { get; set; } = 30; } ``` #### 3. **核心服務實現** ```csharp public interface IPronunciationAssessmentService { Task EvaluatePronunciationAsync( Stream audioStream, string referenceText, string language = "en-US" ); } public class AzurePronunciationAssessmentService : IPronunciationAssessmentService { // 實現 Azure Speech Services 整合 public async Task EvaluatePronunciationAsync(...) { // 1. 配置 Speech SDK var config = SpeechConfig.FromSubscription(apiKey, region); // 2. 設置發音評估參數 var pronunciationConfig = PronunciationAssessmentConfig.Create( referenceText, GradingSystem.HundredMark, Granularity.Phoneme ); // 3. 處理音頻流並獲取評估結果 // 4. 轉換為統一的 PronunciationResult 格式 } } ``` --- ## 🌐 API 設計規格 ### 端點設計 #### **POST `/api/speech/pronunciation-assessment`** **請求格式**: ```http Content-Type: multipart/form-data audio: [音頻檔案] (WAV/MP3, 最大 10MB) referenceText: "He overstepped the boundaries of acceptable behavior." flashcardId: "b2bb23b8-16dd-44b2-bf64-34c468f2d362" language: "en-US" (可選,預設 en-US) ``` **回應格式**: ```json { "success": true, "data": { "assessmentId": "uuid-here", "flashcardId": "b2bb23b8-16dd-44b2-bf64-34c468f2d362", "referenceText": "He overstepped the boundaries...", "transcribedText": "He overstep the boundary of acceptable behavior", "scores": { "overall": 85, "accuracy": 82, "fluency": 88, "completeness": 90, "prosody": 80 }, "wordLevelResults": [ { "word": "overstepped", "accuracy": 75, "errorType": "Mispronunciation" } ], "feedback": [ "發音整體表現良好", "注意 'overstepped' 的重音位置", "語速適中,語調自然" ], "confidenceLevel": 2, "processingTime": "1.2s" } } ``` ### 錯誤處理 **常見錯誤回應**: ```json { "success": false, "error": "AUDIO_TOO_SHORT", "message": "錄音時間太短,請至少錄製 1 秒", "details": { "minDuration": 1000, "actualDuration": 500 } } ``` **錯誤類型定義**: - `AUDIO_TOO_SHORT` - 錄音時間不足 - `AUDIO_TOO_LONG` - 錄音時間過長 (>30秒) - `INVALID_AUDIO_FORMAT` - 音頻格式不支援 - `SPEECH_SERVICE_ERROR` - Azure 服務錯誤 - `NO_SPEECH_DETECTED` - 未檢測到語音 --- ## 📊 資料庫設計 ### 新增評估記錄表 ```sql CREATE TABLE PronunciationAssessments ( Id UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(), UserId UNIQUEIDENTIFIER NOT NULL, FlashcardId UNIQUEIDENTIFIER NOT NULL, ReferenceText NVARCHAR(500) NOT NULL, TranscribedText NVARCHAR(500), -- 評分數據 OverallScore DECIMAL(5,2), AccuracyScore DECIMAL(5,2), FluencyScore DECIMAL(5,2), CompletenessScore DECIMAL(5,2), ProsodyScore DECIMAL(5,2), -- 元數據 AudioDuration DECIMAL(8,3), ProcessingTime DECIMAL(8,3), AzureRequestId NVARCHAR(100), CreatedAt DATETIME2 DEFAULT GETUTCDATE(), -- 外鍵約束 FOREIGN KEY (UserId) REFERENCES Users(Id), FOREIGN KEY (FlashcardId) REFERENCES Flashcards(Id) ); -- 索引優化 CREATE INDEX IX_PronunciationAssessments_UserId_CreatedAt ON PronunciationAssessments(UserId, CreatedAt DESC); CREATE INDEX IX_PronunciationAssessments_FlashcardId ON PronunciationAssessments(FlashcardId); ``` --- ## 🔄 系統整合規格 ### 1. 複習系統擴展 #### **quizType 擴展** ```typescript // hooks/review/useReviewSession.ts interface QuizItem { quizType: 'flip-card' | 'vocab-choice' | 'sentence-speaking' // ... 其他屬性保持不變 } ``` #### **題目生成邏輯更新** ```typescript // 在 generateQuizItemsFromFlashcards 中添加 quizItems.push( // 現有的 flip-card 和 vocab-choice... { id: `${card.id}-sentence-speaking`, cardId: card.id, cardData: cardState, quizType: 'sentence-speaking', order: order++, isCompleted: false, wrongCount: 0, skipCount: 0 } ) ``` ### 2. 評分邏輯映射 **Azure 評分 → 系統信心等級**: ```typescript const mapAzureScoreToConfidence = (overallScore: number): number => { if (overallScore >= 85) return 2 // 優秀 (高信心) if (overallScore >= 70) return 1 // 良好 (中信心) return 0 // 需改善 (低信心) } ``` --- ## ⚙️ 技術實施規格 ### 前端實施 #### 1. **音頻錄製實現** ```typescript // components/shared/AudioRecorder.tsx (新增共用組件) export class AudioRecorder { private mediaRecorder: MediaRecorder | null = null private audioChunks: Blob[] = [] async startRecording(): Promise { const stream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, sampleRate: 16000 // Azure 推薦採樣率 } }) this.mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm;codecs=opus' // 現代瀏覽器支援 }) // 實施錄音邏輯 } stopRecording(): Promise { // 停止錄音並返回音頻 Blob } } ``` #### 2. **API 客戶端** ```typescript // lib/services/speechAssessment.ts export const speechAssessmentService = { async evaluatePronunciation( audioBlob: Blob, referenceText: string, flashcardId: string ): Promise { const formData = new FormData() formData.append('audio', audioBlob, 'recording.webm') formData.append('referenceText', referenceText) formData.append('flashcardId', flashcardId) const response = await fetch('/api/speech/pronunciation-assessment', { method: 'POST', body: formData }) return response.json() } } ``` ### 後端實施 #### 1. **控制器實現** ```csharp [ApiController] [Route("api/speech")] public class SpeechController : BaseController { private readonly IPronunciationAssessmentService _assessmentService; [HttpPost("pronunciation-assessment")] public async Task EvaluatePronunciation( [FromForm] IFormFile audio, [FromForm] string referenceText, [FromForm] string flashcardId, [FromForm] string language = "en-US") { // 1. 驗證請求 if (audio == null || audio.Length == 0) return BadRequest("音頻檔案不能為空"); if (audio.Length > 10 * 1024 * 1024) // 10MB 限制 return BadRequest("音頻檔案過大"); // 2. 處理音頻流 using var audioStream = audio.OpenReadStream(); // 3. 呼叫 Azure Speech Services var result = await _assessmentService.EvaluatePronunciationAsync( audioStream, referenceText, language); // 4. 儲存評估記錄到資料庫 // 5. 返回結果 return Ok(result); } } ``` #### 2. **Azure Speech Services 整合** ```csharp public class AzurePronunciationAssessmentService : IPronunciationAssessmentService { public async Task EvaluatePronunciationAsync( Stream audioStream, string referenceText, string language) { // 1. 設定 Azure Speech Config var speechConfig = SpeechConfig.FromSubscription( _options.SubscriptionKey, _options.Region ); speechConfig.SpeechRecognitionLanguage = language; // 2. 設定發音評估參數 var pronunciationConfig = PronunciationAssessmentConfig.Create( referenceText, GradingSystem.HundredMark, Granularity.Word, // 單詞級別評估 enableMiscue: true // 啟用錯誤檢測 ); // 3. 設定音頻配置 using var audioConfig = AudioConfig.FromStreamInput( AudioInputStream.CreatePushStream() ); // 4. 建立語音識別器 using var recognizer = new SpeechRecognizer(speechConfig, audioConfig); pronunciationConfig.ApplyTo(recognizer); // 5. 處理音頻並獲取結果 var result = await recognizer.RecognizeOnceAsync(); // 6. 解析評估結果 var pronunciationResult = PronunciationAssessmentResult.FromResult(result); // 7. 轉換為系統格式 return new PronunciationResult { OverallScore = pronunciationResult.AccuracyScore, AccuracyScore = pronunciationResult.AccuracyScore, FluencyScore = pronunciationResult.FluencyScore, CompletenessScore = pronunciationResult.CompletenessScore, ProsodyScore = pronunciationResult.ProsodyScore, TranscribedText = result.Text, ProcessingTime = stopwatch.ElapsedMilliseconds }; } } ``` --- ## 🌍 環境配置規格 ### appsettings.json 配置 ```json { "AzureSpeech": { "SubscriptionKey": "${AZURE_SPEECH_KEY}", "Region": "eastus", "Language": "en-US", "EnableDetailedResult": true, "TimeoutSeconds": 30, "MaxAudioSizeMB": 10, "SupportedFormats": ["audio/wav", "audio/webm", "audio/mp3"] } } ``` ### 環境變數 ```bash # 開發環境 AZURE_SPEECH_KEY=your_azure_speech_key_here AZURE_SPEECH_REGION=eastus # 生產環境 (使用 Azure Key Vault) AZURE_SPEECH_KEY_VAULT_URL=https://dramaling-vault.vault.azure.net/ ``` --- ## 📱 複習系統整合 ### 1. Quiz Type 擴展 **更新位置**: `hooks/review/useReviewSession.ts` ```typescript // 類型定義更新 interface QuizItem { quizType: 'flip-card' | 'vocab-choice' | 'sentence-speaking' } // 生成邏輯擴展 (Line 110-132) quizItems.push( // 現有題目類型... { id: `${card.id}-sentence-speaking`, cardId: card.id, cardData: cardState, quizType: 'sentence-speaking', order: order++, isCompleted: false, wrongCount: 0, skipCount: 0 } ) ``` ### 2. 渲染邏輯擴展 **更新位置**: `app/review/page.tsx` (Line 332-350) ```typescript // 添加新的條件渲染 {currentQuizItem.quizType === 'sentence-speaking' && ( )} ``` --- ## 🎨 用戶介面設計 ### 錄音狀態 UI #### **錄音前** ```html

點擊開始錄製例句發音

``` #### **錄音中** ```html
錄音中... {recordingTime}s
``` #### **處理中** ```html

AI 正在評估發音... (約需 2-3 秒)

``` #### **結果顯示** ```html

發音評估結果

{overallScore}
總分 (滿分 100)
準確度
{accuracyScore}
識別結果
{transcribedText}
{feedback.map(item => (
• {item}
))}
``` --- ## 🔄 資料流程設計 ### 完整流程 ```mermaid graph TD A[用戶點擊錄音] --> B[前端開始錄音] B --> C[用戶說完點擊停止] C --> D[前端生成音頻 Blob] D --> E[上傳到後端 API] E --> F[後端接收音頻檔案] F --> G[呼叫 Azure Speech Services] G --> H[Azure 返回評估結果] H --> I[儲存到資料庫] I --> J[返回評分給前端] J --> K[前端顯示結果] K --> L[映射到信心等級] L --> M[更新複習進度] ``` ### 錯誤處理流程 ```mermaid graph TD A[API 請求] --> B{驗證音頻} B -->|失敗| C[返回驗證錯誤] B -->|成功| D[呼叫 Azure API] D -->|成功| E[處理結果] D -->|失敗| F{錯誤類型} F -->|網路| G[返回重試提示] F -->|配額| H[返回配額錯誤] F -->|其他| I[返回一般錯誤] ``` --- ## 🚀 實施階段規劃 ### 第一階段:基礎架構 1. ✅ 後端 Azure Speech Services 整合 2. ✅ 基礎 API 端點實現 3. ✅ 資料庫 Schema 更新 4. ✅ 環境配置設定 ### 第二階段:前端整合 1. ✅ AudioRecorder 共用組件開發 2. ✅ SentenceSpeakingQuiz 組件重構 3. ✅ API 服務客戶端實現 4. ✅ 複習系統整合 ### 第三階段:優化和測試 1. ✅ 錄音品質優化 2. ✅ 評分準確度調整 3. ✅ 錯誤處理完善 4. ✅ 效能和穩定性測試 --- ## 🔧 開發工具和配置 ### 開發環境需求 - **Azure Speech Services 帳戶** (免費層每月 5,000 次請求) - **音頻測試環境** (需要麥克風的開發設備) - **HTTPS 環境** (Web Audio API 需要安全連接) ### 測試策略 - **單元測試**: Azure 服務模擬 - **整合測試**: 端對端音頻流程 - **負載測試**: 併發請求處理 - **用戶測試**: 真實發音評估準確性 ### 部署考量 - **音頻檔案暫存**: 處理後立即清理 - **Azure 配額管理**: 監控使用量避免超限 - **CDN 配置**: 靜態資源優化 - **負載平衡**: 處理高併發錄音請求 --- ## 📈 效能指標和監控 ### 關鍵指標 - **評估延遲**: 目標 < 3 秒 - **準確率**: 與人工評估比較 > 85% - **成功率**: API 請求成功率 > 99% - **用戶滿意度**: 發音改善效果追蹤 ### 監控項目 - Azure API 請求次數和耗時 - 音頻檔案大小分佈 - 評分分佈統計 - 錯誤類型統計 --- ## 💰 成本估算 ### Azure Speech Services 定價 (2024) - **免費層**: 每月 5,000 次請求 - **標準層**: $1 USD / 1,000 次請求 - **預估使用**: 100 用戶 × 10 次/日 = 30,000 次/月 - **月成本**: ~$30 USD (超出免費額度部分) ### 建議成本控制 - 實施請求快取避免重複評估 - 設定用戶每日使用限額 - 監控異常使用模式 --- ## 🔐 安全性規格 ### 音頻資料保護 - **傳輸加密**: HTTPS/TLS 1.3 - **暫存清理**: 處理完成後立即刪除音頻檔案 - **存取控制**: 僅評估用戶自己的錄音 ### API 安全 - **速率限制**: 每用戶每分鐘最多 10 次請求 - **檔案驗證**: 檢查音頻格式和內容 - **輸入清理**: 防止注入攻擊 --- ## 📚 技術參考資料 ### Microsoft 官方文檔 - [Azure Speech Services Pronunciation Assessment](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/how-to-pronunciation-assessment) - [Speech SDK for C#](https://learn.microsoft.com/en-us/dotnet/api/microsoft.cognitiveservices.speech) - [Interactive Language Learning Tutorial](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-learning-with-pronunciation-assessment) ### 實作範例 - [GitHub Azure Speech Samples](https://github.com/Azure-Samples/cognitive-services-speech-sdk) - [Pronunciation Assessment Samples](https://github.com/Azure-Samples/azure-ai-speech/tree/main/pronunciation-assessment) --- ## ✅ 驗收標準 ### 功能驗收 1. ✅ 用戶能成功錄製 1-30 秒的音頻 2. ✅ 後端能準確評估發音並返回多維度評分 3. ✅ 前端能清晰顯示評分結果和改善建議 4. ✅ 評分能正確映射到複習系統的信心等級 ### 效能驗收 1. ✅ 音頻處理延遲 < 5 秒 2. ✅ API 回應時間 < 10 秒 (包含網路延遲) 3. ✅ 系統能處理併發錄音請求 4. ✅ 無記憶體洩漏或音頻檔案堆積 ### 用戶體驗驗收 1. ✅ 錄音過程直觀易懂 2. ✅ 評分結果有意義且具建設性 3. ✅ 錯誤提示清晰有幫助 4. ✅ 與現有複習流程無縫整合 這個規格將為 DramaLing 增加強大的口說練習功能,提升學習者的發音能力和語言實際應用技能!