flutter 语音转文字(科大讯飞)

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);

好了去玩吧

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值