Fix URLs with query strings at the end, e.g. ?size=large
Fix HLS Playlists (only support mp4, m4v and mov file extension) Add debug logging for guiding library consumers about why their video is not cached
This commit is contained in:
parent
9f2cb8f92d
commit
c9e2ba0547
@ -311,13 +311,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
[self removePlayerLayer];
|
[self removePlayerLayer];
|
||||||
[self removePlayerTimeObserver];
|
[self removePlayerTimeObserver];
|
||||||
[self removePlayerItemObservers];
|
[self removePlayerItemObservers];
|
||||||
[self playerItemForSource:source withCallback:^(AVPlayerItem * playerItem) {
|
|
||||||
[self didSetPlayerItemWithSource:source playerItem:playerItem];
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) didSetPlayerItemWithSource:(NSDictionary *)source playerItem:(AVPlayerItem *) playerItem
|
|
||||||
{
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
// perform on next run loop, otherwise other passed react-props may not be set
|
// perform on next run loop, otherwise other passed react-props may not be set
|
||||||
@ -433,11 +427,30 @@ static int const RCTVideoUnset = -1;
|
|||||||
|
|
||||||
if (isNetwork) {
|
if (isNetwork) {
|
||||||
#if __has_include(<react-native-video/RCTVideoCache.h>)
|
#if __has_include(<react-native-video/RCTVideoCache.h>)
|
||||||
[_videoCache getItemForUri:uri withCallback:^(AVAsset * _Nullable cachedAsset) {
|
[_videoCache getItemForUri:uri withCallback:^(RCTVideoCacheStatus videoCacheStatus, AVAsset * _Nullable cachedAsset) {
|
||||||
|
switch (videoCacheStatus) {
|
||||||
|
case RCTVideoCacheStatusMissingFileExtension: {
|
||||||
|
#ifdef DEBUG
|
||||||
|
NSLog(@"Could not generate cache key for uri '%@'. It is currently not supported to cache urls that do not include a file extension. The video file will not be cached. Checkout https://github.com/react-native-community/react-native-video/blob/master/docs/caching.md.", uri);
|
||||||
|
#endif
|
||||||
|
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:assetOptions];
|
||||||
|
[self playerItemPrepareText:asset assetOptions:assetOptions withCallback:handler];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case RCTVideoCacheStatusUnsupportedFileExtension: {
|
||||||
|
#ifdef DEBUG
|
||||||
|
NSLog(@"Could not generate cache key for uri '%@'. The file extension of that uri is currently not supported. The video file will not be cached. Checkout https://github.com/react-native-community/react-native-video/blob/master/docs/caching.md.", uri);
|
||||||
|
#endif
|
||||||
|
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:assetOptions];
|
||||||
|
[self playerItemPrepareText:asset assetOptions:assetOptions withCallback:handler];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
if (cachedAsset) {
|
if (cachedAsset) {
|
||||||
[self playerItemPrepareText:cachedAsset assetOptions:assetOptions withCallback:handler];
|
[self playerItemPrepareText:cachedAsset assetOptions:assetOptions withCallback:handler];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
|
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
|
||||||
[assetOptions setObject:cookies forKey:AVURLAssetHTTPCookiesKey];
|
[assetOptions setObject:cookies forKey:AVURLAssetHTTPCookiesKey];
|
||||||
@ -1138,6 +1151,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
#endif
|
#endif
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma mark - RCTVideoPlayerViewControllerDelegate
|
#pragma mark - RCTVideoPlayerViewControllerDelegate
|
||||||
|
@ -57,7 +57,11 @@
|
|||||||
|
|
||||||
- (void)storeItem:(NSData *)data forUri:(NSString *)uri withCallback:(void(^)(BOOL))handler;
|
- (void)storeItem:(NSData *)data forUri:(NSString *)uri withCallback:(void(^)(BOOL))handler;
|
||||||
{
|
{
|
||||||
NSString * key = [[self generateHashForUrl:uri] stringByAppendingPathExtension: [uri pathExtension]];
|
NSString *key = [self generateCacheKeyForUri:uri];
|
||||||
|
if (key == nil) {
|
||||||
|
handler(NO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
[self saveDataToTemporaryStorage:data key:key];
|
[self saveDataToTemporaryStorage:data key:key];
|
||||||
[self.videoCache storeData:data forKey:key locked:NO withCallback:^(SPTPersistentCacheResponse * _Nonnull response) {
|
[self.videoCache storeData:data forKey:key locked:NO withCallback:^(SPTPersistentCacheResponse * _Nonnull response) {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
@ -90,23 +94,68 @@
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)getItemForUri:(NSString *)uri withCallback:(void(^)(AVAsset * _Nullable)) handler {
|
- (NSString *)generateCacheKeyForUri:(NSString *)uri {
|
||||||
NSString * key = [[self generateHashForUrl:uri] stringByAppendingPathExtension: [uri pathExtension]];
|
NSString *uriWithoutQueryParams = uri;
|
||||||
|
|
||||||
|
// parse file extension
|
||||||
|
if ([uri rangeOfString:@"?"].location != NSNotFound) {
|
||||||
|
NSArray<NSString*> * components = [uri componentsSeparatedByString:@"?"];
|
||||||
|
uriWithoutQueryParams = [components objectAtIndex:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString * pathExtension = [uriWithoutQueryParams pathExtension];
|
||||||
|
NSArray * supportedExtensions = @[@"m4v", @"mp4", @"mov"];
|
||||||
|
if ([supportedExtensions containsObject:pathExtension] == NO) {
|
||||||
|
NSDictionary *userInfo = @{
|
||||||
|
NSLocalizedDescriptionKey: NSLocalizedString(@"Missing file extension.", nil),
|
||||||
|
NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Missing file extension.", nil),
|
||||||
|
NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Missing file extension.", nil)
|
||||||
|
};
|
||||||
|
NSError *error = [NSError errorWithDomain:@"RCTVideoCache"
|
||||||
|
code:RCTVideoCacheStatusMissingFileExtension userInfo:userInfo];
|
||||||
|
@throw error;
|
||||||
|
} else if ([pathExtension isEqualToString:@"m3u8"]) {
|
||||||
|
NSDictionary *userInfo = @{
|
||||||
|
NSLocalizedDescriptionKey: NSLocalizedString(@"Missing file extension.", nil),
|
||||||
|
NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Missing file extension.", nil),
|
||||||
|
NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Missing file extension.", nil)
|
||||||
|
};
|
||||||
|
NSError *error = [NSError errorWithDomain:@"RCTVideoCache"
|
||||||
|
code:RCTVideoCacheStatusUnsupportedFileExtension userInfo:userInfo];
|
||||||
|
@throw error;
|
||||||
|
}
|
||||||
|
return [[self generateHashForUrl:uri] stringByAppendingPathExtension:pathExtension];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)getItemForUri:(NSString *)uri withCallback:(void(^)(RCTVideoCacheStatus, AVAsset * _Nullable)) handler {
|
||||||
|
@try {
|
||||||
|
NSString *key = [self generateCacheKeyForUri:uri];
|
||||||
AVURLAsset * temporaryAsset = [self getItemFromTemporaryStorage:key];
|
AVURLAsset * temporaryAsset = [self getItemFromTemporaryStorage:key];
|
||||||
if (temporaryAsset != nil) {
|
if (temporaryAsset != nil) {
|
||||||
handler(temporaryAsset);
|
handler(RCTVideoCacheStatusAvailable, temporaryAsset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.videoCache loadDataForKey:key withCallback:^(SPTPersistentCacheResponse * _Nonnull response) {
|
[self.videoCache loadDataForKey:key withCallback:^(SPTPersistentCacheResponse * _Nonnull response) {
|
||||||
if (response.record == nil || response.record.data == nil) {
|
if (response.record == nil || response.record.data == nil) {
|
||||||
handler(nil);
|
handler(RCTVideoCacheStatusNotAvailable, nil);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[self saveDataToTemporaryStorage:response.record.data key:key];
|
[self saveDataToTemporaryStorage:response.record.data key:key];
|
||||||
handler([self getItemFromTemporaryStorage:key]);
|
handler(RCTVideoCacheStatusAvailable, [self getItemFromTemporaryStorage:key]);
|
||||||
} onQueue:dispatch_get_main_queue()];
|
} onQueue:dispatch_get_main_queue()];
|
||||||
|
} @catch (NSError * err) {
|
||||||
|
switch (err.code) {
|
||||||
|
case RCTVideoCacheStatusMissingFileExtension:
|
||||||
|
handler(RCTVideoCacheStatusMissingFileExtension, nil);
|
||||||
|
return;
|
||||||
|
case RCTVideoCacheStatusUnsupportedFileExtension:
|
||||||
|
handler(RCTVideoCacheStatusUnsupportedFileExtension, nil);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
@throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) generateHashForUrl:(NSString *)string {
|
- (NSString *) generateHashForUrl:(NSString *)string {
|
||||||
|
Loading…
Reference in New Issue
Block a user