@@ -1,4 +1,4 @@ | |||
import 'package:demo001/scenes/%20RecordScene.dart'; | |||
import 'package:demo001/scenes/translate/TranslateScene.dart'; | |||
import 'package:flutter/material.dart'; | |||
void main() { | |||
@@ -18,7 +18,7 @@ class MyApp extends StatelessWidget { | |||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), | |||
useMaterial3: true, | |||
), | |||
home: RecordScene(), | |||
home: TranslateScene(), | |||
); | |||
} | |||
} |
@@ -1,218 +0,0 @@ | |||
import 'dart:async'; | |||
import 'dart:io'; | |||
import 'dart:typed_data'; | |||
import 'package:record/record.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:logger/logger.dart'; | |||
import 'package:path_provider/path_provider.dart'; | |||
import 'package:permission_handler/permission_handler.dart'; | |||
import 'package:demo001/xunfei/xunfei_translate.dart'; | |||
/* | |||
录音测试场景 | |||
*/ | |||
class RecordScene extends StatefulWidget { | |||
@override | |||
_RecordSceneState createState() => _RecordSceneState(); | |||
} | |||
class _RecordSceneState extends State<RecordScene> { | |||
late Directory savedirectory; | |||
final XunFeiTranslate xunfei = XunFeiTranslate( | |||
appId: "137dc132", | |||
apiKey: "1c1891a475e71250ecd1320303ad6545", | |||
apiSecret: "MjZhNDA1NTI1NWZkZDQxOTMxYzMyN2Yw"); | |||
AudioRecorder _recorder = AudioRecorder(); | |||
bool _isRecorderReady = false; //是否录音已准备 | |||
bool _isRecording = false; //是否录音中 | |||
@override | |||
void initState() { | |||
super.initState(); | |||
_requestPermissions(); | |||
} | |||
// 初始化录音器 | |||
void _initRecorder() async { | |||
try { | |||
// 获取外部存储目录路径 | |||
savedirectory = (await getExternalStorageDirectory())!; | |||
setState(() { | |||
_isRecorderReady = true; | |||
}); | |||
_log('录音器初始化成功'); | |||
} catch (e) { | |||
_log('初始化录音器失败: $e'); | |||
setState(() { | |||
_isRecorderReady = false; | |||
}); | |||
} | |||
} | |||
// 请求麦克风权限 | |||
void _requestPermissions() async { | |||
try { | |||
if (await Permission.microphone.request().isGranted) { | |||
_log('麦克风权限已授予'); | |||
} else { | |||
_log('麦克风权限被拒绝'); | |||
setState(() { | |||
_isRecorderReady = false; | |||
}); | |||
} | |||
} catch (e) { | |||
_log('请求麦克风权限失败: $e'); | |||
setState(() { | |||
_isRecorderReady = false; | |||
}); | |||
} | |||
} | |||
// 切换按钮状态 | |||
void _toggleCallStatus() { | |||
if (!_isRecording) { | |||
//开始通话 | |||
_startRecorder(); | |||
} else { | |||
//结束通话 | |||
_stopRecorder(); | |||
} | |||
setState(() { | |||
_isRecording = !_isRecording; | |||
}); | |||
} | |||
//开始录音 | |||
void _startRecorder() async { | |||
try { | |||
if (!_isRecorderReady) { | |||
_initRecorder(); | |||
} | |||
if (_isRecording) return; // 防止重复调用 | |||
Stream<Uint8List> dataStream = await _recorder.startStream(RecordConfig( | |||
sampleRate: 16000, encoder: AudioEncoder.pcm16bits, numChannels: 1)); | |||
xunfei.starttranslate(dataStream); | |||
setState(() { | |||
_isRecording = true; | |||
}); | |||
_log('录音开始'); | |||
} catch (e) { | |||
_log('录音开始 异常: $e'); | |||
} | |||
} | |||
//结束录音 | |||
void _stopRecorder() async { | |||
try { | |||
if (!_isRecording) return; // 防止重复调用 | |||
await _recorder.stop(); | |||
await _recorder.cancel(); | |||
xunfei.stoptranslate(); | |||
setState(() { | |||
_isRecorderReady = false; | |||
_isRecording = false; | |||
}); | |||
_log('录音停止'); | |||
} catch (e) { | |||
_log('录音停止 异常: $e'); | |||
} | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
appBar: AppBar(title: Text("录音测试")), | |||
// body: ListView.builder( | |||
// itemCount: _records.length, | |||
// itemBuilder: (context, index) { | |||
// var audio = _records[index]; | |||
// return _buildAudioMessage(audio); | |||
// }, | |||
// ), | |||
bottomNavigationBar: Padding( | |||
padding: const EdgeInsets.all(20.0), | |||
child: InkWell( | |||
onTap: _toggleCallStatus, | |||
child: Container( | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(30), // 圆角按钮 | |||
color: _isRecording | |||
? Colors.red | |||
: Colors.green, // 通话状态红色,非通话状态绿色 | |||
), | |||
padding: EdgeInsets.symmetric( | |||
vertical: 15, horizontal: 40), // 调整按钮大小 | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: [ | |||
Icon( | |||
_isRecording ? Icons.call_end : Icons.mic, // 图标变化 | |||
color: Colors.white, | |||
size: 30, | |||
), | |||
SizedBox(width: 10), | |||
Text( | |||
_isRecording ? '挂断' : '开始通话', // 状态文字变化 | |||
style: TextStyle( | |||
color: Colors.white, | |||
fontSize: 18, | |||
), | |||
), | |||
], | |||
), | |||
))), | |||
); | |||
} | |||
// 构建语音消息 | |||
// Widget _buildAudioMessage(RecordData data) { | |||
// Color buttColor = data.state == 0 ? Colors.red : Colors.green; | |||
// return Padding( | |||
// padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), | |||
// child: Column( | |||
// crossAxisAlignment: CrossAxisAlignment.start, | |||
// children: [ | |||
// // 音频播放按钮 | |||
// GestureDetector( | |||
// onTap: () { | |||
// // _playRecording(data); | |||
// }, | |||
// child: Container( | |||
// padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), | |||
// decoration: BoxDecoration( | |||
// color: buttColor, | |||
// borderRadius: BorderRadius.circular(30), | |||
// ), | |||
// child: Row( | |||
// children: [ | |||
// Icon( | |||
// Icons.play_arrow, | |||
// color: Colors.white, | |||
// ), | |||
// SizedBox(width: 10), | |||
// Text( | |||
// '播放音频', | |||
// style: TextStyle(color: Colors.white), | |||
// ), | |||
// ], | |||
// ), | |||
// ), | |||
// ), | |||
// SizedBox(height: 5), | |||
// // 文字内容 | |||
// // Text( | |||
// // message['text'], | |||
// // style: TextStyle(fontSize: 16), | |||
// // ), | |||
// ], | |||
// ), | |||
// ); | |||
// } | |||
void _log(String msg) { | |||
Logger().f("LIWEI---------------:$msg"); | |||
} | |||
} |
@@ -0,0 +1,135 @@ | |||
import 'dart:convert'; | |||
import 'dart:io'; | |||
import 'dart:typed_data'; | |||
import 'package:demo001/scenes/translate/TranslateState.dart'; | |||
import 'package:demo001/tools/audio_tool.dart'; | |||
import 'package:demo001/xunfei/recognition_result/recognition_content/recognition_content.dart'; | |||
import 'package:demo001/xunfei/xunfei_translate.dart'; | |||
import 'package:get/get.dart'; | |||
import 'package:logger/logger.dart'; | |||
import 'package:path_provider/path_provider.dart'; | |||
import 'package:permission_handler/permission_handler.dart'; | |||
import 'package:record/record.dart'; | |||
class TranslateLogic extends GetxController { | |||
late Directory savedirectory; | |||
final state = TranslateState(); | |||
late XunFeiTranslate xunfei; | |||
late AudioRecorder _recorder; | |||
@override | |||
void onInit() { | |||
super.onInit(); | |||
_requestPermissions(); | |||
_recorder = AudioRecorder(); | |||
xunfei = XunFeiTranslate( | |||
appId: "137dc132", | |||
apiKey: "1c1891a475e71250ecd1320303ad6545", | |||
apiSecret: "MjZhNDA1NTI1NWZkZDQxOTMxYzMyN2Yw", | |||
onRecognitionResult: _handleRecognaitionData, | |||
onStreamtransResult: _handleTranslateData, | |||
onAudioResult: _handleAudioData); | |||
} | |||
// 初始化录音器 | |||
void _initRecorder() async { | |||
try { | |||
// 获取外部存储目录路径 | |||
savedirectory = (await getExternalStorageDirectory())!; | |||
state.isRecorderReady.value = true; | |||
_log('录音器初始化成功'); | |||
} catch (e) { | |||
_log('初始化录音器失败: $e'); | |||
state.isRecorderReady.value = false; | |||
} | |||
} | |||
// 请求麦克风权限 | |||
void _requestPermissions() async { | |||
try { | |||
if (await Permission.microphone.request().isGranted) { | |||
_log('麦克风权限已授予'); | |||
} else { | |||
_log('麦克风权限被拒绝'); | |||
} | |||
} catch (e) { | |||
_log('请求麦克风权限失败: $e'); | |||
} | |||
} | |||
// 切换按钮状态 | |||
void toggleCallStatus() { | |||
if (!state.isRecording.value) { | |||
//开始通话 | |||
_startRecorder(); | |||
} else { | |||
//结束通话 | |||
_stopRecorder(); | |||
} | |||
state.isRecording.value = !state.isRecording.value; | |||
} | |||
//开始录音 | |||
void _startRecorder() async { | |||
try { | |||
if (!state.isRecorderReady.value) { | |||
_initRecorder(); | |||
} | |||
if (state.isRecording.value) return; // 防止重复调用 | |||
Stream<Uint8List> dataStream = await _recorder.startStream(RecordConfig( | |||
sampleRate: 16000, encoder: AudioEncoder.pcm16bits, numChannels: 1)); | |||
xunfei.starttranslate(dataStream); | |||
state.isRecording.value = true; | |||
_log('录音开始'); | |||
} catch (e) { | |||
_log('录音开始 异常: $e'); | |||
} | |||
} | |||
//结束录音 | |||
void _stopRecorder() async { | |||
try { | |||
if (!state.isRecording.value) return; // 防止重复调用 | |||
await _recorder.stop(); | |||
await _recorder.cancel(); | |||
xunfei.stoptranslate(); | |||
state.isRecorderReady.value = false; | |||
state.isRecording.value = false; | |||
_log('录音停止'); | |||
} catch (e) { | |||
_log('录音停止 异常: $e'); | |||
} | |||
} | |||
void _handleRecognaitionData(result) { | |||
KDXFSentenceModel model; | |||
try { | |||
final index = state.kdxfSentenceList.indexWhere((KDXFSentenceModel e) { | |||
return e.sid == result.header?.sid; | |||
}); | |||
if (index != -1) { | |||
model = state.kdxfSentenceList[index]; | |||
} else { | |||
final recogContextStr = utf8.decode( | |||
base64Decode(result.payload?.recognitionResults?.text ?? '')); | |||
final model = RecognitionContent.fromJson(jsonDecode(recogContextStr)); | |||
model = KDXFSentenceModel( | |||
content: "", | |||
sid: result.header?.sid ?? '', | |||
transResult: '', | |||
audioPath: '', | |||
perviousWs: model.ws ?? []); | |||
} | |||
} catch (e) { | |||
print("接收识别结果异常 $e"); | |||
} | |||
} | |||
void _handleTranslateData(result) {} | |||
void _handleAudioData(AudioModel model) {} | |||
void _log(String msg) { | |||
Logger().f("LIWEI---------------:$msg"); | |||
} | |||
} |
@@ -0,0 +1,105 @@ | |||
import 'package:get/get.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'TranslateLogic.dart'; | |||
import 'TranslateState.dart'; | |||
/* | |||
录音测试场景 | |||
*/ | |||
class TranslateScene extends StatelessWidget { | |||
final TranslateLogic logic = Get.put(TranslateLogic()); | |||
final TranslateState state = Get.find<TranslateLogic>().state; | |||
TranslateScene({super.key}); | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
appBar: AppBar(title: Text("录音测试")), | |||
// body: ListView.builder( | |||
// itemCount: _records.length, | |||
// itemBuilder: (context, index) { | |||
// var audio = _records[index]; | |||
// return _buildAudioMessage(audio); | |||
// }, | |||
// ), | |||
bottomNavigationBar: Padding( | |||
padding: const EdgeInsets.all(20.0), | |||
child: InkWell( | |||
onTap: logic.toggleCallStatus, | |||
child: Obx(() => Container( | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(30), // 圆角按钮 | |||
color: state.isRecording.value | |||
? Colors.red | |||
: Colors.green, // 通话状态红色,非通话状态绿色 | |||
), | |||
padding: EdgeInsets.symmetric( | |||
vertical: 15, horizontal: 40), // 调整按钮大小 | |||
child: Row( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: [ | |||
Icon( | |||
state.isRecording.value | |||
? Icons.call_end | |||
: Icons.mic, // 图标变化 | |||
color: Colors.white, | |||
size: 30, | |||
), | |||
SizedBox(width: 10), | |||
Text( | |||
state.isRecording.value ? '挂断' : '开始通话', // 状态文字变化 | |||
style: TextStyle( | |||
color: Colors.white, | |||
fontSize: 18, | |||
), | |||
), | |||
], | |||
), | |||
)))), | |||
); | |||
} | |||
// 构建语音消息 | |||
// Widget _buildAudioMessage(RecordData data) { | |||
// Color buttColor = data.state == 0 ? Colors.red : Colors.green; | |||
// return Padding( | |||
// padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), | |||
// child: Column( | |||
// crossAxisAlignment: CrossAxisAlignment.start, | |||
// children: [ | |||
// // 音频播放按钮 | |||
// GestureDetector( | |||
// onTap: () { | |||
// // _playRecording(data); | |||
// }, | |||
// child: Container( | |||
// padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), | |||
// decoration: BoxDecoration( | |||
// color: buttColor, | |||
// borderRadius: BorderRadius.circular(30), | |||
// ), | |||
// child: Row( | |||
// children: [ | |||
// Icon( | |||
// Icons.play_arrow, | |||
// color: Colors.white, | |||
// ), | |||
// SizedBox(width: 10), | |||
// Text( | |||
// '播放音频', | |||
// style: TextStyle(color: Colors.white), | |||
// ), | |||
// ], | |||
// ), | |||
// ), | |||
// ), | |||
// SizedBox(height: 5), | |||
// // 文字内容 | |||
// // Text( | |||
// // message['text'], | |||
// // style: TextStyle(fontSize: 16), | |||
// // ), | |||
// ], | |||
// ), | |||
// ); | |||
// } | |||
} |
@@ -0,0 +1,38 @@ | |||
import 'dart:typed_data'; | |||
import 'package:audio_waveforms/audio_waveforms.dart'; | |||
import 'package:demo001/xunfei/phonetic_dictation/phonetic_dictaion_model/w.dart'; | |||
import 'package:demo001/xunfei/recognition_result/recognition_content/recognition_content.dart'; | |||
import 'package:get/get_rx/src/rx_types/rx_types.dart'; | |||
class TranslateState { | |||
RxBool isRecorderReady = false.obs; //是否录音已准备 | |||
RxBool isRecording = false.obs; //是否录音中 | |||
RxList<KDXFSentenceModel> kdxfSentenceList = <KDXFSentenceModel>[].obs; | |||
} | |||
class KDXFSentenceModel { | |||
String content = ''; | |||
String sid = ''; | |||
String transResult = ''; | |||
String audioPath = ''; | |||
Uint8List audioBytes = Uint8List(0); | |||
///已经释放好的最终文本 | |||
List<String> isFinalTransString = []; | |||
///临时翻译文件 | |||
// String isTempTransString = ''; | |||
List<W> perviousWs = []; | |||
List<RecognitionContent> contentList = []; | |||
int audioDuration = 0; | |||
final PlayerController playerController = PlayerController(); | |||
KDXFSentenceModel({ | |||
required this.content, | |||
required this.sid, | |||
required this.transResult, | |||
required this.audioPath, | |||
required this.perviousWs, | |||
}); | |||
} |
@@ -0,0 +1,116 @@ | |||
import 'dart:async'; | |||
import 'dart:io'; | |||
import 'dart:typed_data'; | |||
import 'package:audioplayers/audioplayers.dart'; | |||
import 'package:get/get.dart'; | |||
import 'package:logger/logger.dart'; | |||
import 'package:path_provider/path_provider.dart'; | |||
class AudioTool { | |||
AudioTool._(); | |||
static final AudioTool share = AudioTool._(); | |||
factory AudioTool() => share; | |||
///所有的音频数据 | |||
List<Uint8List> _audioChunks = []; | |||
///分断合并的数组,达到一定数量后合并去播放 | |||
List<Uint8List> _playTemps = []; | |||
///存放合并后的音频数组用于播放,播放完一个删除一个直到播放全部 | |||
// List<Uint8List> _playBuff = []; | |||
///是否已经播放了,play只被主动调用一次,然后根据_playBuff的数组递归 | |||
bool isPlaying = false; | |||
final player = AudioPlayer(); | |||
void dispose() async { | |||
await player.stop(); | |||
await player.dispose(); | |||
} | |||
void addAudioChunk({required AudioModel model, required Function(String) onPath, required Function() onPlaying, required Function() onPlayEnd}) async { | |||
if (model.status == 0 || model.status == 1) { | |||
_audioChunks.add(model.data); | |||
_playTemps.add(model.data); | |||
} else if (model.status == 2) { | |||
_audioChunks.add(model.data); | |||
_playTemps.add(model.data); | |||
final path = await mergeAudioChunks(sid: model.sid, chunks: _playTemps, onPlaying: onPlaying, onPlayEnd: onPlayEnd); | |||
onPath(path); | |||
} | |||
} | |||
Future<String> mergeAudioChunks({required String sid, required List<Uint8List> chunks, required Function() onPlaying, required Function() onPlayEnd}) async { | |||
// 计算总长度 | |||
int totalLength = chunks.fold(0, (sum, chunk) => sum + chunk.length); | |||
// 创建合并后的 Uint8List | |||
final mergedData = Uint8List(totalLength); | |||
int offset = 0; | |||
for (var chunk in chunks) { | |||
mergedData.setRange(offset, offset + chunk.length, chunk); | |||
offset += chunk.length; | |||
} | |||
///保存到文件或上传 | |||
// Logger().f('------isFinal--------保存文件'); | |||
_audioChunks = []; | |||
_playTemps = []; | |||
// _playBuff.add(mergedData); | |||
// if (!isPlaying) { | |||
// isPlaying = true; | |||
// play(bytes: mergedData, onPlaying: onPlaying, onPlayEnd: onPlayEnd); | |||
// } | |||
final dir = await getApplicationSupportDirectory(); | |||
final path = dir.path + '/$sid.mp3'; | |||
File file = File(path); | |||
await file.writeAsBytes(mergedData); | |||
return path; | |||
} | |||
void play({required Uint8List bytes, required Function() onPlaying, required Function() onPlayEnd}) async { | |||
// Logger().f('------_playBuff--------${_playBuff.length}'); | |||
// if (_playBuff.isNotEmpty) { | |||
await player.onPlayerStateChanged.listen((sta) async { | |||
if (sta == PlayerState.completed) { | |||
isPlaying = false; | |||
// if (_playBuff.isNotEmpty) { | |||
// _playBuff.removeAt(0); | |||
// } | |||
onPlayEnd(); | |||
} | |||
}); | |||
final source = BytesSource(bytes, mimeType: 'audio/mp3'); | |||
onPlaying(); | |||
await player.play(source); | |||
// } else { | |||
// isPlaying = false; | |||
// } | |||
} | |||
static Uint8List mergeAudio({required List<Uint8List> chunks}) { | |||
// 计算总长度 | |||
int totalLength = chunks.fold(0, (sum, chunk) => sum + chunk.length); | |||
// 创建合并后的 Uint8List | |||
final mergedData = Uint8List(totalLength); | |||
int offset = 0; | |||
for (var chunk in chunks) { | |||
mergedData.setRange(offset, offset + chunk.length, chunk); | |||
offset += chunk.length; | |||
} | |||
return mergedData; | |||
} | |||
} | |||
class AudioModel { | |||
int status; | |||
String sid; | |||
Uint8List data; | |||
AudioModel({required this.status, required this.sid, required this.data}); | |||
} |
@@ -0,0 +1,15 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'cw.g.dart'; | |||
@JsonSerializable() | |||
class Cw { | |||
int? sc; | |||
String? w; | |||
Cw({this.sc, this.w}); | |||
factory Cw.fromJson(Map<String, dynamic> json) => _$CwFromJson(json); | |||
Map<String, dynamic> toJson() => _$CwToJson(this); | |||
} |
@@ -0,0 +1,17 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'cw.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Cw _$CwFromJson(Map<String, dynamic> json) => Cw( | |||
sc: (json['sc'] as num?)?.toInt(), | |||
w: json['w'] as String?, | |||
); | |||
Map<String, dynamic> _$CwToJson(Cw instance) => <String, dynamic>{ | |||
'sc': instance.sc, | |||
'w': instance.w, | |||
}; |
@@ -0,0 +1,17 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'result.dart'; | |||
part 'data.g.dart'; | |||
@JsonSerializable() | |||
class Data { | |||
Result? result; | |||
int? status; | |||
Data({this.result, this.status}); | |||
factory Data.fromJson(Map<String, dynamic> json) => _$DataFromJson(json); | |||
Map<String, dynamic> toJson() => _$DataToJson(this); | |||
} |
@@ -0,0 +1,19 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'data.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Data _$DataFromJson(Map<String, dynamic> json) => Data( | |||
result: json['result'] == null | |||
? null | |||
: Result.fromJson(json['result'] as Map<String, dynamic>), | |||
status: (json['status'] as num?)?.toInt(), | |||
); | |||
Map<String, dynamic> _$DataToJson(Data instance) => <String, dynamic>{ | |||
'result': instance.result, | |||
'status': instance.status, | |||
}; |
@@ -0,0 +1,21 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'data.dart'; | |||
part 'phonetic_dictaion_model.g.dart'; | |||
@JsonSerializable() | |||
class PhoneticDictaionModel { | |||
int? code; | |||
String? message; | |||
String? sid; | |||
Data? data; | |||
PhoneticDictaionModel({this.code, this.message, this.sid, this.data}); | |||
factory PhoneticDictaionModel.fromJson(Map<String, dynamic> json) { | |||
return _$PhoneticDictaionModelFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$PhoneticDictaionModelToJson(this); | |||
} |
@@ -0,0 +1,27 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'phonetic_dictaion_model.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
PhoneticDictaionModel _$PhoneticDictaionModelFromJson( | |||
Map<String, dynamic> json) => | |||
PhoneticDictaionModel( | |||
code: (json['code'] as num?)?.toInt(), | |||
message: json['message'] as String?, | |||
sid: json['sid'] as String?, | |||
data: json['data'] == null | |||
? null | |||
: Data.fromJson(json['data'] as Map<String, dynamic>), | |||
); | |||
Map<String, dynamic> _$PhoneticDictaionModelToJson( | |||
PhoneticDictaionModel instance) => | |||
<String, dynamic>{ | |||
'code': instance.code, | |||
'message': instance.message, | |||
'sid': instance.sid, | |||
'data': instance.data, | |||
}; |
@@ -0,0 +1,24 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'w.dart'; | |||
part 'result.g.dart'; | |||
@JsonSerializable() | |||
class Result { | |||
int? sn; | |||
bool? ls; | |||
int? bg; | |||
int? ed; | |||
String? pgs; | |||
List<int>? rg; | |||
List<W>? ws; | |||
Result({this.sn, this.ls, this.bg, this.ed, this.pgs, this.rg, this.ws}); | |||
factory Result.fromJson(Map<String, dynamic> json) { | |||
return _$ResultFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$ResultToJson(this); | |||
} |
@@ -0,0 +1,31 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'result.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Result _$ResultFromJson(Map<String, dynamic> json) => Result( | |||
sn: (json['sn'] as num?)?.toInt(), | |||
ls: json['ls'] as bool?, | |||
bg: (json['bg'] as num?)?.toInt(), | |||
ed: (json['ed'] as num?)?.toInt(), | |||
pgs: json['pgs'] as String?, | |||
rg: (json['rg'] as List<dynamic>?) | |||
?.map((e) => (e as num).toInt()) | |||
.toList(), | |||
ws: (json['ws'] as List<dynamic>?) | |||
?.map((e) => W.fromJson(e as Map<String, dynamic>)) | |||
.toList(), | |||
); | |||
Map<String, dynamic> _$ResultToJson(Result instance) => <String, dynamic>{ | |||
'sn': instance.sn, | |||
'ls': instance.ls, | |||
'bg': instance.bg, | |||
'ed': instance.ed, | |||
'pgs': instance.pgs, | |||
'rg': instance.rg, | |||
'ws': instance.ws, | |||
}; |
@@ -0,0 +1,17 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'cw.dart'; | |||
part 'w.g.dart'; | |||
@JsonSerializable() | |||
class W { | |||
int? bg; | |||
List<Cw>? cw; | |||
W({this.bg, this.cw}); | |||
factory W.fromJson(Map<String, dynamic> json) => _$WFromJson(json); | |||
Map<String, dynamic> toJson() => _$WToJson(this); | |||
} |
@@ -0,0 +1,19 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'w.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
W _$WFromJson(Map<String, dynamic> json) => W( | |||
bg: (json['bg'] as num?)?.toInt(), | |||
cw: (json['cw'] as List<dynamic>?) | |||
?.map((e) => Cw.fromJson(e as Map<String, dynamic>)) | |||
.toList(), | |||
); | |||
Map<String, dynamic> _$WToJson(W instance) => <String, dynamic>{ | |||
'bg': instance.bg, | |||
'cw': instance.cw, | |||
}; |
@@ -0,0 +1,19 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'header.g.dart'; | |||
@JsonSerializable() | |||
class Header { | |||
int? code; | |||
String? message; | |||
String? sid; | |||
int? status; | |||
Header({this.code, this.message, this.sid, this.status}); | |||
factory Header.fromJson(Map<String, dynamic> json) { | |||
return _$HeaderFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$HeaderToJson(this); | |||
} |
@@ -0,0 +1,21 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'header.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Header _$HeaderFromJson(Map<String, dynamic> json) => Header( | |||
code: (json['code'] as num?)?.toInt(), | |||
message: json['message'] as String?, | |||
sid: json['sid'] as String?, | |||
status: (json['status'] as num?)?.toInt(), | |||
); | |||
Map<String, dynamic> _$HeaderToJson(Header instance) => <String, dynamic>{ | |||
'code': instance.code, | |||
'message': instance.message, | |||
'sid': instance.sid, | |||
'status': instance.status, | |||
}; |
@@ -0,0 +1,19 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'recognition_results.dart'; | |||
part 'payload.g.dart'; | |||
@JsonSerializable() | |||
class Payload { | |||
@JsonKey(name: 'recognition_results') | |||
RecognitionResults? recognitionResults; | |||
Payload({this.recognitionResults}); | |||
factory Payload.fromJson(Map<String, dynamic> json) { | |||
return _$PayloadFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$PayloadToJson(this); | |||
} |
@@ -0,0 +1,18 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'payload.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Payload _$PayloadFromJson(Map<String, dynamic> json) => Payload( | |||
recognitionResults: json['recognition_results'] == null | |||
? null | |||
: RecognitionResults.fromJson( | |||
json['recognition_results'] as Map<String, dynamic>), | |||
); | |||
Map<String, dynamic> _$PayloadToJson(Payload instance) => <String, dynamic>{ | |||
'recognition_results': instance.recognitionResults, | |||
}; |
@@ -0,0 +1,20 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'cw.g.dart'; | |||
@JsonSerializable() | |||
class Cw { | |||
int? rl; | |||
int? sc; | |||
String? w; | |||
int? wb; | |||
int? wc; | |||
int? we; | |||
String? wp; | |||
Cw({this.rl, this.sc, this.w, this.wb, this.wc, this.we, this.wp}); | |||
factory Cw.fromJson(Map<String, dynamic> json) => _$CwFromJson(json); | |||
Map<String, dynamic> toJson() => _$CwToJson(this); | |||
} |
@@ -0,0 +1,27 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'cw.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Cw _$CwFromJson(Map<String, dynamic> json) => Cw( | |||
rl: (json['rl'] as num?)?.toInt(), | |||
sc: (json['sc'] as num?)?.toInt(), | |||
w: json['w'] as String?, | |||
wb: (json['wb'] as num?)?.toInt(), | |||
wc: (json['wc'] as num?)?.toInt(), | |||
we: (json['we'] as num?)?.toInt(), | |||
wp: json['wp'] as String?, | |||
); | |||
Map<String, dynamic> _$CwToJson(Cw instance) => <String, dynamic>{ | |||
'rl': instance.rl, | |||
'sc': instance.sc, | |||
'w': instance.w, | |||
'wb': instance.wb, | |||
'wc': instance.wc, | |||
'we': instance.we, | |||
'wp': instance.wp, | |||
}; |
@@ -0,0 +1,35 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'w.dart'; | |||
part 'recognition_content.g.dart'; | |||
@JsonSerializable() | |||
class RecognitionContent { | |||
int? bg; | |||
int? ed; | |||
bool? ls; | |||
String? pgs; | |||
List<int>? rg; | |||
int? sn; | |||
@JsonKey(name: 'sub_end') | |||
bool? subEnd; | |||
List<W>? ws; | |||
RecognitionContent({ | |||
this.bg, | |||
this.ed, | |||
this.ls, | |||
this.pgs, | |||
this.rg, | |||
this.sn, | |||
this.subEnd, | |||
this.ws, | |||
}); | |||
factory RecognitionContent.fromJson(Map<String, dynamic> json) { | |||
return _$RecognitionContentFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$RecognitionContentToJson(this); | |||
} |
@@ -0,0 +1,35 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'recognition_content.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
RecognitionContent _$RecognitionContentFromJson(Map<String, dynamic> json) => | |||
RecognitionContent( | |||
bg: (json['bg'] as num?)?.toInt(), | |||
ed: (json['ed'] as num?)?.toInt(), | |||
ls: json['ls'] as bool?, | |||
pgs: json['pgs'] as String?, | |||
rg: (json['rg'] as List<dynamic>?) | |||
?.map((e) => (e as num).toInt()) | |||
.toList(), | |||
sn: (json['sn'] as num?)?.toInt(), | |||
subEnd: json['sub_end'] as bool?, | |||
ws: (json['ws'] as List<dynamic>?) | |||
?.map((e) => W.fromJson(e as Map<String, dynamic>)) | |||
.toList(), | |||
); | |||
Map<String, dynamic> _$RecognitionContentToJson(RecognitionContent instance) => | |||
<String, dynamic>{ | |||
'bg': instance.bg, | |||
'ed': instance.ed, | |||
'ls': instance.ls, | |||
'pgs': instance.pgs, | |||
'rg': instance.rg, | |||
'sn': instance.sn, | |||
'sub_end': instance.subEnd, | |||
'ws': instance.ws, | |||
}; |
@@ -0,0 +1,17 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'cw.dart'; | |||
part 'w.g.dart'; | |||
@JsonSerializable() | |||
class W { | |||
int? bg; | |||
List<Cw>? cw; | |||
W({this.bg, this.cw}); | |||
factory W.fromJson(Map<String, dynamic> json) => _$WFromJson(json); | |||
Map<String, dynamic> toJson() => _$WToJson(this); | |||
} |
@@ -0,0 +1,19 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'w.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
W _$WFromJson(Map<String, dynamic> json) => W( | |||
bg: (json['bg'] as num?)?.toInt(), | |||
cw: (json['cw'] as List<dynamic>?) | |||
?.map((e) => Cw.fromJson(e as Map<String, dynamic>)) | |||
.toList(), | |||
); | |||
Map<String, dynamic> _$WToJson(W instance) => <String, dynamic>{ | |||
'bg': instance.bg, | |||
'cw': instance.cw, | |||
}; |
@@ -0,0 +1,20 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'header.dart'; | |||
import 'payload.dart'; | |||
part 'recognition_result.g.dart'; | |||
@JsonSerializable() | |||
class RecognitionResult { | |||
Header? header; | |||
Payload? payload; | |||
RecognitionResult({this.header, this.payload}); | |||
factory RecognitionResult.fromJson(Map<String, dynamic> json) { | |||
return _$RecognitionResultFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$RecognitionResultToJson(this); | |||
} |
@@ -0,0 +1,23 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'recognition_result.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
RecognitionResult _$RecognitionResultFromJson(Map<String, dynamic> json) => | |||
RecognitionResult( | |||
header: json['header'] == null | |||
? null | |||
: Header.fromJson(json['header'] as Map<String, dynamic>), | |||
payload: json['payload'] == null | |||
? null | |||
: Payload.fromJson(json['payload'] as Map<String, dynamic>), | |||
); | |||
Map<String, dynamic> _$RecognitionResultToJson(RecognitionResult instance) => | |||
<String, dynamic>{ | |||
'header': instance.header, | |||
'payload': instance.payload, | |||
}; |
@@ -0,0 +1,19 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'recognition_results.g.dart'; | |||
@JsonSerializable() | |||
class RecognitionResults { | |||
String? encoding; | |||
String? format; | |||
int? status; | |||
String? text; | |||
RecognitionResults({this.encoding, this.format, this.status, this.text}); | |||
factory RecognitionResults.fromJson(Map<String, dynamic> json) { | |||
return _$RecognitionResultsFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$RecognitionResultsToJson(this); | |||
} |
@@ -0,0 +1,23 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'recognition_results.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
RecognitionResults _$RecognitionResultsFromJson(Map<String, dynamic> json) => | |||
RecognitionResults( | |||
encoding: json['encoding'] as String?, | |||
format: json['format'] as String?, | |||
status: (json['status'] as num?)?.toInt(), | |||
text: json['text'] as String?, | |||
); | |||
Map<String, dynamic> _$RecognitionResultsToJson(RecognitionResults instance) => | |||
<String, dynamic>{ | |||
'encoding': instance.encoding, | |||
'format': instance.format, | |||
'status': instance.status, | |||
'text': instance.text, | |||
}; |
@@ -0,0 +1,19 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'header.g.dart'; | |||
@JsonSerializable() | |||
class Header { | |||
int? code; | |||
String? message; | |||
String? sid; | |||
int? status; | |||
Header({this.code, this.message, this.sid, this.status}); | |||
factory Header.fromJson(Map<String, dynamic> json) { | |||
return _$HeaderFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$HeaderToJson(this); | |||
} |
@@ -0,0 +1,21 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'header.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Header _$HeaderFromJson(Map<String, dynamic> json) => Header( | |||
code: (json['code'] as num?)?.toInt(), | |||
message: json['message'] as String?, | |||
sid: json['sid'] as String?, | |||
status: (json['status'] as num?)?.toInt(), | |||
); | |||
Map<String, dynamic> _$HeaderToJson(Header instance) => <String, dynamic>{ | |||
'code': instance.code, | |||
'message': instance.message, | |||
'sid': instance.sid, | |||
'status': instance.status, | |||
}; |
@@ -0,0 +1,19 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'streamtrans_results.dart'; | |||
part 'payload.g.dart'; | |||
@JsonSerializable() | |||
class Payload { | |||
@JsonKey(name: 'streamtrans_results') | |||
StreamtransResults? streamtransResults; | |||
Payload({this.streamtransResults}); | |||
factory Payload.fromJson(Map<String, dynamic> json) { | |||
return _$PayloadFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$PayloadToJson(this); | |||
} |
@@ -0,0 +1,18 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'payload.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Payload _$PayloadFromJson(Map<String, dynamic> json) => Payload( | |||
streamtransResults: json['streamtrans_results'] == null | |||
? null | |||
: StreamtransResults.fromJson( | |||
json['streamtrans_results'] as Map<String, dynamic>), | |||
); | |||
Map<String, dynamic> _$PayloadToJson(Payload instance) => <String, dynamic>{ | |||
'streamtrans_results': instance.streamtransResults, | |||
}; |
@@ -0,0 +1,20 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'header.dart'; | |||
import 'payload.dart'; | |||
part 'streamtrans_result.g.dart'; | |||
@JsonSerializable() | |||
class StreamtransResult { | |||
Header? header; | |||
Payload? payload; | |||
StreamtransResult({this.header, this.payload}); | |||
factory StreamtransResult.fromJson(Map<String, dynamic> json) { | |||
return _$StreamtransResultFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$StreamtransResultToJson(this); | |||
} |
@@ -0,0 +1,23 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'streamtrans_result.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
StreamtransResult _$StreamtransResultFromJson(Map<String, dynamic> json) => | |||
StreamtransResult( | |||
header: json['header'] == null | |||
? null | |||
: Header.fromJson(json['header'] as Map<String, dynamic>), | |||
payload: json['payload'] == null | |||
? null | |||
: Payload.fromJson(json['payload'] as Map<String, dynamic>), | |||
); | |||
Map<String, dynamic> _$StreamtransResultToJson(StreamtransResult instance) => | |||
<String, dynamic>{ | |||
'header': instance.header, | |||
'payload': instance.payload, | |||
}; |
@@ -0,0 +1,28 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'streamtrans_results.g.dart'; | |||
@JsonSerializable() | |||
class StreamtransResults { | |||
String? compress; | |||
String? encoding; | |||
String? format; | |||
String? seq; | |||
int? status; | |||
String? text; | |||
StreamtransResults({ | |||
this.compress, | |||
this.encoding, | |||
this.format, | |||
this.seq, | |||
this.status, | |||
this.text, | |||
}); | |||
factory StreamtransResults.fromJson(Map<String, dynamic> json) { | |||
return _$StreamtransResultsFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$StreamtransResultsToJson(this); | |||
} |
@@ -0,0 +1,27 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'streamtrans_results.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
StreamtransResults _$StreamtransResultsFromJson(Map<String, dynamic> json) => | |||
StreamtransResults( | |||
compress: json['compress'] as String?, | |||
encoding: json['encoding'] as String?, | |||
format: json['format'] as String?, | |||
seq: json['seq'] as String?, | |||
status: (json['status'] as num?)?.toInt(), | |||
text: json['text'] as String?, | |||
); | |||
Map<String, dynamic> _$StreamtransResultsToJson(StreamtransResults instance) => | |||
<String, dynamic>{ | |||
'compress': instance.compress, | |||
'encoding': instance.encoding, | |||
'format': instance.format, | |||
'seq': instance.seq, | |||
'status': instance.status, | |||
'text': instance.text, | |||
}; |
@@ -0,0 +1,21 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'trans_content.g.dart'; | |||
@JsonSerializable() | |||
class TransContent { | |||
String? src; | |||
String? dst; | |||
int? wb; | |||
int? we; | |||
@JsonKey(name: 'is_final') | |||
int? isFinal; | |||
TransContent({this.src, this.dst, this.wb, this.we, this.isFinal}); | |||
factory TransContent.fromJson(Map<String, dynamic> json) { | |||
return _$TransContentFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$TransContentToJson(this); | |||
} |
@@ -0,0 +1,24 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'trans_content.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
TransContent _$TransContentFromJson(Map<String, dynamic> json) => TransContent( | |||
src: json['src'] as String?, | |||
dst: json['dst'] as String?, | |||
wb: (json['wb'] as num?)?.toInt(), | |||
we: (json['we'] as num?)?.toInt(), | |||
isFinal: (json['is_final'] as num?)?.toInt(), | |||
); | |||
Map<String, dynamic> _$TransContentToJson(TransContent instance) => | |||
<String, dynamic>{ | |||
'src': instance.src, | |||
'dst': instance.dst, | |||
'wb': instance.wb, | |||
'we': instance.we, | |||
'is_final': instance.isFinal, | |||
}; |
@@ -0,0 +1,19 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'header.g.dart'; | |||
@JsonSerializable() | |||
class Header { | |||
int? code; | |||
String? message; | |||
String? sid; | |||
int? status; | |||
Header({this.code, this.message, this.sid, this.status}); | |||
factory Header.fromJson(Map<String, dynamic> json) { | |||
return _$HeaderFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$HeaderToJson(this); | |||
} |
@@ -0,0 +1,21 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'header.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Header _$HeaderFromJson(Map<String, dynamic> json) => Header( | |||
code: (json['code'] as num?)?.toInt(), | |||
message: json['message'] as String?, | |||
sid: json['sid'] as String?, | |||
status: (json['status'] as num?)?.toInt(), | |||
); | |||
Map<String, dynamic> _$HeaderToJson(Header instance) => <String, dynamic>{ | |||
'code': instance.code, | |||
'message': instance.message, | |||
'sid': instance.sid, | |||
'status': instance.status, | |||
}; |
@@ -0,0 +1,19 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'tts_results.dart'; | |||
part 'payload.g.dart'; | |||
@JsonSerializable() | |||
class Payload { | |||
@JsonKey(name: 'tts_results') | |||
TtsResults? ttsResults; | |||
Payload({this.ttsResults}); | |||
factory Payload.fromJson(Map<String, dynamic> json) { | |||
return _$PayloadFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$PayloadToJson(this); | |||
} |
@@ -0,0 +1,17 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'payload.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Payload _$PayloadFromJson(Map<String, dynamic> json) => Payload( | |||
ttsResults: json['tts_results'] == null | |||
? null | |||
: TtsResults.fromJson(json['tts_results'] as Map<String, dynamic>), | |||
); | |||
Map<String, dynamic> _$PayloadToJson(Payload instance) => <String, dynamic>{ | |||
'tts_results': instance.ttsResults, | |||
}; |
@@ -0,0 +1,20 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'header.dart'; | |||
import 'payload.dart'; | |||
part 'tts_result.g.dart'; | |||
@JsonSerializable() | |||
class TtsResult { | |||
Header? header; | |||
Payload? payload; | |||
TtsResult({this.header, this.payload}); | |||
factory TtsResult.fromJson(Map<String, dynamic> json) { | |||
return _$TtsResultFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$TtsResultToJson(this); | |||
} |
@@ -0,0 +1,21 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'tts_result.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
TtsResult _$TtsResultFromJson(Map<String, dynamic> json) => TtsResult( | |||
header: json['header'] == null | |||
? null | |||
: Header.fromJson(json['header'] as Map<String, dynamic>), | |||
payload: json['payload'] == null | |||
? null | |||
: Payload.fromJson(json['payload'] as Map<String, dynamic>), | |||
); | |||
Map<String, dynamic> _$TtsResultToJson(TtsResult instance) => <String, dynamic>{ | |||
'header': instance.header, | |||
'payload': instance.payload, | |||
}; |
@@ -0,0 +1,16 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'tts_results.g.dart'; | |||
@JsonSerializable() | |||
class TtsResults { | |||
String? audio; | |||
TtsResults({this.audio}); | |||
factory TtsResults.fromJson(Map<String, dynamic> json) { | |||
return _$TtsResultsFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$TtsResultsToJson(this); | |||
} |
@@ -0,0 +1,16 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'tts_results.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
TtsResults _$TtsResultsFromJson(Map<String, dynamic> json) => TtsResults( | |||
audio: json['audio'] as String?, | |||
); | |||
Map<String, dynamic> _$TtsResultsToJson(TtsResults instance) => | |||
<String, dynamic>{ | |||
'audio': instance.audio, | |||
}; |
@@ -0,0 +1,16 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
part 'data.g.dart'; | |||
@JsonSerializable() | |||
class Data { | |||
String? audio; | |||
String? ced; | |||
int? status; | |||
Data({this.audio, this.ced, this.status}); | |||
factory Data.fromJson(Map<String, dynamic> json) => _$DataFromJson(json); | |||
Map<String, dynamic> toJson() => _$DataToJson(this); | |||
} |
@@ -0,0 +1,19 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'data.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
Data _$DataFromJson(Map<String, dynamic> json) => Data( | |||
audio: json['audio'] as String?, | |||
ced: json['ced'] as String?, | |||
status: (json['status'] as num?)?.toInt(), | |||
); | |||
Map<String, dynamic> _$DataToJson(Data instance) => <String, dynamic>{ | |||
'audio': instance.audio, | |||
'ced': instance.ced, | |||
'status': instance.status, | |||
}; |
@@ -0,0 +1,21 @@ | |||
import 'package:json_annotation/json_annotation.dart'; | |||
import 'data.dart'; | |||
part 'xftts_datamodel.g.dart'; | |||
@JsonSerializable() | |||
class XfttsDatamodel { | |||
int? code; | |||
String? message; | |||
String? sid; | |||
Data? data; | |||
XfttsDatamodel({this.code, this.message, this.sid, this.data}); | |||
factory XfttsDatamodel.fromJson(Map<String, dynamic> json) { | |||
return _$XfttsDatamodelFromJson(json); | |||
} | |||
Map<String, dynamic> toJson() => _$XfttsDatamodelToJson(this); | |||
} |
@@ -0,0 +1,25 @@ | |||
// GENERATED CODE - DO NOT MODIFY BY HAND | |||
part of 'xftts_datamodel.dart'; | |||
// ************************************************************************** | |||
// JsonSerializableGenerator | |||
// ************************************************************************** | |||
XfttsDatamodel _$XfttsDatamodelFromJson(Map<String, dynamic> json) => | |||
XfttsDatamodel( | |||
code: (json['code'] as num?)?.toInt(), | |||
message: json['message'] as String?, | |||
sid: json['sid'] as String?, | |||
data: json['data'] == null | |||
? null | |||
: Data.fromJson(json['data'] as Map<String, dynamic>), | |||
); | |||
Map<String, dynamic> _$XfttsDatamodelToJson(XfttsDatamodel instance) => | |||
<String, dynamic>{ | |||
'code': instance.code, | |||
'message': instance.message, | |||
'sid': instance.sid, | |||
'data': instance.data, | |||
}; |
@@ -2,6 +2,9 @@ import 'dart:async'; | |||
import 'dart:convert'; | |||
import 'dart:math'; | |||
import 'dart:typed_data'; | |||
import 'package:demo001/tools/audio_tool.dart'; | |||
import 'package:demo001/xunfei/recognition_result/recognition_result.dart'; | |||
import 'package:demo001/xunfei/streamtrans_result/streamtrans_result.dart'; | |||
import 'package:intl/intl.dart'; | |||
import 'package:demo001/xunfei/utils.dart'; | |||
import 'package:web_socket_channel/web_socket_channel.dart'; | |||
@@ -22,6 +25,9 @@ class XunFeiTranslate { | |||
Timer? _timer; | |||
XunFeiTranslateTask? currtask; | |||
late Function(RecognitionResult) onRecognitionResult; | |||
late Function(StreamtransResult) onStreamtransResult; | |||
late Function(AudioModel) onAudioResult; | |||
final String appId; | |||
final String apiKey; | |||
@@ -30,22 +36,30 @@ class XunFeiTranslate { | |||
final String requestUri = "/v1/private/simult_interpretation"; | |||
//静态变量保存唯一实例 | |||
static XunFeiTranslate? _instance; | |||
XunFeiTranslate._internal({ | |||
required this.appId, | |||
required this.apiKey, | |||
required this.apiSecret, | |||
}); | |||
XunFeiTranslate._internal( | |||
{required this.appId, | |||
required this.apiKey, | |||
required this.apiSecret, | |||
required this.onRecognitionResult, | |||
required this.onStreamtransResult, | |||
required this.onAudioResult}); | |||
//工厂构造函数 | |||
factory XunFeiTranslate({ | |||
required String appId, | |||
required String apiKey, | |||
required String apiSecret, | |||
required Function(RecognitionResult) onRecognitionResult, | |||
required Function(StreamtransResult) onStreamtransResult, | |||
required Function(AudioModel) onAudioResult, | |||
}) { | |||
_instance ??= XunFeiTranslate._internal( | |||
appId: appId, | |||
apiKey: apiKey, | |||
apiSecret: apiSecret, | |||
onRecognitionResult: onRecognitionResult, | |||
onStreamtransResult: onStreamtransResult, | |||
onAudioResult: onAudioResult, | |||
); | |||
return _instance!; | |||
} | |||
@@ -132,14 +146,16 @@ class XunFeiTranslate { | |||
var state = _checkSpeakingStatus(); | |||
if (state == 1) { | |||
//开始说话 | |||
currtask = XunFeiTranslateTask(_geturl()); | |||
currtask = XunFeiTranslateTask(_geturl(), _handleData); | |||
currtask?.sendaudio(_createParams(0, frame)); | |||
print("发送第一帧---------------------------"); | |||
} else if (state == 2) { | |||
//结束说话 | |||
currtask?.sendaudio(_createParams(1, frame)); | |||
} else if (state == 3) { | |||
//结束说话 | |||
currtask?.sendaudio(_createParams(2, frame)); | |||
print("发送最后一帧---------------------------"); | |||
} | |||
}); | |||
return; | |||
@@ -148,12 +164,17 @@ class XunFeiTranslate { | |||
//结束翻译 | |||
Future<void> stoptranslate() async { | |||
_isrecord = false; | |||
_timer?.cancel(); | |||
_timer = null; | |||
if (currtask != null) { | |||
var _frame = _getAudioData(); | |||
currtask?.sendaudio(_createParams(2, _frame)); | |||
print("发送最后一帧---------------------------"); | |||
currtask = null; | |||
} | |||
_isspeaking = false; | |||
_lastBelowThresholdTime = null; | |||
_buff = Uint8List(0); | |||
return; | |||
} | |||
@@ -224,14 +245,44 @@ class XunFeiTranslate { | |||
return 2; | |||
} | |||
} | |||
//处理返回结果 | |||
void _handleData(dynamic json) { | |||
final status = json['header']['status']; | |||
final sid = json['header']['sid']; | |||
var payload = json['payload']; | |||
if (payload != null) { | |||
payload = json['payload'] as Map<String, dynamic>; | |||
//转文字的结果 | |||
if (payload.containsKey('recognition_results')) { | |||
final model = RecognitionResult.fromJson(json); | |||
if (model.payload?.recognitionResults?.text == null || | |||
model.payload?.recognitionResults?.text?.trim() == '') return; | |||
onRecognitionResult(model); | |||
//翻译好的结果 | |||
} else if (payload.containsKey('streamtrans_results')) { | |||
final model = StreamtransResult.fromJson(json); | |||
if (model.payload?.streamtransResults?.text == null || | |||
model.payload?.streamtransResults?.text?.trim() == '') return; | |||
onStreamtransResult(model); | |||
//合成语音 | |||
} else if (payload.containsKey('tts_results')) { | |||
final bytes = base64Decode(payload['tts_results']['audio']); | |||
if (bytes.isEmpty) return; | |||
onAudioResult(AudioModel(status: status, sid: sid, data: bytes)); | |||
} | |||
} | |||
if (status == 2) {} | |||
} | |||
} | |||
//讯飞翻译任务 | |||
class XunFeiTranslateTask { | |||
late WebSocketChannel _channel; | |||
bool isconnected = false; | |||
late Function(dynamic) handle; | |||
XunFeiTranslateTask(String url) { | |||
XunFeiTranslateTask(String url, Function(dynamic) handle) { | |||
_channel = WebSocketChannel.connect(Uri.parse(url)); | |||
_channel.stream.timeout(Duration(seconds: 10)); //设置超时时间 | |||
_channel.stream.listen( | |||
@@ -251,6 +302,7 @@ class XunFeiTranslateTask { | |||
cancelOnError: true, | |||
); | |||
isconnected = true; | |||
handle = handle; | |||
} | |||
Future<void> sendaudio(Map<String, dynamic> data) async { | |||
@@ -261,32 +313,13 @@ class XunFeiTranslateTask { | |||
Future<void> onMessage(String message) async { | |||
try { | |||
print("收到的消息:$message"); | |||
// print("收到的消息:$message"); | |||
// 对结果进行解析 | |||
var messageMap = json.decode(message); | |||
var status = messageMap["header"]["status"]; | |||
var sid = messageMap["header"]["sid"]; | |||
// 接收到的识别结果写到文本 | |||
if (messageMap.containsKey('payload') && | |||
messageMap['payload'].containsKey('recognition_results')) { | |||
var result = messageMap['payload']['recognition_results']['text']; | |||
var asrresult = utf8.decode(base64.decode(result)); | |||
} | |||
//接收到的翻译结果写到文本 | |||
if (messageMap.containsKey('payload') && | |||
messageMap['payload'].containsKey('streamtrans_results')) { | |||
var result = messageMap['payload']['streamtrans_results']['text']; | |||
var transresult = utf8.decode(base64.decode(result)); | |||
print("收到翻译结果:$transresult"); | |||
} | |||
if (messageMap.containsKey('payload') && | |||
messageMap['payload'].containsKey('tts_results')) { | |||
var audio = messageMap['payload']['tts_results']['audio']; | |||
var audioData = base64.decode(audio); | |||
print("收到音频结果:${audioData.length}"); | |||
} | |||
handle(messageMap); | |||
if (status == 2) { | |||
print("任务已结束!"); | |||
print("任务已结束!------------------------------------------"); | |||
_channel.sink.close(); | |||
} | |||
} catch (e) { | |||
@@ -6,9 +6,13 @@ | |||
#include "generated_plugin_registrant.h" | |||
#include <audioplayers_linux/audioplayers_linux_plugin.h> | |||
#include <record_linux/record_linux_plugin.h> | |||
void fl_register_plugins(FlPluginRegistry* registry) { | |||
g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar = | |||
fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin"); | |||
audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar); | |||
g_autoptr(FlPluginRegistrar) record_linux_registrar = | |||
fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin"); | |||
record_linux_plugin_register_with_registrar(record_linux_registrar); | |||
@@ -3,6 +3,7 @@ | |||
# | |||
list(APPEND FLUTTER_PLUGIN_LIST | |||
audioplayers_linux | |||
record_linux | |||
) | |||
@@ -6,11 +6,13 @@ import FlutterMacOS | |||
import Foundation | |||
import audio_session | |||
import audioplayers_darwin | |||
import path_provider_foundation | |||
import record_darwin | |||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | |||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) | |||
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) | |||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) | |||
RecordPlugin.register(with: registry.registrar(forPlugin: "RecordPlugin")) | |||
} |
@@ -17,6 +17,70 @@ packages: | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "0.1.24" | |||
audio_waveforms: | |||
dependency: "direct main" | |||
description: | |||
name: audio_waveforms | |||
sha256: "26531204e539708a51a33096a9d509a68f9a748dd1fe1582c5da25add8daa041" | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "1.2.0" | |||
audioplayers: | |||
dependency: "direct main" | |||
description: | |||
name: audioplayers | |||
sha256: "4ca57fd24594af04e93b9b9f1b1739ffb9204dbab7ce8d9b28a02f464456dcca" | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "6.1.1" | |||
audioplayers_android: | |||
dependency: transitive | |||
description: | |||
name: audioplayers_android | |||
sha256: "6c9443ce0a99b29a840f14bc2d0f7b25eb0fd946dc592a1b8a697807d5b195f3" | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "5.0.1" | |||
audioplayers_darwin: | |||
dependency: transitive | |||
description: | |||
name: audioplayers_darwin | |||
sha256: e507887f3ff18d8e5a10a668d7bedc28206b12e10b98347797257c6ae1019c3b | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "6.0.0" | |||
audioplayers_linux: | |||
dependency: transitive | |||
description: | |||
name: audioplayers_linux | |||
sha256: "9d3cb4e9533a12a462821e3f18bd282e0fa52f67ff96a06301d48dd48b82c2d1" | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "4.0.1" | |||
audioplayers_platform_interface: | |||
dependency: transitive | |||
description: | |||
name: audioplayers_platform_interface | |||
sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5" | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "7.0.0" | |||
audioplayers_web: | |||
dependency: transitive | |||
description: | |||
name: audioplayers_web | |||
sha256: "3609bdf0e05e66a3d9750ee40b1e37f2a622c4edb796cc600b53a90a30a2ace4" | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "5.0.1" | |||
audioplayers_windows: | |||
dependency: transitive | |||
description: | |||
name: audioplayers_windows | |||
sha256: "8605762dddba992138d476f6a0c3afd9df30ac5b96039929063eceed416795c2" | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "4.0.0" | |||
boolean_selector: | |||
dependency: transitive | |||
description: | |||
@@ -89,6 +153,14 @@ packages: | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "2.1.3" | |||
file: | |||
dependency: transitive | |||
description: | |||
name: file | |||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "7.0.1" | |||
fixnum: | |||
dependency: transitive | |||
description: | |||
@@ -144,6 +216,14 @@ packages: | |||
description: flutter | |||
source: sdk | |||
version: "0.0.0" | |||
get: | |||
dependency: "direct main" | |||
description: | |||
name: get | |||
sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "4.6.6" | |||
http: | |||
dependency: "direct main" | |||
description: | |||
@@ -176,6 +256,14 @@ packages: | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "0.7.1" | |||
json_annotation: | |||
dependency: "direct main" | |||
description: | |||
name: json_annotation | |||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" | |||
url: "https://pub.dev" | |||
source: hosted | |||
version: "4.9.0" | |||
leak_tracker: | |||
dependency: transitive | |||
description: | |||
@@ -43,6 +43,10 @@ dependencies: | |||
intl: ^0.20.2 | |||
web_socket_channel: ^3.0.2 | |||
http: ^1.3.0 | |||
get: ^4.6.6 | |||
json_annotation: ^4.9.0 | |||
audioplayers: ^6.1.1 | |||
audio_waveforms: ^1.2.0 | |||
dev_dependencies: | |||
flutter_test: | |||
@@ -6,10 +6,13 @@ | |||
#include "generated_plugin_registrant.h" | |||
#include <audioplayers_windows/audioplayers_windows_plugin.h> | |||
#include <permission_handler_windows/permission_handler_windows_plugin.h> | |||
#include <record_windows/record_windows_plugin_c_api.h> | |||
void RegisterPlugins(flutter::PluginRegistry* registry) { | |||
AudioplayersWindowsPluginRegisterWithRegistrar( | |||
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); | |||
PermissionHandlerWindowsPluginRegisterWithRegistrar( | |||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); | |||
RecordWindowsPluginCApiRegisterWithRegistrar( | |||
@@ -3,6 +3,7 @@ | |||
# | |||
list(APPEND FLUTTER_PLUGIN_LIST | |||
audioplayers_windows | |||
permission_handler_windows | |||
record_windows | |||
) | |||