Tableview Cell Video Autoplay

Autoplay Video in UITableViewCell hiccupps

So I achieved this smooth scrolling with Texturekit. In case anyone wants to achieve the smooth scrolling here is what I did.

I have created a new UItableViewCell -

#import <UIKit/UIKit.h>
#import <AsyncDisplayKit/AsyncDisplayKit.h>

@interface AutoplayVideoTableViewCell : UITableViewCell {
ASVideoPlayerNode *_videoPlayerNode;
ASControlNode *_likeButtonNode;
ASButtonNode *_muteButtonNode;
UIImage* _fsIcon;
}
- (void)setVideoURL:(NSString*)aVideoURL;
@end

#import "AutoplayVideoTableViewCell.h"
#import "UIImage+Tint.h"

#define AVATAR_IMAGE_HEIGHT 30
#define HORIZONTAL_BUFFER 10
#define VERTICAL_BUFFER 5

@interface AutoplayVideoTableViewCell () <ASVideoPlayerNodeDelegate>
@end

@implementation AutoplayVideoTableViewCell

- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code

_muteButtonNode = [[ASButtonNode alloc] init];
_muteButtonNode.style.width = ASDimensionMakeWithPoints(16.0);
_muteButtonNode.style.height = ASDimensionMakeWithPoints(22.0);
[_muteButtonNode addTarget:self action:@selector(didTapMuteButton) forControlEvents:ASControlNodeEventTouchUpInside];

_videoPlayerNode = [[ASVideoPlayerNode alloc] init];
_videoPlayerNode.delegate = self;
_videoPlayerNode.backgroundColor = [UIColor blackColor];
[self.contentView addSubnode:_videoPlayerNode];

[self setMuteButtonIcon];

_fsIcon = [[UIImage imageNamed:@"fullScreenIcon"] imageTintedWithColor:[UIColor whiteColor]];
}

- (void)setVideoURL:(NSString*)aVideoURL {

//ASVideoNode *videoNode = [[ASVideoNode alloc] init];
CGFloat fullWidth = [UIScreen mainScreen].bounds.size.width;

_videoPlayerNode.view.frame = CGRectMake(0, 0, fullWidth, 200);

[_videoPlayerNode setAssetURL:[NSURL URLWithString:aVideoURL]];
[_videoPlayerNode setGravity:AVLayerVideoGravityResizeAspectFill];
[_videoPlayerNode setShouldAutoPlay:YES];
[_videoPlayerNode setShouldAutoRepeat:NO];
[_videoPlayerNode play];
}

- (void)videoPlayerNodeDidPlayToEnd:(ASVideoPlayerNode *)videoPlayer {
[videoPlayer seekToTime:0];
}

- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
CGFloat fullWidth = [UIScreen mainScreen].bounds.size.width;

_videoPlayerNode.style.width = ASDimensionMakeWithPoints(fullWidth);
// _videoPlayerNode.style.height = ASDimensionMakeWithPoints(200);

ASStackLayoutSpec *bottomControlsStack = [ASStackLayoutSpec horizontalStackLayoutSpec];
bottomControlsStack.spacing = HORIZONTAL_BUFFER;
bottomControlsStack.alignItems = ASStackLayoutAlignItemsCenter;
bottomControlsStack.children = @[_likeButtonNode];

UIEdgeInsets bottomControlsInsets = UIEdgeInsetsMake(HORIZONTAL_BUFFER, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER);
ASInsetLayoutSpec *bottomControlsInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:bottomControlsInsets child:bottomControlsStack];

ASStackLayoutSpec *verticalStack = [ASStackLayoutSpec verticalStackLayoutSpec];
verticalStack.alignItems = ASStackLayoutAlignItemsStretch;
verticalStack.children = @[_videoPlayerNode, bottomControlsInset];
return verticalStack;
}

- (void)setMuteButtonIcon
{
if (_videoPlayerNode.muted) {
[_muteButtonNode setImage:[UIImage imageNamed:@"ico-mute1"] forState:UIControlStateNormal];
} else {
[_muteButtonNode setImage:[UIImage imageNamed:@"ico-unmute1"] forState:UIControlStateNormal];
}
}

