Search code examples
objective-cmacosavplayernsviewavkit

custom NSView with video player is not showing (MacOS)


I have created a custom NSView with an AVPlayer embedded and it is not showing at all

this is my header:

@interface VideoPlayer : NSView
- (void)loadVideo;
@end

Implementation:

@implementation VideoPlayer

AVPlayer *avPlayer;
AVPlayerLayer* playerLayer;

- (instancetype)initWithFrame:(NSRect)rect {
    self = [super initWithFrame:rect];
    [self setWantsLayer:YES];
    [self setNeedsDisplay:YES];
    self.hidden = NO;
    return self;
}

-(void) loadVideo {
    [avPlayer pause];
    avPlayer = nil;
    playerLayer = nil;

    NSURL *videoURL = [NSURL fileURLWithPath:@"file://~/Documents/tests.mp4"];
    //same error with a valid url
    //NSURL *videoURL = [NSURL URLWithString:@"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4"];

    avPlayer = [AVPlayer playerWithURL:videoURL];
    playerLayer = [AVPlayerLayer playerLayerWithPlayer:avPlayer];
    playerLayer.frame = self.frame;//or your desired CGRect
    playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    //playerLayer.masksToBounds = YES;
    [self.layer addSublayer:playerLayer];

    [avPlayer play];
}

@end

And this is how I am creating the view:

view = [[VideoPlayer alloc] initWithFrame:NSMakeRect(0, 0, 500, 500)];
view.hidden = false;
[view loadVideo];
[parent_view addSubview:view];

I have tried multiple combinations, but the result is always the same... Nothing is being rendered on the application.

On the other hand, if I override the method drawRect in my view like this:

- (void)drawRect:(NSRect)dirtyRect {
         [super drawRect:dirtyRect];
         [[NSColor whiteColor] setFill];
         NSRectFill(dirtyRect);
         [super drawRect:dirtyRect];
}

I am getting a white rectangle where it is suppose to show my video which is expected. So I assume that I am missing something else, but most of the examples are using UIView which is not an option for me at this moment (I am working with some specific constraints)

Any thoughts?

Thank you

Update:

This finally worked for me:

-(void) loadVideo {

    AVPlayer *avPlayer = [AVPlayer playerWithURL:[NSURL URLWithString:@"file://localhost/Users/xxxxxxxx/Documents/xxxxxxx.mp4"]];
    AVPlayerView *playerView = [[AVPlayerView alloc] initWithFrame:self.bounds];
    [playerView setPlayer:avPlayer];
    [self addSubview:playerView];
    [playerView.player play];
}

Solution

    1. Make sure that you add the AVKit framework to your project.
    2. There is a header in AVKit framework called AVPlayerView.h
    3. Then all you need to do to see the player is to call it:
    // **** AVPlayer ***** //
    AVPlayerView *playerView = [[AVPlayerView alloc] initWithFrame:NSMakeRect( 0, 0, _wndW, _wndH - 100)];
    [[window contentView] addSubview:playerView];
    

    I have a programmatic demo which I could post if you are unable to get it to work.