everyThing is a widget
先引入 web_socket_channel: ^1.0.14(别问,问就是websocket)
看代码:
import ‘dart:async’;
import ‘dart:convert’;
import ‘dart:io’;
import ‘package:flutter/widgets.dart’;
import ‘package:web_socket_channel/io.dart’;
/// 科大讯飞语音转文本
class AudioTextForKDXF extends StatefulWidget {
final String wsAddr; // 例如: ws://echo.websocket.org
final AudioTextController controller;
final double width;
AudioTextForKDXF({this.wsAddr, this.controller,this.width});
@override
State createState() {
return _AudioTextForKDXFState();
}
}
class _AudioTextForKDXFState extends State {
AudioTextController _controller;
@override
void initState() {
super.initState();
if (widget.controller != null) {
_controller = widget.controller;
} else {
_controller = AudioTextController();
}
_controller.wsAddr = widget.wsAddr;
_controller.addListener(() {
setState(() {});
});
}
@override
void dispose() {
if (_controller != null) {
_controller.dispose();
_controller = null;
}
super.dispose();
}
@override
Widget build(BuildContext context) {
print(’----_controller–${_controller.state}’);
if(_controller.state == AudioTextState.noConvert) {
return Container();
}
return Container(
child: Container(
alignment: AlignmentDirectional.centerStart,
padding: EdgeInsets.all(5.0),
width: widget.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.0),
border: Border.all(color: Colors.black12,width: 0.1),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildConvertText(),
_controller.state == AudioTextState.endConvert? _buildConvertFinish():Container(),
],
),
)
);
}
_buildConvertText() {
return Row(
children: [
Offstage(
offstage: _controller.state != AudioTextState.startConvert,
child: CupertinoActivityIndicator(),
),
_controller.state != AudioTextState.startConvert?Expanded(child: Text(_controller.value??"")):Container(),
],
);
}
_buildConvertFinish() {
return Row(
children: [
Container(
margin: EdgeInsets.only(right: 2.0),
child: Icon(
Icons.check_circle,
size: 10.0,
color: Colors.black26,
),
),
Expanded(
child: Text(
“转换完成”,
style: TextStyle(fontSize: 10.0, color: Colors.black26),
maxLines: 1,
)),
],
);
}
}
enum AudioTextState {
noConvert, // 没有转换
startConvert, // 开始转换
converting,
endConvert, // 结束转换
}
class AudioTextController extends ChangeNotifier {
String wsAddr;
IOWebSocketChannel _channel;
StreamSubscription _subscription;
String value;
StreamSubscription _channelSub;
AudioTextState state = AudioTextState.noConvert; // 转换状态
void audioToText(File audio) async {
if (_subscription != null) {
_subscription.cancel();
}
if (_channelSub != null) {
_channelSub.cancel();
_channelSub = null;
}
value = “”;
// 开始转换
state = AudioTextState.startConvert;
notifyListeners();
_channel = new IOWebSocketChannel.connect(wsAddr);
var data = audio.readAsBytesSync();
int buffSize = 1280; // 缓存大小
int currPos = 0; // 当前位置
while (true) {
int dataLen = data.length;
List<int> buff;
int isLast = 0;
if (dataLen - 1 > currPos) {
if (dataLen > currPos + 1 + buffSize) {
buff = data.sublist(currPos, currPos + buffSize);
currPos += buffSize;
} else {
buff = data.sublist(currPos, dataLen);
currPos = dataLen - 1;
}
}
if (currPos == dataLen - 1) {
isLast = 1;
}
if (buff != null && buff.length > 0) {
_channel.sink.add(json.encode({
"is_last": isLast,
"format": "audio/L16;rate=16000",
"audio": base64.encode(buff),
"encoding": "raw",
}));
await Future.delayed(Duration(milliseconds: 40));
} else {
break;
}
}
_channelSub = _channel.stream.listen((dynamic result) {
state = AudioTextState.converting;
Map<String, Object> resultMap = json.decode(result);
value = "${value ?? ""}${resultMap["text"]}";
bool last = resultMap["last"];
if (last) {
state = AudioTextState.endConvert;
}
notifyListeners();
});
}
@override
void dispose() {
if (_subscription != null) {
_subscription.cancel();
}
if (_channelSub != null) {
_channelSub.cancel();
}
super.dispose();
}
}
使用方式:
不要你觉得好用
我觉得行
AudioTextForKDXF(
controller: _audioTextController,
wsAddr: “xxxx/v1/ws/iat”,//连接地址
child: Text(_audioTextController.value??""),//翻译结果
),
执行文本翻译:
_audioTextController.audioToText(audioFile);
好了去玩吧