iT邦幫忙

2025 iThome 鐵人賽

DAY 11
0
Mobile Development

Flutter :30天打造念佛App,跨平台應用從Mobile到VR,讓極樂世界在眼前實現!系列 第 11

[ Day 11 ] Flutter 語音辨識 實戰入門篇 — 生活在地球的勇者啊,你聽過阿彌陀佛嗎(2) #speech_to_text

  • 分享至 

  • xImage
  •  

2025 iThome鐵人賽
「 Flutter :30天打造念佛App,跨平台從Mobile到VR,讓極樂世界在眼前實現! 」
Day 11
「 Flutter 語音辨識 實戰入門篇 — 生活在地球的勇者啊,你聽過阿彌陀佛嗎(2) 」


前言

昨天我們已經透過官方文件初步認識「speech_to_text」並且完成安裝與權限設置。
今天我們要來 demo 官方的 example code ,並且知道該如何實作它!

Day 11 文章目錄:
一、Basic Example Demo
二、speech_to_text 實作步驟
三、speech_to_text 細節設置


一、Basic Example Demo

官方文件中有提供兩種版本Example:精簡版本、完整版本。
下面錄製的影片是精簡版本的內容,
讓大家可以快速看到 speech_to_text 語音辨識的基礎實作內容。

點擊觀看影片:

Yes

先在Info.plist 和 manifest 設置語音辨識及麥克風權限,
就可以在main.dart 貼上官方提供的 Basic Example 跑跑看 。
Basic Example :

import 'package:flutter/material.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  SpeechToText _speechToText = SpeechToText();
  bool _speechEnabled = false;
  String _lastWords = '';

  @override
  void initState() {
    super.initState();
    _initSpeech();
  }

  /// This has to happen only once per app
  void _initSpeech() async {
    _speechEnabled = await _speechToText.initialize();
    setState(() {});
  }

  /// Each time to start a speech recognition session
  void _startListening() async {
    await _speechToText.listen(onResult: _onSpeechResult);
    setState(() {});
  }

  /// Manually stop the active speech recognition session
  /// Note that there are also timeouts that each platform enforces
  /// and the SpeechToText plugin supports setting timeouts on the
  /// listen method.
  void _stopListening() async {
    await _speechToText.stop();
    setState(() {});
  }

  /// This is the callback that the SpeechToText plugin calls when
  /// the platform returns recognized words.
  void _onSpeechResult(SpeechRecognitionResult result) {
    setState(() {
      _lastWords = result.recognizedWords;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Speech Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              padding: EdgeInsets.all(16),
              child: Text(
                'Recognized words:',
                style: TextStyle(fontSize: 20.0),
              ),
            ),
            Expanded(
              child: Container(
                padding: EdgeInsets.all(16),
                child: Text(
                  // If listening is active show the recognized words
                  _speechToText.isListening
                      ? '$_lastWords'
                      // If listening isn't active but could be tell the user
                      // how to start it, otherwise indicate that speech
                      // recognition is not yet ready or not supported on
                      // the target device
                      : _speechEnabled
                          ? 'Tap the microphone to start listening...'
                          : 'Speech not available',
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed:
            // If not yet listening for speech start, otherwise stop
            _speechToText.isNotListening ? _startListening : _stopListening,
        tooltip: 'Listen',
        child: Icon(_speechToText.isNotListening ? Icons.mic_off : Icons.mic),
      ),
    );
  }
}

二、speech_to_text 實作步驟

1. 匯入

import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';

2. 設置動態頁面 與 建立物件

建立 SpeechToText 物件
_speechEnabled :是否已可使用語音辨識 (初始化成功)
_lastWords: 存放最後一次辨識到的文字

class MyHomePage extends StatefulWidget { ... }

class _MyHomePageState extends State<MyHomePage> {
  SpeechToText _speechToText = SpeechToText();
  bool _speechEnabled = false;
  String _lastWords = '';

3. 初始化

App第一次開啟時執行,系統會詢問 麥克風與語音辨識 的授權

@override
void initState() {
  super.initState();
  _initSpeech();
}

void _initSpeech() async {
  _speechEnabled = await _speechToText.initialize();
  setState(() {});
}

4. 開始/停止聆聽

listen 會把辨識結果傳給 _onSpeechResult

void _startListening() async {
  await _speechToText.listen(onResult: _onSpeechResult);
  setState(() {});
}

void _stopListening() async {
  await _speechToText.stop();
  setState(() {});
}

5. 接收辨識結果與更新畫面

void _onSpeechResult(SpeechRecognitionResult result) {
  setState(() {
    _lastWords = result.recognizedWords;
  });
}

6. UI 和麥克風按鈕

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text('Speech Demo')),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          # 標題
          Container(padding: EdgeInsets.all(16), child: Text('Recognized words:', style: TextStyle(fontSize: 20.0))),
          Expanded(
            child: Container(
              padding: EdgeInsets.all(16),
              child: Text(
          # 文字:顯示即時結果或提示
                _speechToText.isListening
                  ? '$_lastWords'
                  : _speechEnabled
                      ? 'Tap the microphone to start listening...'
                      : 'Speech not available',
              ),
            ),
          ),
        ],
      ),
    ),
    #右下角麥克風按鈕:切換開始/停止
    floatingActionButton: FloatingActionButton(
      onPressed: _speechToText.isNotListening ? _startListening : _stopListening,
      tooltip: 'Listen',
      child: Icon(_speechToText.isNotListening ? Icons.mic_off : Icons.mic),
    ),
  );
}

