我们能否在派生自 Cloud Firestore 的 Dart [Flutter] 中检索添加了 Duration 的相同更新媒体项?
Can we retrieve the same updated media item with added Duration in Dart [Flutter] which is derived from Cloud Firestore?
我对 Flutter 中 Dart 包的 [audio_service][1] 有疑问。它无法读取当前 MediaItem 的持续时间。正如其官方文档 [此处][2] 中所写,我们被要求创建一个新的 MediaItem 来存储复制的持续时间。如果我们不这样做,那么我们将无法在 [audio_service][1] 播放歌曲时保持进度条。我的意思是,如果它没有歌曲的持续时间值,如果用户点击暂停按钮或停止按钮,它将打破进度条。
现在,我想到了另一种选择来保留持续时间数据。
我使用 [flutter_ffmpeg][3] 及其包之一来读取字符串中的持续时间。然后使用这些代码将 String 转换为 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);
}
我的用例是我创建了服务器应用程序和客户端应用程序。服务器应用程序用于处理,使用插件 flutter_ffmpeg 检索持续时间值并将其存储在 MediaItem 中,然后将其上传到 Cloud Firestore 和 Storage。客户端应用程序用于从 Cloud Firestore 和 Storage 检索数据。
我根据 [官方文档][2] 更新了媒体项目。我打算使用更新的歌曲,所以我不需要再次为当前媒体项目添加持续时间。
我的问题是:
从 Cloud Firestore 下载后,媒体项中包含的数据是否具有相同的持续时间值?我的意思是,我们需要在同一首歌中再次添加持续时间值吗???或者持续时间值已经存储在歌曲中?
[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
好的,我想我知道答案了。
Dart 中 Duration 类型的数据不能上传到 Firestore 中,必须转换成 Timestamp 格式。所以,我存储 Duration 数据的唯一方法是在这个函数 readAudio(File audio)
.
中保留 return 值的字符串值
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; //this data
}
当我从 Cloud Firestore 和 Storage 下载所有歌曲数据时,我应该使用函数 parseDuration(String s)
. 设置并将字符串类型的 Duration 值转换为 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);
}
获得 Duration 值后,我会将其添加到 class 中,这将为我稍后准备的歌曲集合定义 MediaItem。这是我能想到的在 MediaItem 中添加 Duration 值的唯一方法。由于 audio_service 包中的示例文件如 example_playlist.dart
[在 github 存储库中所示],如果歌曲没有持续时间值。
如果 Shuffle button/Repeat 按钮被用户点击,我希望任何专家都能提供另一种获取持续时间值的解决方案,并阻止它错过进度条的位置。如果有任何提示和技巧,我将不胜感激。
非常感谢你。
无论如何,在这 whosebug.com 中帮助过我的人将被视为贡献者,在我的应用程序达到 1.000.000 美元后,我将捐赠其中的 10% 给所有贡献者。这也适用于我在我的项目、任何教程网站和 YouTube 上的视频中使用的 dart 包的作者。他们的名字将列在应用程序内。像这样无偿贡献的人应该得到奖励,如果它很有用,我会很乐意奖励他们。
我的第一个应用程序将于 2022 年 5 月 1 日发布。
我不会告诉应用程序的名称,以保护 Google Play Store 和 Apple App Store 中的唯一名称。
我的原则工作就是你帮我,达到最低收入后我会奖励你5年non-stop
我发现我错在哪里了。
实际上,我们只需要在 init() 函数中添加这些代码:
_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);
}
});
我还应该在函数 setShuffleMode() 中添加这些
@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,
));
}
});
}
}
我不需要使用库 flutter_ffmpeg 读取持续时间值,我只需要在 init()
函数中添加该代码并替换原函数setShuffleMode。我想我必须删除我下面的评论以替代比这个答案难得多的方式。嗯,还是谢谢你。
我对 Flutter 中 Dart 包的 [audio_service][1] 有疑问。它无法读取当前 MediaItem 的持续时间。正如其官方文档 [此处][2] 中所写,我们被要求创建一个新的 MediaItem 来存储复制的持续时间。如果我们不这样做,那么我们将无法在 [audio_service][1] 播放歌曲时保持进度条。我的意思是,如果它没有歌曲的持续时间值,如果用户点击暂停按钮或停止按钮,它将打破进度条。
现在,我想到了另一种选择来保留持续时间数据。
我使用 [flutter_ffmpeg][3] 及其包之一来读取字符串中的持续时间。然后使用这些代码将 String 转换为 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);
}
我的用例是我创建了服务器应用程序和客户端应用程序。服务器应用程序用于处理,使用插件 flutter_ffmpeg 检索持续时间值并将其存储在 MediaItem 中,然后将其上传到 Cloud Firestore 和 Storage。客户端应用程序用于从 Cloud Firestore 和 Storage 检索数据。
我根据 [官方文档][2] 更新了媒体项目。我打算使用更新的歌曲,所以我不需要再次为当前媒体项目添加持续时间。
我的问题是:
从 Cloud Firestore 下载后,媒体项中包含的数据是否具有相同的持续时间值?我的意思是,我们需要在同一首歌中再次添加持续时间值吗???或者持续时间值已经存储在歌曲中?
[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
好的,我想我知道答案了。
Dart 中 Duration 类型的数据不能上传到 Firestore 中,必须转换成 Timestamp 格式。所以,我存储 Duration 数据的唯一方法是在这个函数 readAudio(File audio)
.
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; //this data
}
当我从 Cloud Firestore 和 Storage 下载所有歌曲数据时,我应该使用函数
parseDuration(String s)
. 设置并将字符串类型的 Duration 值转换为 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);
}
example_playlist.dart
[在 github 存储库中所示],如果歌曲没有持续时间值。
如果 Shuffle button/Repeat 按钮被用户点击,我希望任何专家都能提供另一种获取持续时间值的解决方案,并阻止它错过进度条的位置。如果有任何提示和技巧,我将不胜感激。
非常感谢你。
无论如何,在这 whosebug.com 中帮助过我的人将被视为贡献者,在我的应用程序达到 1.000.000 美元后,我将捐赠其中的 10% 给所有贡献者。这也适用于我在我的项目、任何教程网站和 YouTube 上的视频中使用的 dart 包的作者。他们的名字将列在应用程序内。像这样无偿贡献的人应该得到奖励,如果它很有用,我会很乐意奖励他们。
我的第一个应用程序将于 2022 年 5 月 1 日发布。
我不会告诉应用程序的名称,以保护 Google Play Store 和 Apple App Store 中的唯一名称。
我的原则工作就是你帮我,达到最低收入后我会奖励你5年non-stop
我发现我错在哪里了。 实际上,我们只需要在 init() 函数中添加这些代码:
_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,
));
}
});
}
}
我不需要使用库 flutter_ffmpeg 读取持续时间值,我只需要在 init()
函数中添加该代码并替换原函数setShuffleMode。我想我必须删除我下面的评论以替代比这个答案难得多的方式。嗯,还是谢谢你。