talk_it 1.0.1
talk_it: ^1.0.1 copied to clipboard
Simple native speech-to-text for Flutter. Talk, get text — like speech_to_text but lighter, with reliable Arabic support and push-to-talk mode.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:talk_it/talk_it.dart';
void main() => runApp(const TalkItDemoApp());
class TalkItDemoApp extends StatelessWidget {
const TalkItDemoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Talk It Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: const TalkItDemoPage(),
);
}
}
class TalkItDemoPage extends StatefulWidget {
const TalkItDemoPage({super.key});
@override
State<TalkItDemoPage> createState() => _TalkItDemoPageState();
}
class _TalkItDemoPageState extends State<TalkItDemoPage> {
final TalkIt _talk = TalkIt();
bool _enabled = false;
String _words = '';
String _locale = 'ar-EG';
TalkItMode _mode = TalkItMode.untilSilence;
@override
void initState() {
super.initState();
_init();
}
Future<void> _init() async {
_enabled = await _talk.initialize(
localeId: _locale,
onStatus: (s) => debugPrint('status: $s'),
onError: (e) => debugPrint('error: $e'),
);
setState(() {});
}
Future<bool> _permissions() async {
if (!await Permission.microphone.request().isGranted) return false;
if (Platform.isIOS && !await Permission.speech.request().isGranted) {
return false;
}
return true;
}
Future<void> _start() async {
if (!await _permissions()) return;
await _talk.listen(
localeId: _locale,
listenOptions: TalkItListenOptions(mode: _mode),
onResult: (result) {
setState(() => _words = result.recognizedWords);
},
);
setState(() {});
}
Future<void> _stop() async {
await _talk.stop();
setState(() {});
}
@override
Widget build(BuildContext context) {
final rtl = _locale.startsWith('ar');
return Scaffold(
appBar: AppBar(
title: const Text('Talk It'),
actions: [
PopupMenuButton<String>(
initialValue: _locale,
onSelected: (v) {
setState(() => _locale = v);
_talk.initialize(localeId: v);
},
itemBuilder: (_) => const [
PopupMenuItem(value: 'ar-EG', child: Text('ar-EG')),
PopupMenuItem(value: 'en-US', child: Text('en-US')),
],
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Center(child: Text(_locale)),
),
),
],
),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SegmentedButton<TalkItMode>(
segments: const [
ButtonSegment(
value: TalkItMode.untilSilence,
label: Text('Auto-stop'),
),
ButtonSegment(
value: TalkItMode.untilStopped,
label: Text('Push-to-talk'),
),
],
selected: {_mode},
onSelectionChanged: _talk.isListening
? null
: (s) => setState(() => _mode = s.first),
),
const SizedBox(height: 24),
Expanded(
child: DecoratedBox(
decoration: BoxDecoration(
border: Border.all(color: Theme.of(context).dividerColor),
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Text(
_talk.isListening
? _words
: _enabled
? 'Tap the mic to start…'
: 'Speech not available on this device',
textDirection: rtl ? TextDirection.rtl : TextDirection.ltr,
style: Theme.of(context).textTheme.titleMedium,
),
),
),
),
],
),
),
floatingActionButton: FloatingActionButton.large(
onPressed: !_enabled
? null
: _talk.isNotListening
? _start
: _stop,
backgroundColor: _talk.isListening ? Colors.red : null,
child: Icon(_talk.isNotListening ? Icons.mic : Icons.stop),
),
);
}
}