Flutter中 TTS(播放文本功能)的使用


需求

在flutter中指定一段文字,播放语音。

实现

1.添加库引用

我们这里使用Dart的 tts库,首先在配置文件中添加这个库的引用:

在pubspec.yaml文件中添加如下代码引用:

dependencies:
  tts: ^1.0.2

执行命令,获取该库:

flutter packages get

请支持原文:http://tryenough.com/flutter-tts

使用时引入头文件:

import 'package:tts/tts.dart';

2.创建tts_helper类,作为使用tts的帮助类


import 'package:tts/tts.dart';

import 'dart:async';
import 'dart:io';

/// Singleton tool class for tts

/// Use TtsHelper step:
///
/// Method : #isLanguageAvailable judge language, here language is _languageMap's values like "en-US",instead of the type of 'en' etc..
///
/// Method : #getTtsLanguage  help you convert "en" to "en-US".
///
/// Method : #setLanguage help you set Language , but "en-US" is default value
///
/// use example:
/// TtsHelper.instance.speak("speech content");
/// or
/// TtsHelper.instance.setLanguageAndSpeak("speech content", "en-US");
/// ...
class TtsHelper {

  // Locale to tss language map
  static final Map<String, String> _languageMap = {
    'en': "en-US",
    'zh': "zh-CN",
    "ar": "ar-SA",
    "cs": "cs-CZ",
    "da": "da-DK",
    "de": "de-DE",
    "el": "el-GR",
    "es": "es-ES",
    "fi": "fi-FI",
    "fr": "fr-CA",
    "he": "he-IL",
    "hi": "hi-IN",
    "hu": "hu-HU",
    "id": "id-ID",
    "it": "it-IT",
    "ja": "ja-JP",
    "ko": "ko-KR",
    "nl": "nl-BE",
    "no": "no-NO",
    "pl": "pl-PL",
    "pt": "pt-BR",
    "ro": "ro-RO",
    "ru": "ru-RU",
    "sk": "sk-SK",
    "sv": "sv-SE",
    "th": "th-TH",
    "tr": "tr-TR",
    'en-US': "en-US",
    'zh-CN': "zh-CN",
    "ar-SA": "ar-SA",
    "cs-CZ": "cs-CZ",
    "da-DK": "da-DK",
    "de-DE": "de-DE",
    "el-GR": "el-GR",
    "es-ES": "es-ES",
    "fi-FI": "fi-FI",
    "fr-CA": "fr-CA",
    "he-IL": "he-IL",
    "hi-IN": "hi-IN",
    "hu-HU": "hu-HU",
    "id-ID": "id-ID",
    "it-IT": "it-IT",
    "ja-JP": "ja-JP",
    "ko-KR": "ko-KR",
    "nl-BE": "nl-BE",
    "no-NO": "no-NO",
    "pl-PL": "pl-PL",
    "pt-BR": "pt-BR",
    "ro-RO": "ro-RO",
    "ru-RU": "ru-RU",
    "sk-SK": "sk-SK",
    "sv-SE": "sv-SE",
    "th-TH": "th-TH",
    "tr-TR": "tr-TR",
  };

  static final String _defaultL = "en-US";
  List<String> _languages;
  static TtsHelper _instance;
  static TtsHelper get instance => _getInstance();

  factory TtsHelper() =>_getInstance();

  static TtsHelper _getInstance() {
    if (_instance == null) {
      _instance = new TtsHelper._internal();
    }
    return _instance;
  }

  TtsHelper._internal() {
    // Initialize
    _initPlatformState();
  }

  _initPlatformState() async {
    _languages = await Tts.getAvailableLanguages();

    // If getAvailableLanguages is null, add "en-US" to _languages.
    if (_languages == null) {
      _languages = [_defaultL];
    }
    // Default set en-US language
    _setLanguage(_defaultL);
  }

  String _getTtsLanguage(String localeStr) {
    if(localeStr == null || localeStr.isEmpty ||
        !_languageMap.containsKey(localeStr)) {
      return _defaultL;
    }
    return _languageMap[localeStr];
  }