三、speech_to_text 細節設置

官方Example

  • 從完整版本的Example Code,我們知道有更多的細節可以進行設定。

    例如:
    pauseFor 語音暫停多久後就停止語音辨識
    listenFor 每一次最多支援多久的語音辨識
    localeId 取得預設語系 / 語言清單

class _SpeechSampleAppState extends State<SpeechSampleApp> {
  // ===== 狀態欄位 =====
  bool _hasSpeech = false;      // 是否初始化成功
  double level = 0.0;           // 即時音量
  double minSoundLevel = 50000; // 觀測到的最小音量
  double maxSoundLevel = -50000;// 觀測到的最大音量
  String lastWords = '';        // 最新辨識的文字
  String lastError = '';        // 最新錯誤訊息
  String lastStatus = '';       // 最新狀態字串
  List<LocaleName> _localeNames = []; // 裝置支援的語言清單
  final SpeechToText speech = SpeechToText();   // 創建實例

  // ===== 本次 Session 設定(可在 Demo 的設定面板調整)=====
  SpeechExampleConfig currentOptions = SpeechExampleConfig(
    SpeechListenOptions(
      listenMode: ListenMode.confirmation, // iOS才有效,範本預寫的是短回覆的聆聽模式
      onDevice: false,           // 是否嘗試「裝置端/離線」辨識(不一定支援)
      cancelOnError: true,       // 出錯時是否自動 cancel 本次 session
      partialResults: true,      // 是否回傳「即時片段」
      autoPunctuation: true,     // 支援的平台會自動加標點
      enableHapticFeedback: true,// 聆聽期間給些觸覺回饋
    ),
    "",    // localeId(初始化若為空字串,會帶入systemLocale)
    3,     // pauseFor 秒數(最後一次說話後,最多等多久自動結束)
    30,    // listenFor 秒數(本次聆聽的最大時長上限)
    false, // logEvents:印出範例事件 log
    false, // debugLogging:印出 speech_to_text 的 debug log
  );
}
  • 如果我們想自訂內容:

    (1) 停頓3秒就結束語音辨識
    (2) 每次最多支援5分鐘語音辨識
    (3) 指定繁體中文辨識

    提醒:

    • pauseFor / listenFor 都是上限,不是保證值;
      有些裝置/平台可能會更早結束(特別是 Android 對停頓時間常有自己的短上限)。
    • 一開始建議先使用系統預設語系systemLocale,如果有需要讓使用者自行更換語系,
      可以使用speech.locales() 取得裝置支援的語系清單。

步驟1:在 currentOptions 設定參數

SpeechExampleConfig currentOptions = SpeechExampleConfig(
    SpeechListenOptions(
      listenMode: ListenMode.confirmation, 
      onDevice: false,           
      cancelOnError: true,      
      partialResults: true,      
      autoPunctuation: true,     
      enableHapticFeedback: true,
    ),
    "",    // localeId,如果是在官方Example這邊寫指定語系,初始化時會改回系統語系
    3,     // pauseFor  停頓3秒自動結束
    300,   // listenFor 最長300秒
    false, 
    false, 
  );

步驟2:將參數帶入 speech.listen()

speech.listen(
  onResult: resultListener,
  listenFor: Duration(seconds: currentOptions.listenFor), // ← 最長300秒
  pauseFor:  Duration(seconds: currentOptions.pauseFor),  // ← 停頓3秒自動結束
  localeId:  "zh_TW", //← 指定語音辨識繁體中文
  onSoundLevelChange: soundLevelListener,
  listenOptions: currentOptions.options,
);

Day11 重點回顧

重點 內容
Basic Example Demo 語音辨識的實作畫面
speech_to_text 實作步驟 建立語音辨識的核心步驟
speech_to_text 細節設置 speech.listen()帶入參數

上一篇
[ Day 10] Flutter 語音辨識 實戰入門篇 — 生活在地球的勇者啊,你聽過阿彌陀佛嗎(1) #speech_to_text
系列文
Flutter :30天打造念佛App,跨平台應用從Mobile到VR,讓極樂世界在眼前實現!11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言