【Flutter】Flutter_tts로 텍스트 낭독 프로그램 만들기 [전문 유·복사 붙여넣기 OK]
안부를 묻다
안녕하세요, 저는 흰 사과입니다.
이전 Fluttertts를 해 본 샘플이 있어서 소개해 드릴게요.
전문 코드가 실렸으니, 마음에 드는 사람은 복사해 보세요.
차리다
"fluter tts"패키지와 "fluter localization"을 미리 설치합니다.
코무 IT 학원 어드벤트 캘린더 2021
pubspec.yaml
dependencies:
flutter_tts:
flutter_localizations:
sdk: flutter
MinsdkVersion은 안드로이드에서 21로 지정됩니다.android/app/build.gradle
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.camera_app"
minSdkVersion 21
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
이것으로 끝낼 준비를 하다.코드 전체 텍스트
main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_tts/flutter_tts.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState();
}
enum TtsState { playing, stopped, paused, continued }
class _MyAppState extends State<MyApp> {
FlutterTts flutterTts;
String language;
String engine;
double volume = 0.5;
double pitch = 1.0;
double rate = 0.5;
bool isCurrentLanguageInstalled = false;
String _newVoiceText;
var _controller = TextEditingController();
TtsState ttsState = TtsState.stopped;
get isPlaying => ttsState == TtsState.playing;
get isStopped => ttsState == TtsState.stopped;
get isPaused => ttsState == TtsState.paused;
get isContinued => ttsState == TtsState.continued;
initState() {
super.initState();
initTts();
}
initTts() {
flutterTts = FlutterTts();
flutterTts.setStartHandler(() {
setState(() {
ttsState = TtsState.playing;
});
});
flutterTts.setCompletionHandler(() {
setState(() {
ttsState = TtsState.stopped;
});
});
flutterTts.setCancelHandler(() {
setState(() {
ttsState = TtsState.stopped;
});
});
flutterTts.setErrorHandler((msg) {
setState(() {
ttsState = TtsState.stopped;
});
});
}
Future<dynamic> _getLanguages() => flutterTts.getLanguages;
Future _speak() async {
await flutterTts.setVolume(volume);
await flutterTts.setSpeechRate(rate);
await flutterTts.setPitch(pitch);
if (_newVoiceText != null) {
if (_newVoiceText.isNotEmpty) {
await flutterTts.awaitSpeakCompletion(true);
await flutterTts.speak(_newVoiceText);
}
}
}
Future _stop() async {
var result = await flutterTts.stop();
if (result == 1) setState(() => ttsState = TtsState.stopped);
}
Future _pause() async {
var result = await flutterTts.pause();
if (result == 1) setState(() => ttsState = TtsState.paused);
}
void dispose() {
super.dispose();
flutterTts.stop();
}
List<DropdownMenuItem<String>> getEnginesDropDownMenuItems(dynamic engines) {
var items = <DropdownMenuItem<String>>[];
for (dynamic type in engines) {
items.add(
DropdownMenuItem(value: type as String, child: Text(type as String)));
}
return items;
}
void changedEnginesDropDownItem(String selectedEngine) {
flutterTts.setEngine(selectedEngine);
language = null;
setState(() {
engine = selectedEngine;
});
}
List<DropdownMenuItem<String>> getLanguageDropDownMenuItems(
dynamic languages) {
var items = <DropdownMenuItem<String>>[];
for (dynamic type in languages) {
items.add(
DropdownMenuItem(
value: type as String,
child: Text(type as String),
),
);
}
return items;
}
void changedLanguageDropDownItem(String selectedType) {
setState(() {
language = selectedType;
flutterTts.setLanguage(language);
});
}
void _onChange(String text) {
setState(() {
_newVoiceText = text;
});
}
Widget build(BuildContext context) {
return MaterialApp(
supportedLocales: [Locale('ja', 'JP')],
locale: Locale('ja', 'JP'),
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text(
'TextToSpeech',
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.white,
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
_inputSection(),
_btnSection(),
_futureBuilder(),
_buildSliders(),
],
),
),
),
),
);
}
Widget _futureBuilder() => FutureBuilder<dynamic>(
future: _getLanguages(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
return _languageDropDownSection(snapshot.data);
} else if (snapshot.hasError) {
return Text('言語の読み込みに失敗');
} else
return Text('読み込み中');
});
Widget _inputSection() => Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.only(top: 25.0, left: 25.0, right: 25.0),
child: TextField(
controller: _controller,
enabled: true,
keyboardType: TextInputType.multiline,
maxLines: null,
minLines: 3,
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: () => _controller.clear(),
icon: Icon(
Icons.clear,
color: Colors.grey,
),
),
),
onChanged: (String value) {
_onChange(value);
},
));
Widget _btnSection() {
return Container(
padding: EdgeInsets.only(top: 50.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(
Colors.green,
Colors.greenAccent,
Icons.play_arrow,
'再生',
_speak,
),
_buildButtonColumn(
Colors.red,
Colors.redAccent,
Icons.stop,
'リセット',
_stop,
),
_buildButtonColumn(
Colors.blue,
Colors.blueAccent,
Icons.pause,
'停止',
_pause,
),
],
),
);
}
Widget _languageDropDownSection(dynamic languages) {
return Container(
padding: EdgeInsets.only(top: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DropdownButton(
value: language,
items: getLanguageDropDownMenuItems(languages),
onChanged: changedLanguageDropDownItem,
),
],
),
);
}
Column _buildButtonColumn(
Color color,
Color splashColor,
IconData icon,
String label,
Function func,
) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Icon(icon),
color: color,
splashColor: splashColor,
onPressed: () => func(),
),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(
label,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}
Widget _buildSliders() {
return Column(
children: [_volume(), _pitch(), _rate()],
);
}
Widget _volume() {
return Slider(
value: volume,
onChanged: (newVolume) {
setState(() => volume = newVolume);
},
min: 0.0,
max: 1.0,
divisions: 10,
label: "音量: $volume");
}
Widget _pitch() {
return Slider(
value: pitch,
onChanged: (newPitch) {
setState(() => pitch = newPitch);
},
min: 0.5,
max: 2.0,
divisions: 15,
label: "声の高さ: $pitch",
activeColor: Colors.red,
);
}
Widget _rate() {
return Slider(
value: rate,
onChanged: (newRate) {
setState(() => rate = newRate);
},
min: 0.0,
max: 1.0,
divisions: 10,
label: "スピード: $rate",
activeColor: Colors.green,
);
}
}
해설
거의'fluter tts'의 샘플과 마찬가지로 iOS 실기 테스트에 사용할 수 있도록 곳곳에서 수정되었다.
사진에서
텍스트 쓰기 "inputSection"
main.dart
Widget _inputSection() => Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.only(top: 25.0, left: 25.0, right: 25.0),
child: TextField(
controller: _controller,
enabled: true,
keyboardType: TextInputType.multiline,
maxLines: null,
minLines: 3,
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: () => _controller.clear(),
icon: Icon(
Icons.clear,
color: Colors.grey,
),
),
),
onChanged: (String value) {
_onChange(value);
},
));
텍스트 읽기, 읽기 위치 재설정, 일시 중지된 "btnSection"main.dart
Widget _btnSection() {
return Container(
padding: EdgeInsets.only(top: 50.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(
Colors.green,
Colors.greenAccent,
Icons.play_arrow,
'再生',
_speak,
),
_buildButtonColumn(
Colors.red,
Colors.redAccent,
Icons.stop,
'リセット',
_stop,
),
_buildButtonColumn(
Colors.blue,
Colors.blueAccent,
Icons.pause,
'停止',
_pause,
),
],
),
);
}
전환 언어main.dart
Widget _futureBuilder() => FutureBuilder<dynamic>(
future: _getLanguages(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
return _languageDropDownSection(snapshot.data);
} else if (snapshot.hasError) {
return Text('言語の読み込みに失敗');
} else
return Text('読み込み中');
});
발음 소리, 소리 높이, 속도를 조절하는 "buildSliders"main.dart
Widget _buildSliders() {
return Column(
children: [_volume(), _pitch(), _rate()],
);
}
Widget _volume() {
return Slider(
value: volume,
onChanged: (newVolume) {
setState(() => volume = newVolume);
},
min: 0.0,
max: 1.0,
divisions: 10,
label: "音量: $volume");
}
Widget _pitch() {
return Slider(
value: pitch,
onChanged: (newPitch) {
setState(() => pitch = newPitch);
},
min: 0.5,
max: 2.0,
divisions: 15,
label: "声の高さ: $pitch",
activeColor: Colors.red,
);
}
Widget _rate() {
return Slider(
value: rate,
onChanged: (newRate) {
setState(() => rate = newRate);
},
min: 0.0,
max: 1.0,
divisions: 10,
label: "スピード: $rate",
activeColor: Colors.green,
);
}
대체로 4개의 위젯으로 구성돼 있다.발음 언어는 기본적으로 영어로 설정되며 "future Builder"에서 일본어를 설정합니다.
다만 일본어, 특히 한자는 읽는 방법이 불안정해 실용성을 원한다면 영어로 읽어 애플리케이션으로 활용하는 것이 좋다.
Reference
이 문제에 관하여(【Flutter】Flutter_tts로 텍스트 낭독 프로그램 만들기 [전문 유·복사 붙여넣기 OK]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/imorin_basson/articles/a34664a048e6d7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)