Методы AVAssetDownloadDelegate для кэширования HLS не вызываются

#ios #objective-c #swift #http-live-streaming #offline-caching

#iOS #objective-c #swift #http-прямая трансляция #автономное кэширование

Вопрос:

Я следовал приведенному здесь руководству по кэшированию HLS, но элемент управления никогда не доходит ни до одного из делегатов ( AVAssetDownloadDelegate ).

Я что-то пропустил? Вот код, который я написал

 - (void)setupAssetDownloader {
    NSURL *assetURL = [NSURL URLWithString:@"STREAMING_HOST/video/hls/3729170.m3u8"];
    AVURLAsset *hlsAsset = [AVURLAsset assetWithURL:assetURL];

    urlSessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"assetDowloadConfigIdentifier"];
    avAssetDownloadSession = [AVAssetDownloadURLSession sessionWithConfiguration:urlSessionConfiguration assetDownloadDelegate:self delegateQueue:[NSOperationQueue mainQueue]];

    // Download movie
    avAssetDownloadTask = [avAssetDownloadSession assetDownloadTaskWithURLAsset:hlsAsset assetTitle:@"downloadedMedia" assetArtworkData:nil options:nil];

//@{AVAssetDownloadTaskMinimumRequiredMediaBitrateKey : @(300000)}


    [avAssetDownloadTask resume];

    AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:avAssetDownloadTask.URLAsset];
    AVPlayer *player = [[AVPlayer alloc ] initWithPlayerItem:playerItem];
    AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc ] init];
    [playerLayer setPlayer:player];
    [playerLayer setFrame:self.view.frame];
    [self.view.layer addSublayer:playerLayer];
    [player play];
}

#pragma mark - AVAssetDownloadDelegate

- (void)URLSession:(NSURLSession *)session assetDownloadTask:(AVAssetDownloadTask *)assetDownloadTask didResolveMediaSelection:(AVMediaSelection *)resolvedMediaSelection {

}
- (void)URLSession:(NSURLSession *)session assetDownloadTask:(AVAssetDownloadTask *)assetDownloadTask didLoadTimeRange:(CMTimeRange)timeRange totalTimeRangesLoaded:(NSArray<NSValue *> *)loadedTimeRanges timeRangeExpectedToLoad:(CMTimeRange)timeRangeExpectedToLoad {
    NSInteger percent = 0;
    for (NSValue *value in loadedTimeRanges) {
        CMTimeRange timeRange = [value CMTimeRangeValue];
        percent  = CMTimeGetSeconds(timeRange.duration) / CMTimeGetSeconds(timeRangeExpectedToLoad.duration);
    }
    percent *= 100;
    NSLog(@"Progress: %ld", (long)percent);
}

- (void)URLSession:(NSURLSession *)session assetDownloadTask:(AVAssetDownloadTask *)assetDownloadTask didFinishDownloadingToURL:(NSURL *)location {
    NSString *localPath = location.relativePath;
    NSLog(@"localPath: %@", localPath);
    // TODO: Play downloaded file
    // IMPORTANT: Don't move this file to another location.
}
 

Комментарии:

1. Это был очень полезный пример, независимо от вопроса. Спасибо!

Ответ №1:

Я запускал код на симуляторе и

Загрузка потоков HLS не поддерживается в симуляторе.

Я понял это, когда использовал метод делегирования, упомянутый ниже.

 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

}
 

И теперь, борясь целый день, я нашел образец от Apple здесь и получил реальную причину проблемы.

Комментарии:

1. Эй, я запускаю тот же код на устройстве, но все равно мои методы делегирования не вызываются, есть идеи?

Ответ №2:

Недавно я столкнулся с теми же симптомами.

Оказывается, в моем приложении был другой объект, который настраивал фоновый сеанс URL.

 let configuration = URLSessionConfiguration.background(withIdentifier: "[id]") 
 

Как только я удалил этот другой сеанс, я начал получать ожидаемые обратные вызовы.

Возможно, где-то задокументировано, что приложение не должно настраивать несколько сеансов фоновой загрузки, но в любом случае это решило мою проблему.