  // Return whether the result if set language is successful
  Future<bool> _setLanguage (String lang) async {
    String language = _getTtsLanguage(lang);
    if (language == null || language.isEmpty) {
      language = _defaultL;
    }
    if(Platform.isIOS && !_languages.contains(language)) {
      return false;
    }
    final bool isSet = await Tts.setLanguage(language);
    return isSet;
  }

  // Returns whether the supported language is supported
  Future<bool> _isLanguageAvailable (String language) async {
    final bool isSupport = await Tts.isLanguageAvailable(language);
    return isSupport;
  }

  void speak (String text) async {
    if (text == null || text.isEmpty) { return;}
    Tts.speak(text);
  }

  void setLanguageAndSpeak(String text, String language) async {
    String ttsL = _getTtsLanguage(language);
    var setResult = await _setLanguage(ttsL);
    if(setResult != null) {
      var available = await _isLanguageAvailable(ttsL);
      if(available != null) {
        speak(text);
      }
    }
  }

}

请支持原文:http://tryenough.com/flutter-tts

3.添加测试页面

import 'package:flutter_tts/tts_helper.dart';

import 'package:flutter/material.dart';

class VoiceSetPage extends StatefulWidget {
  VoiceSetPage({Key key, this.title}) : super(key: key);

  final String title;

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

class _VoiceSetPageState extends State<VoiceSetPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(

        backgroundColor: Colors.blue,
        title: Text(widget.title),
        elevation: 5.0, // shadow the bottom of AppBar
      ),
      body: Center(
        child: ListView(
          children: <Widget>[
            ListTile(
              title: Text(
                'test vioce',
                style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0),
              ),
              onTap: () {
                showAlertDialog(context);
                TtsHelper.instance.setLanguageAndSpeak("你好我是声音播放器", "zh");
              },
            ),
            Divider(
              height: 1,
            )
          ],
        ),
      ),
    );
  }
}

void showAlertDialog(BuildContext context) {
  NavigatorState navigator =
  context.rootAncestorStateOfType(const TypeMatcher<NavigatorState>());
  debugPrint("navigator is null?" + (navigator == null).toString());
  showDialog(
      context: context,
      builder: (_) => new AlertDialog(
          title: new Text("Dialog Title"),
          content: new Text("This is my content"),
          actions: <Widget>[
            new FlatButton(
              child: new Text("CANCEL"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            new FlatButton(
              child: new Text("OK"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            )
          ]));
}

4.在main中添加测试入口

import 'package:flutter/material.dart';
import 'package:flutter_tts/voice_set_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {

  void _incrementCounter() {
    Navigator.push(context, MaterialPageRoute(builder: (context) => VoiceSetPage(title: "Setting")));
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '点击浮动按钮跳转到语音测试页',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: '跳转',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

测试可用,希望能帮助到你。

请支持原文:http://tryenough.com/flutter-tts

完成demo下载地址:

[download info="完整例子" imageurl="https://upload-images.jianshu.io/upload_images/679754-787eca4a19408a01.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/200"]
<a href="https://pan.baidu.com/s/1EIj3fYSmGPkRJdbJtGCbTQ" target="_blank">百度网盘</a>
[/download]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • # 一、框架概述 # 课程概述 1. laravel 4天(之前TP框架还是很大的区别)(国外框架) 2. 在线教...
    关进一阅读 362评论 0 0
  • 在深圳实习已经三个多月了,在这三个月的实习生活中,我深刻体会到,人,果然是一种发声动物。 为什么说人是发...
    孤独百年阅读 810评论 1 3
  • 一、工作 二、感想 三、书与影 四、本周完成&下周计划 一、工作 周六计划开会,所以在周二的时候就发通知到了群里,...
    diy1947阅读 290评论 0 0
  • 抛开生硬的理论,那是我不擅长的领域,因为对于理科类的东西天生过敏。因此光对自己能写出东西的方面做一个总结和反思。 ...
    雁旋阅读 105评论 0 0
  • Finland Day.5 今天一早,大家兴致高涨,出发到密林里远足。场主家壮硕的大哥哥是我们的领队。 ...
    希子妈妈阅读 635评论 0 0