- (void)didTapMuteButton
{
_videoPlayerNode.muted = !_videoPlayerNode.muted;
[self setMuteButtonIcon];
}

#pragma mark - ASVideoPlayerNodeDelegate
- (void)didTapVideoPlayerNode:(ASVideoPlayerNode *)videoPlayer
{
if (_videoPlayerNode.playerState == ASVideoNodePlayerStatePlaying) {
_videoPlayerNode.controlsDisabled = !_videoPlayerNode.controlsDisabled;
[_videoPlayerNode pause];
} else {
[_videoPlayerNode play];
}
}

- (NSDictionary *)videoPlayerNodeCustomControls:(ASVideoPlayerNode *)videoPlayer
{
return @{
@"muteControl" : _muteButtonNode
};
}

- (UIImage *)videoPlayerNodeFullScreenButtonImage:(ASVideoPlayerNode *)videoPlayer {
return _fsIcon;
}

- (NSArray *)controlsForControlBar:(NSDictionary *)availableControls
{
NSMutableArray *controls = [[NSMutableArray alloc] init];

if (availableControls[ @(ASVideoPlayerNodeControlTypePlaybackButton) ]) {
[controls addObject:availableControls[ @(ASVideoPlayerNodeControlTypePlaybackButton) ]];
}

if (availableControls[ @(ASVideoPlayerNodeControlTypeElapsedText) ]) {
[controls addObject:availableControls[ @(ASVideoPlayerNodeControlTypeElapsedText) ]];
}

if (availableControls[ @(ASVideoPlayerNodeControlTypeScrubber) ]) {
[controls addObject:availableControls[ @(ASVideoPlayerNodeControlTypeScrubber) ]];
}

if (availableControls[ @(ASVideoPlayerNodeControlTypeDurationText) ]) {
[controls addObject:availableControls[ @(ASVideoPlayerNodeControlTypeDurationText) ]];
}
if (availableControls[ @(ASVideoPlayerNodeControlTypeFullScreenButton) ]) {
[controls addObject:availableControls[ @(ASVideoPlayerNodeControlTypeFullScreenButton) ]];
}

return controls;
}

#pragma mark - Layout
- (ASLayoutSpec*)videoPlayerNodeLayoutSpec:(ASVideoPlayerNode *)videoPlayer forControls:(NSDictionary *)controls forMaximumSize:(CGSize)maxSize
{
ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init];
spacer.style.flexGrow = 1.0;

UIEdgeInsets insets = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);

if (controls[ @(ASVideoPlayerNodeControlTypeScrubber) ]) {
ASDisplayNode *scrubber = controls[ @(ASVideoPlayerNodeControlTypeScrubber) ];
scrubber.style.height = ASDimensionMakeWithPoints(44.0);
scrubber.style.minWidth = ASDimensionMakeWithPoints(0.0);
scrubber.style.maxWidth = ASDimensionMakeWithPoints(maxSize.width);
scrubber.style.flexGrow = 1.0;
}

NSArray *controlBarControls = [self controlsForControlBar:controls];
NSMutableArray *topBarControls = [[NSMutableArray alloc] init];

//Our custom control
if (controls[@"muteControl"]) {
[topBarControls addObject:controls[@"muteControl"]];
}

ASStackLayoutSpec *topBarSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal
spacing:10.0
justifyContent:ASStackLayoutJustifyContentStart
alignItems:ASStackLayoutAlignItemsCenter
children:topBarControls];

ASInsetLayoutSpec *topBarInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:topBarSpec];

ASStackLayoutSpec *controlbarSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal
spacing:10.0
justifyContent:ASStackLayoutJustifyContentStart
alignItems:ASStackLayoutAlignItemsCenter
children: controlBarControls ];
controlbarSpec.style.alignSelf = ASStackLayoutAlignSelfStretch;

ASInsetLayoutSpec *controlbarInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:controlbarSpec];

