Flutter 如何使用audio_服务和just_audio查找颤振中的当前歌曲时长

Flutter 如何使用audio_服务和just_audio查找颤振中的当前歌曲时长,flutter,dart,audio,just-audio,Flutter,Dart,Audio,Just Audio,当您在中设置MediaItem时,您还不知道歌曲的持续时间,因为此时还没有变化告诉您 用户可以这样更新MediaItem: modifiedMediaItem=mediaItem.copyWith(持续时间:持续时间); AudioServiceBackground.setMediaItem(modifiedMediaItem); 但我不清楚如何或在何处这样做。通过提供预计算时间,可以避免这个问题。() 如何以及在何处将持续时间从just_audio传输到audio_service,以便它可以

当您在中设置
MediaItem
时,您还不知道歌曲的持续时间,因为此时还没有变化告诉您

用户可以这样更新
MediaItem

modifiedMediaItem=mediaItem.copyWith(持续时间:持续时间);
AudioServiceBackground.setMediaItem(modifiedMediaItem);
但我不清楚如何或在何处这样做。通过提供预计算时间,可以避免这个问题。()

如何以及在何处将持续时间从just_audio传输到audio_service,以便它可以更新侦听器

我发现了一些有效的方法,因此我在下面添加了一个答案。

一旦您设置了
AudioPlayer
,您就可以监听持续时间流中的更改,然后在那里进行更新:

\u player.durationStream.listen((持续时间){
最终歌曲索引=_player.playbackEvent.currentIndex;
打印('当前索引:$songIndex,持续时间:$duration');
final modifiedMediaItem=mediaItem.copyWith(持续时间:持续时间);
_队列[songIndex]=modifiedMediaItem;
setMediaItem(_队列[songIndex]);
AudioServiceBackground.setQueue(_queue);
});
注释

  • 这是您的
    BackgroundAudioTask
    类中的内容
  • 当我尝试直接使用
    \u player.currentIndex
    时,我得到了奇怪的行为(在索引开始增加之前,前两首歌的索引都是
    0
    )。这就是为什么我在这里使用回放事件来获取当前索引
  • 在我的示例中,我使用了队列的
    列表。我实际上不需要在最后一行中使用setQueue,因为by-UI没有监听队列中的更改,但我认为这样做还是不错的
更完整的代码示例 这是我的整个
后台音频服务.dart
供参考。这是对以下内容的改编:

导入'dart:async';
导入“package:audio_service/audio_service.dart”;
导入“包:audio_session/audio_session.dart”;
导入“包:just_audio/just_audio.dart”;
void audioPlayerTaskEntrypoint()异步{
运行(()=>AudioPlayerTask());
}
类AudioPlayerTask扩展了BackgroundAudioTask{
AudioPlayer _player=新的AudioPlayer();
音频处理状态_skipState;
StreamSubscription\u eventSubscription;
列表_队列=[];
列表获取队列=>\u队列;
int get index=>\u player.playbackEvent.currentIndex;
MediaItem获取MediaItem=>index==null?null:队列[index];
@凌驾
未来onStart(映射参数)异步{
_加载MediaItemsInToQueue(参数);
等待_setAudioSession();
_PropogateEventsFromAudioPlayerToudioServiceClient();
_对状态传输执行特殊处理();
_loadQueue();
}
void _loadMediaItemsIntoQueue(映射参数){
_queue.clear();
最终列表mediatems=params['data'];
for(mediaItems中的变量项){
final mediaItem=mediaItem.fromJson(项目);
_添加(mediaItem);
}
}
Future\u setAudioSession()异步{
最终会话=等待AudioSession.instance;
wait session.configure(AudioSessionConfiguration.music());
}
void _propogateeventsfromAudioPlayerToudioServiceClients(){
_eventSubscription=\u player.playbackEventStream.listen((事件){
_广播状态();
});
}
void _执行状态转换的特殊处理(){
_player.processingStateStream.listen((状态){
开关(状态){
案例处理状态。已完成:
顶部();
打破
case ProcessingState.ready:
_skipState=null;
打破
违约:
打破
}
});
}
Future\u loadQueue()异步{
设置队列(队列);
试一试{
等待(u player.load)(连接音频资源)(
儿童:
queue.map((item)=>AudioSource.uri(uri.parse(item.id))).toList(),
));
_player.durationStream.listen((持续时间){
_updateQueueWithCurrentDuration(持续时间);
});
onPlay();
}捕获(e){
打印('Error:$e');
顶部();
}
}
void\u updateQueueWithCurrentDuration(持续时间){
最终歌曲索引=_player.playbackEvent.currentIndex;
打印('当前索引:$songIndex,持续时间:$duration');
final modifiedMediaItem=mediaItem.copyWith(持续时间:持续时间);
_队列[songIndex]=modifiedMediaItem;
setMediaItem(_队列[songIndex]);
AudioServiceBackground.setQueue(_queue);
}
@凌驾
未来onSkipToQueueItem(字符串mediaId)异步{
final newIndex=queue.indexWhere((item)=>item.id==mediaId);
如果(newIndex=-1)返回;
_skipState=newIndex>index
?音频处理state.skippingToNext
:AudioProcessingState.skippingToPrevious;
_player.seek(Duration.zero,索引:newIndex);
}
@凌驾
Future onPlay()=>\u player.play();
@凌驾
Future onPause()=>\u player.pause();
@凌驾
Future onSeekTo(持续时间位置)=>_player.seek(位置);
@凌驾
Future onFastForward()=>\u seekRelative(fastForwardInterval);
@凌驾
Future on Rewind()=>\u seekRelative(-rewindInterval);
@凌驾
Future onStop()异步{
等待_player.dispose();
_eventSubscription.cancel();
等待广播状态();
等待super.onStop();
}
///从当前位置跳出[偏移]。
未来相对(持续时间偏移)异步{
var newPosition=_player.position+偏移量;
如果(newPositionmediaItem.duration)newPosition=mediaItem.duration;
等待玩家寻找(新位置);
}
///将当前状态广播到所有客户端。
Future\u broadcastState()异步{
等待AudioServiceBackground.setState(
控制:[
MediaControl.skipToPrevious,
如果(_player.playing)MediaControl.pause else MediaCon