使用NSURLSession播放远程音频,代码批评

时间:2015-02-07 17:56:45

标签: ios avaudioplayer nsurlsession

首先,为了避免在这里发布大量代码,我创建了一个非常基本的例子来说明我所追求的内容 - https://github.com/opheliadesign/AudioTest

我是iOS开发的新手,我在理解在远程服务器上加载和播放静态MP3文件的最佳方式时遇到了一些麻烦。音频直播,小于一兆字节 - 平均约30秒(它们是无线电调度)。

有人建议我使用NSURLSession加载MP3文件,然后在完成块中播放。这似乎有效,但我有一种感觉,我可以更好地处理它,只是不知道如何。这是我抓住音频并开始播放的块:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:YES];
    NSLog(@"View loaded");
    // Register to receive notification from AppDelegate when entering background
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stopPlayingAudio) name:@"stopPlayingAudio" object:nil];

    // Assign timer to update progress
    self.updateTimer =     [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateSeekBar) userInfo:nil repeats:YES];

    // Demo recording URL
    NSString *recordingUrl = @"https://s3.amazonaws.com/tevfd-recording/All_Fire_and_EMS_2015-02-0214_48_33_630819.mp3";

    NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithURL:[NSURL URLWithString:recordingUrl] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (!error) {
            NSLog(@"No error..");
            self.player = [[AVAudioPlayer alloc]initWithData:data error:nil];
            // Setup slider for track position
            self.slider.minimumValue = 0;
            self.slider.maximumValue = self.player.duration;
            [self.player prepareToPlay];
            [self.player play];
        }
    }]resume];

}

例如,有一个滑块可以在移动时更新玩家的位置。我在完成块中初始化AVAudioPlayer,但在标题中为它创建了一个属性。如果播放器尚未初始化,移动滑块会导致崩溃吗?如果是这样,我该如何更好地处理这个?

另外,我有一个计时器,可以在AVAudioPlayer播放时更新滑块位置。当轨道到达终点时,计时器继续 - 显然这是一个潜在的内存问题。不确定处理此问题的最佳方法,我也希望用户能够在完成后再次开始播放录制内容,例如,如果他们将滑块移动到右侧。

我已经搜索过,无法找到与我正在做的事情有关的任何事情。任何帮助将不胜感激。

更新 这是我最初开始的,但是我在点击UITableView单元格和呈现加载/播放音频的视图之间经历了一些延迟。有几个人提出了NSURLSession。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Get the URL
    NSURL *callAudioURL = [NSURL URLWithString:[self.call objectForKey:@"url"]];
    NSData *callAudioData = [NSData dataWithContentsOfURL:callAudioURL];
    AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithData: callAudioData error:nil];
    self.player = audio;

    self.slider.minimumValue = 0;
    self.slider.maximumValue = self.player.duration;
    [[self player] play];
    self.updateTimer =     [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateSeekBar) userInfo:nil repeats:YES];
}

1 个答案:

答案 0 :(得分:0)

如果您担心一小段延迟,那么下载并缓存 是最好的解决方案。您需要下载音频文件,然后在本地播放。通常,只有当音频非常独特且无法在本地存储时,才能从网络播放或流式传输。

实现类似这样的代码(代码未经测试):

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSFileHandle *hFile = [NSFileHandle fileHandleForWritingAtPath:self.localPath];
//did we succeed in opening the existing file?
if (!hFile) {   //nope->create that file!
   [[NSFileManager defaultManager] createFileAtPath:self.localPath contents:nil attributes:nil];
   //try to open it again...
   hFile = [NSFileHandle fileHandleForWritingAtPath:self.localPath];
}
//did we finally get an accessable file?
if (!hFile) {
   NSLog("could not write to file %@", self.localPath); 
   return;
}

@try {
   //seek to the end of the file
   [hFile seekToEndOfFile];
   //finally write our data to it
   [hFile writeData:data];
} @catch (NSException * e) {
   NSLog("exception when writing to file %@", self.localPath); 
   result = NO;
}
   [hFile closeFile];
}

收到所有数据后,启动音频:

self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:self.localPath error:nil];