Skip to content

Commit d03efd7

Browse files
manoj-simformManoj Padiya
andauthored
fix: šŸ›Update codec issue while recording audio on android (#391)
Co-authored-by: Manoj Padiya <ā€œ[email protected]ā€>
1 parent 2584d34 commit d03efd7

File tree

7 files changed

+87
-71
lines changed

7 files changed

+87
-71
lines changed

ā€ŽCHANGELOG.mdā€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
- Fixed [#386](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/pull/386) - On permission denied isRecording flag changed
44
- Fixed [#384](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/384) - Provide a callback of drag,tap,start and end details on user gesture
55
- Fixed [#309](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/309) - Added support for Liner PCM codec in iOS
6+
- Fixed [#291](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/291) - Codec issue while recording audio on android
7+
- Fixed wrong codec selection on the platform side on both Android and iOS.
68

79
## 1.2.0
810

ā€ŽREADME.mdā€Ž

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ Widget build(BuildContext context) {
133133
#### Function to control recording and waveforms
134134
1. record
135135
```dart
136-
recorderController.record(); // If path isn't provided by default sets current date time as file name m4a is used as file extension.
136+
recorderController.record(); // If a path isn't provided, by default, the current date and time are set as the file name; m4a is used as the file extension.
137137
```
138138
2. pause
139139
```dart
@@ -174,9 +174,9 @@ Widget build(BuildContext context) {
174174
Reported duration is in **milliseconds**.
175175
#### Other available parameters
176176
```dart
177-
recorderController.waveData; // The waveform data in form of normalised peak power for Ios and normalised peak amplitude for Android. The values are between 0.0 and 1.0.
177+
recorderController.waveData; // The waveform data is in the form of normalized peak power for iOS and normalized peak amplitude for Android. The values are between 0.0 and 1.0.
178178
recorderController.elapsedDuration; // Recorded duration of the file.
179-
recorderController.recordedDuration; // Duration of recorded audio file when recording has been stopped. Until recording has been stopped, this duration will be zero(Duration.zero). Also, once new recording is started this duration will be reset to zero.
179+
recorderController.recordedDuration; // Duration of recorded audio file when recording has been stopped. Until recording has been stopped, this duration will be zero (Duration.zero). Also, once a new recording is started, this duration will be reset to zero.
180180
recorderController.hasPermission; // If we have microphone permission or not.
181181
recorderController.isRecording; // If the recorder is currently recording.
182182
recorderController.recorderState; // Current state of the recorder.
@@ -301,16 +301,16 @@ AudioFileWaveforms(
301301

302302
#### Listening to events from the player
303303
```dart
304-
playerController.onPlayerStateChanged.listen((state) {}); // Provides events when the player state changes.
305-
playerController.onCurrentDurationChanged.listen((duration) {}); // Provides events when audio is sought to any duration.
304+
playerController.onPlayerStateChanged.listen((state) {}); // Triggers events when the player state changes.
305+
playerController.onCurrentDurationChanged.listen((duration) {}); // Triggers events when the audio playback position is adjusted to a specific duration.
306306
playerController.onCurrentExtractedWaveformData.listen((data) {}); // Provides latest data while extracting the waveforms.
307307
playerController.onExtractionProgress.listen((progress) {}); // Provides progress of the waveform extractions.
308-
playerController.onCompletion.listen((_){}); // Provides events every time audio file is finished playing.
308+
playerController.onCompletion.listen((_){}); // Triggers events every time when an audio file is finished playing.
309309
```
310310
#### Getting the current or maximum duration of the audio file
311311
```dart
312312
final fileLengthInDuration = await playerController.getDuration(DurationType.max);
313-
final currentDuration = await playerController.getDuration(DurationType.current); // This is where file is paused or an in progress audio files current duration.
313+
final currentDuration = await playerController.getDuration(DurationType.current); // Provides the current duration where the file is in a paused or in-progress state.
314314
```
315315
#### The types of waveforms
316316
1. fitWidth
@@ -346,7 +346,7 @@ final currentDuration = await playerController.getDuration(DurationType.current)
346346
```dart
347347
playerController.updateFrequency = UpdateFrequency.high;
348348
```
349-
There are 3 modes low, medium and high. Setting **updateFrequency** to `high` will update current progress of the playing file faster(every 50ms) which will mame waveform seek animation smooth and `low` makes slower(every 200ms) which could make seek animation a little laggy. You can update this according to device configuration.
349+
There are 3 modes low, medium and high. Setting **updateFrequency** to `high` will update current progress of the playing file faster(every 50ms) which will make waveform seek animation smooth and `low` makes slower(every 200ms) which could make seek animation a little laggy. You can update this according to device configuration.
350350

351351
#### Releasing resources of native player
352352
```dart

ā€Žandroid/src/main/kotlin/com/simform/audio_waveforms/AudioRecorder.ktā€Ž

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,19 @@ class AudioRecorder : PluginRegistry.RequestPermissionsResultListener {
3838
}
3939

4040
fun initRecorder(
41-
path: String,
4241
result: MethodChannel.Result,
4342
recorder: MediaRecorder?,
44-
encoder: Int,
45-
outputFormat: Int,
46-
sampleRate: Int,
47-
bitRate: Int?
43+
recorderSettings: RecorderSettings
4844
) {
4945
recorder?.apply {
5046
setAudioSource(MediaRecorder.AudioSource.MIC)
51-
setOutputFormat(getOutputFormat(outputFormat))
52-
setAudioEncoder(getEncoder(encoder))
53-
setAudioSamplingRate(sampleRate)
54-
if (bitRate != null) {
55-
setAudioEncodingBitRate(bitRate)
47+
setOutputFormat(getOutputFormat(recorderSettings.outputFormat))
48+
setAudioEncoder(getEncoder(recorderSettings.encoder))
49+
setAudioSamplingRate(recorderSettings.sampleRate)
50+
if (recorderSettings.bitRate != null) {
51+
setAudioEncodingBitRate(recorderSettings.bitRate)
5652
}
57-
setOutputFile(path)
53+
setOutputFile(recorderSettings.path)
5854
try {
5955
recorder.prepare()
6056
result.success(true)

ā€Žandroid/src/main/kotlin/com/simform/audio_waveforms/AudioWaveformsPlugin.ktā€Ž

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
2727
private var recorder: MediaRecorder? = null
2828
private var activity: Activity? = null
2929
private lateinit var audioRecorder: AudioRecorder
30-
private var path: String? = null
31-
private var encoder: Int = 0
32-
private var outputFormat: Int = 0
33-
private var sampleRate: Int = 44100
34-
private var bitRate: Int? = null
30+
private var recorderSettings = RecorderSettings(path = null, bitRate = null)
3531
private lateinit var applicationContext: Context
3632
private var audioPlayers = mutableMapOf<String, AudioPlayer?>()
3733
private var extractors = mutableMapOf<String, WaveformExtractor?>()
@@ -48,12 +44,19 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
4844
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
4945
when (call.method) {
5046
Constants.initRecorder -> {
51-
path = call.argument(Constants.path) as String?
52-
encoder = (call.argument(Constants.encoder) as Int?) ?: 0
53-
outputFormat = (call.argument(Constants.outputFormat) as Int?) ?: 0
54-
sampleRate = (call.argument(Constants.sampleRate) as Int?) ?: 44100
55-
bitRate = (call.argument(Constants.bitRate) as Int?)
56-
checkPathAndInitialiseRecorder(result, encoder, outputFormat, sampleRate, bitRate)
47+
val arguments = call.arguments;
48+
if (arguments != null && arguments is Map<*, *>) {
49+
@Suppress("UNCHECKED_CAST")
50+
recorderSettings =
51+
RecorderSettings.fromJson(json = arguments as Map<String, Any?>)
52+
53+
checkPathAndInitialiseRecorder(
54+
result,
55+
recorderSettings
56+
)
57+
} else {
58+
result.error(Constants.LOG_TAG, "Failed to initialise Recorder", "Invalid Arguments")
59+
}
5760
}
5861

5962
Constants.startRecording -> {
@@ -63,7 +66,11 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
6366
}
6467

6568
Constants.stopRecording -> {
66-
audioRecorder.stopRecording(result, recorder, path!!)
69+
audioRecorder.stopRecording(
70+
result,
71+
recorder,
72+
recorderSettings.path!!
73+
)
6774
recorder = null
6875
}
6976

@@ -79,10 +86,10 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
7986
if (key != null) {
8087
initPlayer(key)
8188
audioPlayers[key]?.preparePlayer(
82-
result,
83-
audioPath,
84-
volume?.toFloat(),
85-
frequency?.toLong(),
89+
result,
90+
audioPath,
91+
volume?.toFloat(),
92+
frequency?.toLong(),
8693
)
8794
} else {
8895
result.error(Constants.LOG_TAG, "Player key can't be null", "")
@@ -207,46 +214,36 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
207214
}
208215

209216
private fun checkPathAndInitialiseRecorder(
210-
result: Result,
211-
encoder: Int,
212-
outputFormat: Int,
213-
sampleRate: Int,
214-
bitRate: Int?
217+
result: Result,
218+
recorderSettings: RecorderSettings
215219
) {
216220
try {
217221
recorder = MediaRecorder()
218222
} catch (e: Exception) {
219223
Log.e(Constants.LOG_TAG, "Failed to initialise Recorder")
220224
}
221-
if (path == null) {
225+
if (recorderSettings.path == null) {
222226
val outputDir = activity?.cacheDir
223227
val outputFile: File?
224-
val dateTimeInstance = SimpleDateFormat(Constants.fileNameFormat, Locale.US)
228+
val dateTimeInstance =
229+
SimpleDateFormat(Constants.fileNameFormat, Locale.US)
225230
val currentDate = dateTimeInstance.format(Date())
226231
try {
227232
outputFile = File.createTempFile(currentDate, ".m4a", outputDir)
228-
path = outputFile.path
233+
recorderSettings.path = outputFile.path
229234
audioRecorder.initRecorder(
230-
path!!,
231-
result,
232-
recorder,
233-
encoder,
234-
outputFormat,
235-
sampleRate,
236-
bitRate
235+
result,
236+
recorder,
237+
recorderSettings,
237238
)
238239
} catch (e: IOException) {
239240
Log.e(Constants.LOG_TAG, "Failed to create file")
240241
}
241242
} else {
242243
audioRecorder.initRecorder(
243-
path!!,
244-
result,
245-
recorder,
246-
encoder,
247-
outputFormat,
248-
sampleRate,
249-
bitRate
244+
result,
245+
recorder,
246+
recorderSettings,
250247
)
251248
}
252249
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.simform.audio_waveforms
2+
3+
data class RecorderSettings(
4+
var path: String?,
5+
val encoder: Int = 0,
6+
val outputFormat: Int = 0,
7+
val sampleRate: Int = 44100,
8+
val bitRate: Int?
9+
) {
10+
companion object {
11+
fun fromJson(json: Map<String, Any?>): RecorderSettings {
12+
return RecorderSettings(
13+
path = json[Constants.path] as String?,
14+
encoder = (json[Constants.encoder] as Int?) ?: 0,
15+
outputFormat = (json[Constants.outputFormat] as Int?) ?: 0,
16+
sampleRate = (json[Constants.sampleRate] as Int?) ?: 44100,
17+
bitRate = json[Constants.bitRate] as Int?
18+
)
19+
}
20+
}
21+
}

ā€Žandroid/src/main/kotlin/com/simform/audio_waveforms/Utils.ktā€Ž

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,23 @@ object Constants {
2222

2323

2424
/** encoder */
25-
const val acc = 1
26-
const val aac_eld = 2
27-
const val he_aac = 3
28-
const val opus = 6
29-
const val vorbis = 7
25+
const val acc = 0
26+
const val aac_eld = 1
27+
const val he_aac = 2
28+
const val opus = 5
29+
const val vorbis = 6
3030

3131
/** output format */
32-
const val mpeg4 = 1
33-
const val three_gpp = 2
34-
const val ogg = 3
35-
const val webm = 6
36-
const val mpeg_2_ts = 7
37-
const val aac_adts = 8
32+
const val mpeg4 = 0
33+
const val three_gpp = 1
34+
const val ogg = 2
35+
const val webm = 5
36+
const val mpeg_2_ts = 6
37+
const val aac_adts = 7
3838

3939
/** common */
40-
const val amr_nb = 4
41-
const val amr_wb = 5
40+
const val amr_nb = 3
41+
const val amr_wb = 4
4242

4343
const val preparePlayer = "preparePlayer"
4444
const val startPlayer = "startPlayer"

ā€Žlib/src/controllers/player_controller.dartā€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ class PlayerController extends ChangeNotifier {
223223
notifyListeners();
224224
}
225225

226-
/// A function to stop player. After calling this.
226+
/// A function to stop player.
227227
Future<void> stopPlayer() async {
228228
final isStopped =
229229
await AudioWaveformsInterface.instance.stopPlayer(playerKey);

0 commit comments

Comments
Ā (0)