flet-audio-recorder 0.0.1__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flet_audio_recorder/__init__.py +6 -1
- flet_audio_recorder/audio_recorder.py +294 -0
- flet_audio_recorder-0.1.0.dist-info/METADATA +93 -0
- flet_audio_recorder-0.1.0.dist-info/RECORD +16 -0
- {flet_audio_recorder-0.0.1.dist-info → flet_audio_recorder-0.1.0.dist-info}/WHEEL +2 -1
- flet_audio_recorder-0.1.0.dist-info/top_level.txt +2 -0
- flutter/flet_audio_recorder/CHANGELOG.md +3 -0
- flutter/flet_audio_recorder/LICENSE +201 -0
- flutter/flet_audio_recorder/README.md +3 -0
- flutter/flet_audio_recorder/analysis_options.yaml +4 -0
- flutter/flet_audio_recorder/lib/flet_audio_recorder.dart +3 -0
- flutter/flet_audio_recorder/lib/src/audio_recorder.dart +165 -0
- flutter/flet_audio_recorder/lib/src/create_control.dart +17 -0
- flutter/flet_audio_recorder/lib/src/utils/audio_recorder.dart +26 -0
- flutter/flet_audio_recorder/pubspec.lock +799 -0
- flutter/flet_audio_recorder/pubspec.yaml +18 -0
- .DS_Store +0 -0
- flet_audio_recorder/.DS_Store +0 -0
- flet_audio_recorder-0.0.1.dist-info/.DS_Store +0 -0
- flet_audio_recorder-0.0.1.dist-info/METADATA +0 -14
- flet_audio_recorder-0.0.1.dist-info/RECORD +0 -7
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import 'dart:async';
|
|
2
|
+
import 'dart:convert';
|
|
3
|
+
|
|
4
|
+
import 'package:flet/flet.dart';
|
|
5
|
+
import 'package:flutter/widgets.dart';
|
|
6
|
+
import 'package:record/record.dart';
|
|
7
|
+
|
|
8
|
+
import 'utils/audio_recorder.dart';
|
|
9
|
+
|
|
10
|
+
class AudioRecorderControl extends StatefulWidget {
|
|
11
|
+
final Control? parent;
|
|
12
|
+
final Control control;
|
|
13
|
+
final FletControlBackend backend;
|
|
14
|
+
|
|
15
|
+
const AudioRecorderControl(
|
|
16
|
+
{super.key,
|
|
17
|
+
required this.parent,
|
|
18
|
+
required this.control,
|
|
19
|
+
required this.backend});
|
|
20
|
+
|
|
21
|
+
@override
|
|
22
|
+
State<AudioRecorderControl> createState() => _AudioRecorderControlState();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class _AudioRecorderControlState extends State<AudioRecorderControl>
|
|
26
|
+
with FletStoreMixin {
|
|
27
|
+
AudioRecorder? recorder;
|
|
28
|
+
void Function(RecordState)? _onStateChanged;
|
|
29
|
+
StreamSubscription? _onStateChangedSubscription;
|
|
30
|
+
|
|
31
|
+
@override
|
|
32
|
+
void initState() {
|
|
33
|
+
debugPrint("AudioRecorder.initState($hashCode)");
|
|
34
|
+
recorder = widget.control.state["recorder"];
|
|
35
|
+
if (recorder == null) {
|
|
36
|
+
recorder = AudioRecorder();
|
|
37
|
+
recorder = widget.control.state["recorder"] = recorder;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_onStateChangedSubscription = recorder?.onStateChanged().listen((state) {
|
|
41
|
+
_onStateChanged?.call(state);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
widget.control.onRemove.clear();
|
|
45
|
+
widget.control.onRemove.add(_onRemove);
|
|
46
|
+
super.initState();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void _onRemove() {
|
|
50
|
+
debugPrint("AudioRecorder.remove($hashCode)");
|
|
51
|
+
widget.control.state["recorder"]?.dispose();
|
|
52
|
+
widget.backend.unsubscribeMethods(widget.control.id);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@override
|
|
56
|
+
void deactivate() {
|
|
57
|
+
debugPrint("AudioRecorder.deactivate($hashCode)");
|
|
58
|
+
_onStateChangedSubscription?.cancel();
|
|
59
|
+
super.deactivate();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
Future<String?> stopRecording() async {
|
|
63
|
+
debugPrint("AudioRecorder.stopRecording($hashCode)");
|
|
64
|
+
final path = await recorder!.stop();
|
|
65
|
+
return path;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@override
|
|
69
|
+
Widget build(BuildContext context) {
|
|
70
|
+
debugPrint(
|
|
71
|
+
"AudioRecorder build: ${widget.control.id} (${widget.control.hashCode})");
|
|
72
|
+
|
|
73
|
+
int bitRate = widget.control.attrInt("bitRate", 128000)!;
|
|
74
|
+
int sampleRate = widget.control.attrInt("sampleRate", 44100)!;
|
|
75
|
+
int numChannels = widget.control.attrInt("channels", 2)!;
|
|
76
|
+
bool autoGain = widget.control.attrBool("autoGain", false)!;
|
|
77
|
+
bool cancelEcho = widget.control.attrBool("cancelEcho", false)!;
|
|
78
|
+
bool suppressNoise = widget.control.attrBool("suppressNoise", false)!;
|
|
79
|
+
AudioEncoder audioEncoder =
|
|
80
|
+
parseAudioEncoder(widget.control.attrString("audioEncoder", "wav"))!;
|
|
81
|
+
|
|
82
|
+
_onStateChanged = (state) {
|
|
83
|
+
debugPrint("AudioRecorder($hashCode) - state_changed: ${state.name}");
|
|
84
|
+
var s = state.name.toString();
|
|
85
|
+
if (s == "record") {
|
|
86
|
+
s = "recording";
|
|
87
|
+
} else if (s == "pause") {
|
|
88
|
+
s = "paused";
|
|
89
|
+
} else if (s == "stop") {
|
|
90
|
+
s = "stopped";
|
|
91
|
+
}
|
|
92
|
+
widget.backend.triggerControlEvent(widget.control.id, "state_changed", s);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
() async {
|
|
96
|
+
widget.backend.subscribeMethods(widget.control.id,
|
|
97
|
+
(methodName, args) async {
|
|
98
|
+
switch (methodName) {
|
|
99
|
+
case "start_recording":
|
|
100
|
+
if (await recorder!.hasPermission()) {
|
|
101
|
+
if (args["outputPath"] != null) {
|
|
102
|
+
await recorder!.start(
|
|
103
|
+
RecordConfig(
|
|
104
|
+
encoder: audioEncoder,
|
|
105
|
+
bitRate: bitRate,
|
|
106
|
+
sampleRate: sampleRate,
|
|
107
|
+
numChannels: numChannels,
|
|
108
|
+
autoGain: autoGain,
|
|
109
|
+
echoCancel: cancelEcho,
|
|
110
|
+
noiseSuppress: suppressNoise,
|
|
111
|
+
),
|
|
112
|
+
path: args["outputPath"]!);
|
|
113
|
+
return "true";
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
case "stop_recording":
|
|
119
|
+
debugPrint("AudioRecorder.stopRecording($hashCode)");
|
|
120
|
+
String? out = await recorder!.stop();
|
|
121
|
+
return out;
|
|
122
|
+
case "cancel_recording":
|
|
123
|
+
debugPrint("AudioRecorder.cancelRecording($hashCode)");
|
|
124
|
+
await recorder!.cancel();
|
|
125
|
+
case "resume_recording":
|
|
126
|
+
debugPrint("AudioRecorder.resumeRecording($hashCode)");
|
|
127
|
+
await recorder!.resume();
|
|
128
|
+
case "pause_recording":
|
|
129
|
+
debugPrint("AudioRecorder.pauseRecording($hashCode)");
|
|
130
|
+
await recorder!.pause();
|
|
131
|
+
case "is_supported_encoder":
|
|
132
|
+
debugPrint("AudioRecorder.isEncoderSupported($hashCode)");
|
|
133
|
+
if (parseAudioEncoder(args["encoder"]) != null) {
|
|
134
|
+
bool isSupported = await recorder!.isEncoderSupported(
|
|
135
|
+
parseAudioEncoder(args["encoder"]) ?? AudioEncoder.wav);
|
|
136
|
+
return isSupported.toString();
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case "is_paused":
|
|
140
|
+
debugPrint("AudioRecorder.isPaused($hashCode)");
|
|
141
|
+
bool isPaused = await recorder!.isPaused();
|
|
142
|
+
return isPaused.toString();
|
|
143
|
+
case "is_recording":
|
|
144
|
+
debugPrint("AudioRecorder.isRecording($hashCode)");
|
|
145
|
+
bool isRecording = await recorder!.isRecording();
|
|
146
|
+
return isRecording.toString();
|
|
147
|
+
case "has_permission":
|
|
148
|
+
debugPrint("AudioRecorder.hasPermission($hashCode)");
|
|
149
|
+
bool hasPermission = await recorder!.hasPermission();
|
|
150
|
+
return hasPermission.toString();
|
|
151
|
+
case "get_input_devices":
|
|
152
|
+
debugPrint("AudioRecorder.getInputDevices($hashCode)");
|
|
153
|
+
List<InputDevice> devices = await recorder!.listInputDevices();
|
|
154
|
+
String devicesJson = json.encode(devices.asMap().map((key, value) {
|
|
155
|
+
return MapEntry(key, (value.id, value.label));
|
|
156
|
+
}).toString());
|
|
157
|
+
return devicesJson;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
});
|
|
161
|
+
}();
|
|
162
|
+
|
|
163
|
+
return const SizedBox.shrink();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import 'package:flet/flet.dart';
|
|
2
|
+
|
|
3
|
+
import 'audio_recorder.dart';
|
|
4
|
+
|
|
5
|
+
CreateControlFactory createControl = (CreateControlArgs args) {
|
|
6
|
+
switch (args.control.type) {
|
|
7
|
+
case "audiorecorder":
|
|
8
|
+
return AudioRecorderControl(
|
|
9
|
+
parent: args.parent, control: args.control, backend: args.backend);
|
|
10
|
+
default:
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
void ensureInitialized() {
|
|
16
|
+
// nothing to do
|
|
17
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import 'package:record/record.dart';
|
|
2
|
+
|
|
3
|
+
AudioEncoder? parseAudioEncoder(String? encoding) {
|
|
4
|
+
switch (encoding?.toLowerCase()) {
|
|
5
|
+
case "aaclc":
|
|
6
|
+
return AudioEncoder.aacLc;
|
|
7
|
+
case "aaceld":
|
|
8
|
+
return AudioEncoder.aacEld;
|
|
9
|
+
case "aache":
|
|
10
|
+
return AudioEncoder.aacHe;
|
|
11
|
+
case "amrnb":
|
|
12
|
+
return AudioEncoder.amrNb;
|
|
13
|
+
case "amrwb":
|
|
14
|
+
return AudioEncoder.amrWb;
|
|
15
|
+
case "opus":
|
|
16
|
+
return AudioEncoder.opus;
|
|
17
|
+
case "flac":
|
|
18
|
+
return AudioEncoder.flac;
|
|
19
|
+
case "wav":
|
|
20
|
+
return AudioEncoder.wav;
|
|
21
|
+
case "pcm16bits":
|
|
22
|
+
return AudioEncoder.pcm16bits;
|
|
23
|
+
default:
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|