cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
1
2
3
4
|
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
import 'package:wow_english/common/request/dao/listen_dao.dart';
import '../../../common/request/exception.dart';
import '../../../models/read_content_entity.dart';
import '../../../utils/loading.dart';
import '../../../utils/toast_util.dart';
part 'repeat_after_content_event.dart';
part 'repeat_after_content_state.dart';
enum VoiceRecordState {
///未知
voiceRecordUnkonw,
///开始录音
voiceRecordStat,
///正在录音
voiceRecording,
///录音结束
voiceRecordEnd
}
enum VoicePlayState {
///未知
unKnow,
///播放中
playing,
///播放完成
completed,
///播放终止
stop
}
class RepeatAfterContentBloc extends Bloc<RepeatAfterContentEvent, RepeatAfterContentState> {
final String courseLessonId;
///是否正在播放视频
bool _videoPlaying = true;
///是否需要录音
bool _isRecord = false;
Map? _voiceTestResult;
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
49
50
|
int _recordNumber = 0;
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
VoiceRecordState _voiceRecordState = VoiceRecordState.voiceRecordUnkonw;
bool get videoPlaying => _videoPlaying;
bool get isRecord => _isRecord;
VoiceRecordState get voiceRecordState => _voiceRecordState;
List<ReadContentEntity?>? _entityList;
List<ReadContentEntity?>? get entityList => _entityList ;
Map? get voiceTestResult => _voiceTestResult;
late MethodChannel methodChannel;
late AudioPlayer audioPlayer;
RepeatAfterContentBloc(this.courseLessonId) : super(RepeatAfterContentInitial()) {
on<VoiceRecordStateChangeEvent>(_voiceRecordStateChange);
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
71
|
on<PostFollowReadContentEvent>(_postFollowReadContent);
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
on<VideoPlayChangeEvent>(_videoPlayStateChange);
on<RecordeVoicePlayEvent>(_recordeVoicePlay);
on<XSVoiceResultEvent>(_voiceXsResult);
on<XSVoiceInitEvent>(_initVoiceSdk);
on<RequestDataEvent>(_requestData);
on<XSVoiceTestEvent>(_voiceXsTest);
on<XSVoiceStopEvent>(_voiceXsStop);
on<VoiceRecordEvent>(_voiceRecord);
on<InitBlocEvent>((event, emit) {
//音频播放器
audioPlayer = AudioPlayer();
audioPlayer.onPlayerStateChanged.listen((event) async {
debugPrint('播放状态变化');
if (event == PlayerState.completed) {
debugPrint('播放完成');
}
if (event == PlayerState.stopped) {
debugPrint('播放结束');
}
if (event == PlayerState.playing) {
debugPrint('正在播放中');
}
if(isClosed) {
return;
}
});
methodChannel = const MethodChannel('wow_english/sing_sound_method_channel');
methodChannel.setMethodCallHandler((call) async {
if (call.method == 'voiceResult') {//评测结果
add(XSVoiceResultEvent(call.arguments));
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
108
|
add(PostFollowReadContentEvent());
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
return;
}
if (call.method == 'voiceStart') {//评测开始
debugPrint('评测开始');
return;
}
if (call.method == 'voiceEnd') {//评测结束
debugPrint('评测结束');
return;
}
if (call.method == 'voiceFail') {//评测失败
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
123
|
showToast('评测失败');
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
return;
}
});
});
}
///请求数据
void _requestData(RequestDataEvent event,Emitter<RepeatAfterContentState> emitter) async {
try {
await loading(() async {
_entityList = await ListenDao.readContent(courseLessonId);
emitter(RequestDataState());
});
} catch (e) {
if (e is ApiException) {
showToast(e.message??'请求失败,请检查网络连接');
}
}
}
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
///跟读结果
void _postFollowReadContent(PostFollowReadContentEvent event,Emitter<RepeatAfterContentState> emitter) async {
try {
await loading(() async {
_entityList = await ListenDao.followResult(_recordNumber.toString(),courseLessonId);
});
} catch (e) {
if (e is ApiException) {
}
}
}
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
void _videoPlayStateChange(VideoPlayChangeEvent event,Emitter<RepeatAfterContentState> emitter) async {
_videoPlaying = !_videoPlaying;
emitter(VideoPlayChangeState());
}
void _voiceRecord(VoiceRecordEvent event,Emitter<RepeatAfterContentState> emitter) async {
_isRecord = !_isRecord;
emitter(VoiceRecordChangeState());
}
void _voiceRecordStateChange(VoiceRecordStateChangeEvent event,Emitter<RepeatAfterContentState> emitter) async {
_voiceRecordState = event.voiceRecordState;
emitter(VoiceRecordStateChange());
}
_initVoiceSdk(XSVoiceInitEvent event,Emitter<RepeatAfterContentState> emitter) async {
methodChannel.invokeMethod('initVoiceSdk',event.data);
}
///先声测试
void _voiceXsTest(XSVoiceTestEvent event,Emitter<RepeatAfterContentState> emitter) async {
await audioPlayer.stop();
methodChannel.invokeMethod(
'startVoice',
{'word':event.testWord,'type':event.type,'userId':event.userId.toString()}
);
|
cc3b183a
liangchengyou
feat:ios启动图/logo
|
185
|
_recordNumber++;
|
cb38bc90
liangchengyou
feat:视频跟读逻辑处理
|
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
emitter(XSVoiceTestState());
}
///终止评测
void _voiceXsStop(XSVoiceStopEvent event,Emitter<RepeatAfterContentState> emitter) async {
methodChannel.invokeMethod('stopVoice');
}
///先声评测结果
void _voiceXsResult(XSVoiceResultEvent event,Emitter<RepeatAfterContentState> emitter) async {
final Map args = event.message as Map;
final result = args['result'] as Map;
final overall = result['overall'].toString()??'';
final audioUrl = args['audioUrl'].toString()??'';
_voiceTestResult = {'overall':overall,'audioUrl':audioUrl};
emitter(XSVoiceTestState());
}
///播放声音
void _recordeVoicePlay(RecordeVoicePlayEvent event,Emitter<RepeatAfterContentState> emitter) async {
await audioPlayer.stop();
assert(event.audioUrl.isNotEmpty);
await audioPlayer.play(UrlSource(event.audioUrl));
}
}
|