Issue
I have problem with [audio_service][1] of Dart's package inside Flutter. It has trouble in reading the duration of current MediaItem. As written in its official documentation [here][2], we are asked to create a new MediaItem to store the copied duration. If we don't do it, then we won't be able to maintain the progress bar when [audio_service][1] is playing the song. I meant, if it has no duration value of the song, it will break the progress bar if user tap on Pause button or Stop button.
Now, I thought another alternative in order to keep duration data.
I used [flutter_ffmpeg][3], and one of its package to read duration in String. Then use these codes to convert String into Duration:
Future<MediaItem> addDuration(File myAudio) async {
late final MediaItem songInfo;
String duration = "";
await readAudio(myAudio).then((value) => duration = value);
durSong = parseDuration(duration);
songInfo.copyWith(duration: durSong);
log("Duration is $durSong");
log("The current duration for ${songInfo.title} is ${songInfo.duration}");
return songInfo;
}
Future<String> readAudio(File audio) async {
final FlutterFFprobe durReader = FlutterFFprobe();
String duration = "";
await durReader.getMediaInformation(audio.path).then((value) => duration = value.getMediaProperties()!["duration"]);
return duration;
}
Duration parseDuration(String s) {
int hours = 0;
int minutes = 0;
int micros;
List<String> parts = s.split(':');
if (parts.length > 2) {
hours = int.parse(parts[parts.length - 3]);
}
if (parts.length > 1) {
minutes = int.parse(parts[parts.length - 2]);
}
micros = (double.parse(parts[parts.length - 1]) * 1000000).round();
return Duration(hours: hours, minutes: minutes, microseconds: micros);
}
My use case is I created server app and client app. Server app is used to process, retrieve the duration value using plugin flutter_ffmpeg and store it in MediaItem and then upload it to Cloud Firestore and Storage. Client app is used to retrieve data from Cloud Firestore and Storage.
I updated the media item according to [official documentation][2]. I intended to use the updated songs so I don't need to add duration again to current media item.
My question is:
Can the data included inside media item have the same duration value after being downloaded from Cloud Firestore? I meant, do we need to add Duration value again in the same song??? Or the Duration value is already stored within the song?
[1]: https://pub.dev/packages/audio_service
[2]: https://github.com/ryanheise/audio_service/wiki/FAQ#how-do-i-update-an-existing-mediaitem
[3]: https://pub.dev/packages/flutter_ffmpeg
Solution
I found out where I went wrong. Actually, we just need to add these code inside init() function:
_player.durationStream.listen((duration) {
var index = _player.currentIndex;
if (index != null && duration != null) {
final newQueue = queue.value;
final oldMediaItem = newQueue[index];
final newMediaItem = oldMediaItem.copyWith(duration: duration);
newQueue[index] = newMediaItem;
mediaItem.add(newMediaItem);
}
});
@override
Future<void> setShuffleMode(AudioServiceShuffleMode shuffleMode) async {
final enabled = shuffleMode == AudioServiceShuffleMode.all;
if (enabled) {
await _player.shuffle();
await _player.setShuffleModeEnabled(true);
_player.durationStream.listen((duration) {
var index = _player.currentIndex;
if (index != null && duration != null) {
final newQueue = queue.value;
final oldMediaItem = newQueue[index];
final newMediaItem = oldMediaItem.copyWith(duration: duration);
newQueue[index] = newMediaItem;
mediaItem.add(newMediaItem);
playbackState.add(playbackState.value.copyWith(
shuffleMode: shuffleMode,
updatePosition: _player.position,
bufferedPosition: _player.bufferedPosition,
));
}
});
} else {
shuffleMode = AudioServiceShuffleMode.none;
await _player.setShuffleModeEnabled(false);
_player.durationStream.listen((duration) {
var index = _player.currentIndex;
if (index != null && duration != null) {
final newQueue = queue.value;
final oldMediaItem = newQueue[index];
final newMediaItem = oldMediaItem.copyWith(duration: duration);
newQueue[index] = newMediaItem;
mediaItem.add(newMediaItem);
playbackState.add(playbackState.value.copyWith(
shuffleMode: shuffleMode,
updatePosition: _player.position,
bufferedPosition: _player.bufferedPosition,
));
}
});
}
}
I don't need to read the duration value using library flutter_ffmpeg, I just need to add that code inside init()
function and replace the original function setShuffleMode. I think I have to erase my below comment for alternative way which is so much harder than this answer. Well, thank you anyway.
Answered By - Wege
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.