Objective c 跳到AVQueuePlayer上的上一个AVPlayerItem/播放队列中的选定项目
我正在播放一个电视节目,该节目已被切割成不同的章节,我的项目使用的是AVQueuePlayer。 我还想提供跳到上一章/下一章的可能性,或者在AVQueuePlayer已经开始播放时动态选择不同的章节 AVQueuePlayer提供的Objective c 跳到AVQueuePlayer上的上一个AVPlayerItem/播放队列中的选定项目,objective-c,avplayer,skip,avqueueplayer,movieplayer,Objective C,Avplayer,Skip,Avqueueplayer,Movieplayer,我正在播放一个电视节目,该节目已被切割成不同的章节,我的项目使用的是AVQueuePlayer。 我还想提供跳到上一章/下一章的可能性,或者在AVQueuePlayer已经开始播放时动态选择不同的章节 AVQueuePlayer提供的advanceToNextItem可以跳到下一个项目,但是从队列中跳回或播放某个项目没有任何相似之处 因此,我不太确定这里最好的方法是什么: 使用AVPlayer而不是AVQueuePlayer,在actionAtItemEnd处调用replaceCurrentIt
advanceToNextItem
可以跳到下一个项目,但是从队列中跳回或播放某个项目没有任何相似之处
因此,我不太确定这里最好的方法是什么:
actionAtItemEnd
处调用replaceCurrentItemWithPlayerItem:
来播放下一个片段,只需使用“replaceCurrentItemWithPlayerItem”让用户选择某个章节如果有人知道在哪里可以买到提供该功能的IOS VideoPlayerFramework,我也会很感激这个链接 如果您希望您的程序可以播放上一个项目并播放playeritems(NSArray)中选定的项目,您可以这样做
- (void)playAtIndex:(NSInteger)index
{
[player removeAllItems];
for (int i = index; i <playerItems.count; i ++) {
AVPlayerItem* obj = [playerItems objectAtIndex:i];
if ([player canInsertItem:obj afterItem:nil]) {
[obj seekToTime:kCMTimeZero];
[player insertItem:obj afterItem:nil];
}
}
}
-(void)playatinex:(NSInteger)索引
{
[player removeAllItems];
对于(int i=index;i第一个答案从AVQueuePlayer中删除所有项,并从作为索引arg传递的迭代开始重新填充队列。这将使用前一项启动新填充的队列(假设传递了正确的索引)以及从该点开始的现有playerItems数组中的其他项,但它不允许多次反转,例如,您在第10轨道上,希望返回并重放第9轨道,然后重放第5轨道,上面的操作您无法完成。但在这里您可以
-(IBAction) prevSongTapped: (id) sender
{
if (globalSongCount>1){ //keep running tally of items already played
[self resetAVQueue]; //removes all items from AVQueuePlayer
for (int i = 1; i < globalSongCount-1; i++){
[audioQueuePlayer advanceToNextItem];
}
globalSongCount--;
[audioQueuePlayer play];
}
}
-(iAction)发送方:(id)发送方
{
如果(globalSongCount>1){//继续运行已播放项目的计数
[self resetAVQueue];//从AVQueuePlayer中删除所有项目
对于(int i=1;i
以下代码允许您跳转到游戏中的任何项目。无playerhead前进。简单明了。playerItemList是包含AVPlayerItem对象的NSArray
- (void)playAtIndex:(NSInteger)index
{
[audioPlayer removeAllItems];
AVPlayerItem* obj = [playerItemList objectAtIndex:index];
[obj seekToTime:kCMTimeZero];
[audioPlayer insertItem:obj afterItem:nil];
[audioPlayer play];
}
创建了一个子类AVQueuePlayer
,该子类正好提供此功能
你可以在电视上找到它
我还没有对它进行测试,但通过浏览代码,它似乎完成了工作。此外,代码有很好的文档记录,因此它至少可以作为自定义功能实现的一个很好的参考(我建议使用类别,而不是子类化).如果您想使用AVQueuePlayer播放任何索引中的歌曲。下面的代码可以帮助您
NSMutableArray *musicListarray (add song that you want to play in queue);
AVQueuePlayer *audioPlayer;
AVPlayerItem *item;
-(void) nextTapped
{
nowPlayingIndex = nowPlayingIndex + 1;
if (nowPlayingIndex > musicListarray.count)
{
}
else
{
[self playTrack];
}
}
-(void) playback
{
if (nowPlayingIndex < 0)
{
}
else
{
nowPlayingIndex = nowPlayingIndex - 1;
[self playTrack];
}
}
-(void) playTrack
{
@try
{
if (musicArray.count > 0)
{
item =[[AVPlayerItem alloc] initWithURL: [NSURL URLWithString:musicListarray
[nowPlayingIndex]]];
[audioPlayer replaceCurrentItemWithPlayerItem:item];
[audioPlayer play];
}
}
@catch (NSException *exception)
{
}
}
-(void) PlaySongAtIndex
{
//yore code...
nowPlayingIndex = i (stating index from queue)[audioPlayer play];
[self playTrack];
}
NSMutableArray*musicListarray(添加要在队列中播放的歌曲);
AVQueuePlayer*音频播放器;
AVPlayerItem*项目;
-(作废)下一页
{
nowPlayingIndex=nowPlayingIndex+1;
如果(正在播放索引>MusicListaray.count)
{
}
其他的
{
[自行播放曲目];
}
}
-(void)回放
{
如果(正在播放索引<0)
{
}
其他的
{
nowPlayingIndex=nowPlayingIndex-1;
[自行播放曲目];
}
}
-(无效)播放曲目
{
@试一试
{
如果(musicArray.count>0)
{
item=[[AVPlayerItem alloc]initWithURL:[NSURL URLWithString:MusicListaray
[nowPlayingIndex]];
[audioPlayer用PlayerItem替换当前项:项];
[音频播放器播放];
}
}
@捕获(NSException*异常)
{
}
}
-(无效)播放歌曲索引
{
//过去的代码。。。
nowPlayingIndex=i(从队列中声明索引)[audioPlayer播放];
[自行播放曲目];
}
这里播放歌曲当你想播放歌曲时,请拨打电话。@saiday的答案对我来说很有效,这里是他的答案的快速版本
func play(at index: Int) {
queue.removeAllItems()
for i in index..<items.count {
let obj: AVPlayerItem? = items[i]
if queue.canInsert(obj!, after: nil) {
obj?.seek(to: kCMTimeZero, completionHandler: nil)
queue.insert(obj!, after: nil)
}
}
}
func播放(索引为Int){
queue.removeAllItems()
对于索引中的i..这应该是AVQueuePlayer对象的责任,而不是视图控制器本身,因此您应该使其可重用,并通过扩展公开其他answers实现,并以类似advanceToNextItem()的方式使用它:
维护索引的一种方法是观察每个视频项目的AVPlayerItemDidPlayToEndTime通知:
func addDidFinishObserver() {
queuePlayer.items().forEach { item in
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: Notification.Name.AVPlayerItemDidPlayToEndTime, object: item)
}
}
func removeDidFinishObserver() {
queuePlayer.items().forEach { item in
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: item)
}
}
@objc func playerDidFinishPlaying(note: NSNotification) {
if queuePlayer.currentItem == queuePlayer.items().last {
print("last item finished")
} else {
print("item \(currentIndex) finished")
currentIndex += 1
}
}
此观察结果对于其他用例(进度条、当前视频计时器重置…)也非常有用。Swift 5.2
var playerItems=[AVPlayerItem]()
func播放(在itemIndex:Int处){
player.removeAllItems()
对于itemIndex…playerItems.count中的索引{
如果let item=playerItems[安全:索引]{
if player.canInsert(项目,之后:无){
item.seek(收件人:.zero,completionHandler:nil)
玩家。插入(项目,之后:无)
}
}
}
}
谢谢。我也在做类似的事情。但最后我只使用了一个视频文件和一个数组,其中包含指向章节开始时间的指针和seekTo函数。如果你倾向于无间隙播放,你的解决方案似乎是唯一的方法。是否有任何方法可以在不清除队列的情况下执行此操作?这是有意义的。但是每次播放索引歌曲时,您都会从列表中删除所有内容。在这种情况下,为什么不直接使用AVPlayer?我给了您+1票,但AVQueuePlayer没有在索引中搜索项目的方法,这让我很着迷。我可以问一下,您是否有自定义控件来检测用户按了什么,或者您是否以某种方式管理了
self.queuePlayer.advanceToPreviousItem(for: self.currentIndex, with: self.playerItems)
func addDidFinishObserver() {
queuePlayer.items().forEach { item in
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: Notification.Name.AVPlayerItemDidPlayToEndTime, object: item)
}
}
func removeDidFinishObserver() {
queuePlayer.items().forEach { item in
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: item)
}
}
@objc func playerDidFinishPlaying(note: NSNotification) {
if queuePlayer.currentItem == queuePlayer.items().last {
print("last item finished")
} else {
print("item \(currentIndex) finished")
currentIndex += 1
}
}