controlbarInsetSpec.style.alignSelf = ASStackLayoutAlignSelfStretch;

ASStackLayoutSpec *mainVerticalStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical
spacing:0.0
justifyContent:ASStackLayoutJustifyContentStart
alignItems:ASStackLayoutAlignItemsStart
children:@[topBarInsetSpec, spacer, controlbarInsetSpec]];

return mainVerticalStack;

}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];

// Configure the view for the selected state
}

@end

And in the cellforRow method I changed the code

                    if (post.medias.count > 0) {
MediaItem* item = post.medias[0];
if ([item getMediaType] == VIDEO) {

[cell setVideoURL:item.mediaUrl];
// dispatch_async(dispatch_get_main_queue(), ^{

//cell.videoThumbnail.image = nil;

//});
}
}

And it worked like a charm. I'm still trying to figure other things but it will be a enough to start for anyone else. The Code I picked up is from the sample app named ASDKTube [ObjC] from the Texture samples.

Play video on UITableViewCell when it is completely visible

You can use

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
isScrolling = NO;
[homeTabl reloadData];
}

-(void)scrollViewWillBeginDragging:(UIScrollView *)aScrollView
{
isScrolling = YES;
[homeTabl reloadData];
index = -1;
}

And in cellForRowatindexpath

if (fullvisible && index == indexPath.row) {
if (!isScrolling) {

NSLog(@"video index---%d",indexPath.row);

if (index == indexPath.row) {
NSLog(@"video index---%d",indexPath.row);
cell.videoActivity.hidden = NO;

// if (index == indexPath.row) {
NSURL *url = [NSURL URLWithString:[[responsearray objectAtIndex:indexPath.row]valueForKey:@"feed_video"]];

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

dispatch_async(queue, ^{
cell.videoItem = [AVPlayerItem playerItemWithURL:url];

dispatch_sync(dispatch_get_main_queue(), ^{
cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem];
cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer];
cell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[cell.videoItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[cell.videoItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];

cell.avLayer.frame = CGRectMake(5, 9, 310, 310);
[cell.contentView.layer addSublayer: cell.avLayer];
[ cell.videoPlayer play];
[cell.contentView addSubview:cell.videoActivity];
});
});
// }
// else{
// cell.videoActivity.hidden = YES;
// cell.videoPlayer = nil;
// [cell.avLayer removeFromSuperlayer];
// cell.videoItem = nil;
// [cell.videoPlayer pause];
// }
}
}}

else{

cell.videoActivity.hidden = YES;
cell.videoPlayer = nil;
[cell.avLayer removeFromSuperlayer];
cell.videoItem = nil;
[cell.videoPlayer pause];

}

Play Videos in TableViewCell

If you create a custom UITableViewCell, you can add a AVPlayer object to that cell and load it up with a video (some code you can use to start with can be found in this related question).

To be honest though, do not expect responsive or fast UI in your table view if you have 7 videos playing at the same time. This is going to be very taxing on the device (in terms of CPU and battery). And each time the "more" button is touched (to add more videos), you might get even slower performance (mitigated only by if you code things in a friendly way -- e.g. where the player stops when the cell is scrolled offscreen).

Playing a Video in UITableView when it is completely visible

You can prepare the videos on

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

In cellForRowAtIndexPath method check if the current cell is visible by compering the index path with

NSArray *visiblePaths = [tableView indexPathsForVisibleRows];

if yes play it if not stop playing.Depending on the videos and number of videos you can extend this approach with some caching mechanism of course.YOu can preload all the videos if you feel that loading videos on willDisplayCell makes a lag.

A helper function to find if the cell is visible or not.You can call this function in cellForRowatIndexpath.

- (BOOL)isIndexPathVisible:(NSIndexPath*)indexPath
{
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];

for (NSIndexPath *currentIndex in visiblePaths)
{
NSComparisonResult result = [currentIndex compare:currentIndex];

if(result == NSOrderedSame)
{
NSLog(@"Visible");
return YES;
}
}

return NO;
}


Related Topics



Leave a reply



Submit