這個賞金已經結束。此問題的答案有資格獲得 150聲望賞金。賞金寬限期在7 小時后結束。 stefanosn正在尋找一個規范的答案。
我創建了一個帶有自定義 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 時,視頻會立即開始播放?我查看preferredForwardBufferDuration了 AVPlayerItem 上的屬性,但似乎沒有任何區別。任何幫助或建議表示贊賞!
uj5u.com熱心網友回復:
AVPlayer實體化時開始流式傳輸 m3u8。(我通過在 Xcode 的除錯導航器中監視網路圖注意到了這一點。我在沒有呼叫的情況下實體化了一個 AVPlayer,-[play]并且網路處于負載狀態。)AVPlayer一旦單元變得可見,就不要加載,而是在單元可見之前實體化并播放內容可見時。AVPlayer
這可以通過首先讓一些資料結構保存AVPlayer專案來實作。我會推薦一個NSMutableDictionary,因為我們可以將密鑰設定為我們想要的視頻 URL,并且物件可以是AVPlayer已經加載了 URL 的物件。有兩種填充結構的方法。您可以使用類似的方法一次性加載所有內容,也可以-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
這與您提供的代碼和資訊的數量一樣具體。希望這可以幫助!
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/467599.html
