【问题标题】:AVQueuePlayer audio not playingAVQueuePlayer 音频未播放
【发布时间】:2014-12-14 08:43:37
【问题描述】:

我有一个AVQueuePlayer 属性,设置如下。 NSLog 语句报告音频应该可以正常播放(在应用程序运行时),但是在模拟器和 iOS 设备本身(iPhone 5s iOS 8.1.1)上进行测试时,没有音频播放。

我已确认该设备未静音,并且处于全音量状态。我正在使用 Xcode 6 和 iOS 8 SDK。我在“链接二进制文件”部分导入了 AVFoundation 框架并将其导入到我的类中。

-(void)viewDidLoad
{
   [super viewDidLoad];
   [self music];
   // other setup code
}


- (void)music
{
    music = [[NSMutableArray alloc]initWithArray:@[
                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM1"
                                                                                                                                        ofType:@"mp3" ]]],

                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM2"
                                                                                                                                        ofType:@"mp3" ]]],
                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM3"
                                                                                                                                        ofType:@"mp3" ]]],

                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM4"
                                                                                                                                        ofType:@"mp3" ]]],
                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM5"
                                                                                                                                        ofType:@"mp3" ]]],

                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM6"
                                                                                                                                        ofType:@"mp3" ]]],



                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM7"
                                                                                                                                        ofType:@"mp3" ]]]



                                                   ]];


    for(AVPlayerItem *a in music)
    {

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:a];

    }

    [music shuffle];

    self.audio  = [[AVQueuePlayer alloc]initWithItems:music];


    [self.audio play];



    NSLog(@"Now playing%@",[self.audio currentItem]);

    NSLog(@"%@",self.audio);









}
-(void)playerItemFinished:(NSNotification *)notification
{
    if([[self.audio currentItem] isEqual:[music lastObject]])
    {

        self.audio = nil;

        [music shuffle];

        self.audio = [[AVQueuePlayer alloc]initWithItems:music];


        [self.audio play];

    }

}

【问题讨论】:

  • 能否显示您的shuffle 方法,在调用initWithItems: 之前调用它,可能是此方法是您的问题的原因。此外,音乐创作可以从initWithArray: 更改为initWithObjects:,因此您不需要创建新的不必要的数组。另外,您可以简单地调用[[NSBundle mainBundle] URLForResource:withExtension:,而不是对该数组中的每个对象调用[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:ofType:]]]
  • 哦...当您说NSLog 报告正在播放正确的文件时,我错过了部分。有点远射,但请尝试实施我给here 的答案。另外,尝试执行我上面的建议,看看它是否有任何改变。

标签: ios objective-c audio avplayer avqueueplayer


【解决方案1】:

尝试以这种方式构建数组:

music = [[NSMutableArray alloc] initWithArray:@[[AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM1" withExtension:@"mp3"]],...]];

编辑: 无论如何,恕我直言,最重要的方面是强调 withExtension 在 ofType 不起作用的情况下起作用的原因:第一个返回由指定名称和文件扩展名标识的资源的文件 URL,其中 -pathForResource:ofType: 返回完整路径名由指定名称和文件扩展名标识的资源。但是,您需要一个 NSURL 对象来初始化 AVPlayer,而 AVQueuePlayer 是 AVPlayer 的子类,用于按顺序播放多个项目。

【讨论】:

    【解决方案2】:

    好吧,我已经根据上面的评论制作了一个代码 sn-p,因此您可以将其复制粘贴到您的项目中。

    我基本上做了 2 处更改。
    数组创建已从 initWithArray: 更改为 initWithObjects:,因此您不会创建新的不必要的、未使用的数组,该数组可能在此方法调用后释放。
    另外,无需对数组中的每个对象调用[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:ofType:]]],只需调用[[NSBundle mainBundle] URLForResource:withExtension:

    music = [[NSMutableArray alloc] initWithObjects:
                              [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM1" withExtension:@"mp3"]],
                              [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM2" withExtension:@"mp3"]],
                              [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM3" withExtension:@"mp3"]],
                              [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM4" withExtension:@"mp3"]],
                              [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"MP5" withExtension:@"mp3"]],
                              [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"MP6" withExtension:@"mp3"]],
                              [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"MP7" withExtension:@"mp3"]],
                              nil];  
    

    祝你好运。

    编辑-
    我不是以英语为母语的人,所以我会尽力说清楚,
    如果有什么不清楚的地方,请告诉我,我会尝试重新表述。

    initWithArray 所做的是使用给定数组的内容创建一个新数组,
    比如:

    NSArray *array1 = [[NSArray alloc] initWithObjects:@"One", @"Two", @"Three", nil]];  
    NSArray *array2 = [[NSArray alloc] initWithArray:array1];  
    

    所以现在array1array2 都有相同的项目。

    如果我没记错的话,自 Xcode 4 以来,引入了一种创建数组的新方法,现在,可以使用 @[] 语法简单地创建包含对象的数组,而不是调用 [[NSArray alloc] initWithObjects:]
    所以我们上面的例子看起来像这样:

    NSArray *array1 = @[@"One", @"Two", @"Three"]; // Notice that 'nil' is not necessary  
    NSArray *array2 = [[NSArray alloc] initWithArray:array2];  
    

    所以你在原始代码中所做的,基本上是调用[[NSMutableArray alloc] initWithObjects:],最终会创建一个新数组,

    然后,使用“新”@[] 语法,您创建了另一个包含所有 AVPlayerItem 对象的新数组,
    并“告诉”music 数组,在其中包含该新数组的内容。

    所以在这“一行”代码中,您实际上创建了 2 个不同的数组。
    “新”未命名数组可能在该行之后被释放的原因是因为您在任何地方都没有对该数组的任何引用(您只是在新创建的数组中引用了它的对象),
    ARC 自动释放引用计数为零的对象。

    您可能不会因此而感到任何内存/性能问题,
    但我认为有必要指出这一点,因为它是不必要的,它不是实现您所尝试的“正确”方法,现在代码看起来更干净、更具可读性。

    顺便说一句-
    这不是您的代码不起作用的原因。
    您的问题在于您的原始代码正在生成NSURL,路径为字符串:/PATH/TO/MY/MP3
    AVPlayerItem 期望路径为 URL:file:///PATH/TO/MY/MP3
    (你可以NSLog新旧调用来验证不同的输出)

    【讨论】:

    • 谢谢,这很有效,虽然我不明白这个问题。为什么不必要的数组被释放了?
    • 印象非常深刻,可能我的评论超出范围
    • @bl4stwave 谢谢伙计。我不确定“评论超出范围”是什么意思(对不起,不是以英语为母语的人),我认为您的回答很好并且确实解决了问题。 +1 给你的回答伙伴。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    • 2023-03-31
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多