我已经用自定义UITableViewCells创建了一个UITableView。UITableView由通过互联网加载的图像和视频组成。当用户在其中一个UITableViewCell中滚动时,我加载AVPlayer来播放hls视频。为了播放项目,我将hls格式的URL设置为avplayer项目。
self.playerController = [[AVPlayerViewController alloc] init];
NSURL *videoURL = @"https://playeritemvideourl";
self.player = [AVPlayer playerWithURL:url];
self.playerController.player = self.player;
[self.player play];
视频播放,但从触发[self.player play]
的时刻开始,有大约3到5秒的延迟。我如何预缓冲视频到avplayer的当前项,所以当我滚动到特定的UITableViewCell视频立即开始播放?我看了看AVPlayerItem上的preferredForwardBufferDuration
属性,但似乎没有任何区别。任何帮助或建议,感谢!
AVPlayer
在实例化时开始流式传输m3u8。(我注意到这一点,通过监控网络图在调试导航在Xcode。我在没有调用-[play]
的情况下实例化了一个AVPlayer,并且网络处于负载状态。而不是加载AVPlayer
一旦细胞变得可见,实例化AVPlayer
在细胞是可见的,播放内容当它变得可见。
这可以通过首先使用一些数据结构来保存AVPlayer
项来实现。我推荐NSMutableDictionary
,因为我们可以将键设置为我们想要的视频URL,对象可以是已经加载了URL的AVPlayer
。有两种方法来填充结构。你可以在像-viewDidLoad
这样的方法中一次加载它,或者在-scrollViewDidScroll:
中动态加载项目,以确定我们是否接近带有视频的单元格。如果没有太多的内容,用户几乎可以保证观看所有的视频,我会使用前者。如果我们有很多内容要加载,或者如果用户可能不会观看所有的视频,我会使用后者。下面是一个UITableViewController
的例子。
MyTableViewController.h
#import <UIKit/UIKit.h>
#import <AVKit/AVKit.h>
@interface MyTableViewController : UITableViewController
{
NSMutableDictionary *mediaPlayers; // stores the media players, key = NSString with URL, value = AVPlayer
// you don't need mediaKeyIndexPaths or mediaKeyURLs if you are taking the load-all-at-once approach
NSMutableSet *mediaKeyIndexPaths; // set that stores the key NSIndexPaths that trigger loading a media player
NSDictionary *mediaKeyURLs; // dictionary that maps a key NSIndexPath to a URL (NSString), key = NSIndexPath, value = NSString
}
@property (strong, nonatomic) AVPlayerViewController *playerController;
@end
MyTableViewController.m
#import "MyTableViewController.h"
@implementation MyTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// if you want to load all items at once, you can forget mediaKeyIndexPaths and mediaKeyURLs
// and instead just load all of your media here
mediaPlayers = [[NSMutableDictionary alloc] init];
// if taking the load-all-at-once approach, load mediaPlayers like this
// NSString *videoURLString = @"https://playeritemvideourl";
// AVPlayer *player = [AVPlayer playerWithURL:videoURLString];
// [mediaPlayers setObject:player forKey:@"https://playeritemvideourl"];
// lets say that the cell with the media in it is defined here
NSIndexPath *dummyMediaIndexPath = [NSIndexPath indexPathForRow:40 inSection:0];
// calculate an index path that, when visible, will trigger loading the media at dummyMediaIndexPath
NSIndexPath *dummyKeyIndexPath = [NSIndexPath indexPathForRow:dummyMediaIndexPath.row-10
inSection:dummyMediaIndexPath.section];
// add the key index path to the set of key index paths
mediaKeyIndexPaths = [[NSMutableSet alloc] initWithObjects:dummyKeyIndexPath, nil];
// define mediaKeyURLs mapping the key dummyKeyIndexPath to the value of the URL string we want
mediaKeyURLs = [[NSDictionary alloc] initWithObjectsAndKeys:
@"https://playeritemvideourl", dummyKeyIndexPath,
nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TextCell" forIndexPath:indexPath];
// this is the row of dummyMediaIndexPath defined in -viewDidLoad
if (indexPath.row == 40)
{
self.playerController = [[AVPlayerViewController alloc] init];
NSString *videoURLString = @"https://playeritemvideourl";
AVPlayer *player = [mediaPlayers objectForKey:videoURLString]; // load player with URL
if (!player)
{
player = [AVPlayer playerWithURL:[NSURL URLWithString:videoURLString]];
NSLog(@"Video with URL: %@ was not preloaded. Loading now.", videoURLString);
}
self.playerController.player = player;
// [player play];
// present your playerController here
[cell setText:@"Player cell"];
}
else
{
[cell setText:[NSString stringWithFormat:@"Cell #%li", (long)indexPath.row]];
}
return cell;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// get visible rows
NSArray *visibleRows = [self.tableView indexPathsForVisibleRows];
// traverse through rows
for (NSIndexPath *i in visibleRows)
{
// we use an NSSet to quickly determine if i is contained in mediaKeyIndexPaths
if ([mediaKeyIndexPaths containsObject:i])
{
[mediaKeyIndexPaths removeObject:i]; // we only need to load a player once
NSString *videoURLString = [mediaKeyURLs objectForKey:i];
NSLog(@"Preloading URL: %@", videoURLString); // for information purposes only
AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:videoURLString]];
[mediaPlayers setObject:player forKey:videoURLString];
}
}
}
@end
这是我所能做的关于你提供的代码和信息的数量的具体说明。希望这对你有帮助!