简体   繁体   English

AVPlayer不显示视频

[英]AVPlayer does not show video

I am trying to play a movie at the beginning of my game. 我正在尝试在游戏开始时播放电影。 I am using AVPlayer to do this. 我正在使用AVPlayer来做到这一点。 My problem is, when I register a KVO to check the status of my AVPlayer, my game proceeds as usual without waiting for the video to load and finish. 我的问题是,当我注册KVO以检查AVPlayer的状态时,我的游戏照常进行,而无需等待视频加载和完成。 As a result, I can only hear the audio from my .mov file and can't see any video (since my game has already started). 结果,我只能听到来自.mov文件的音频,而看不到任何视频(因为我的游戏已经开始)。 I would like the video to load and finish before proceeding with the game. 我希望在继续游戏之前先加载并完成视频。 Here's the code: 这是代码:

    @interface RMVideoView : NSView
{
    NSURL* _videoURL;
    AVPlayer* _player;
    AVPlayerLayer* _playerLayer;
}

@property (nonatomic, readonly, strong) AVPlayer* player;
@property (nonatomic, readonly, strong) AVPlayerLayer* playerLayer;
@property (nonatomic, retain) NSURL* videoURL;
 - (void) play;
@end

static void *RMVideoViewPlayerLayerReadyForDisplay = &RMVideoViewPlayerLayerReadyForDisplay;
static void *RMVideoViewPlayerItemStatusContext = &RMVideoViewPlayerItemStatusContext;

@interface RMVideoView()

- (void)onError:(NSError*)error;
- (void)onReadyToPlay;
- (void)setUpPlaybackOfAsset:(AVAsset *)asset withKeys:(NSArray *)keys;

@end

@implementation RMVideoView

@synthesize player = _player;
@synthesize playerLayer = _playerLayer;
@synthesize videoURL = _videoURL;

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.wantsLayer = YES;
        _player = [[AVPlayer alloc] init];
        [self addObserver:self forKeyPath:@"player.currentItem.status" options:NSKeyValueObservingOptionNew context:RMVideoViewPlayerItemStatusContext];
    }

    return self;
}

- (void) setVideoURL:(NSURL *)videoURL {
    _videoURL = videoURL;

    [self.player pause];
    [self.playerLayer removeFromSuperlayer];

    AVURLAsset *asset = [AVAsset assetWithURL:self.videoURL];

    [asset retain];


    NSArray *assetKeysToLoadAndTest = [NSArray arrayWithObjects:@"playable", @"hasProtectedContent", @"tracks", @"duration", nil];
    [asset loadValuesAsynchronouslyForKeys:assetKeysToLoadAndTest completionHandler:^{
        dispatch_async(dispatch_get_main_queue(),^{
            [self setUpPlaybackOfAsset:asset withKeys:assetKeysToLoadAndTest];
        });
    }];
}

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (context == RMVideoViewPlayerItemStatusContext)
    {
        AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        switch (status)
        {
            case AVPlayerItemStatusUnknown:
                break;
            case AVPlayerItemStatusReadyToPlay:
                [self onReadyToPlay];
                break;
            case AVPlayerItemStatusFailed:
                [self onError:nil];
                break;
        }
    }
    else if (context == RMVideoViewPlayerLayerReadyForDisplay)
    {
        if ([[change objectForKey:NSKeyValueChangeNewKey] boolValue])
        {
            self.playerLayer.hidden = NO;
        }
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark - Private

- (void)onError:(NSError*)error {
    // Notify delegate
}

- (void)onReadyToPlay {
    // Notify delegate
    [self.player play];
}

- (void)setUpPlaybackOfAsset:(AVAsset *)asset withKeys:(NSArray *)keys {
    for (NSString *key in keys) {
        NSError *error = nil;
        if ([asset statusOfValueForKey:key error:&error] == AVKeyValueStatusFailed) {
            [self onError:error];
            return;
        }
    }

    if (!asset.isPlayable || asset.hasProtectedContent) {
        [self onError:nil];
        return;
    }

    if ([[asset tracksWithMediaType:AVMediaTypeVideo] count] != 0)
    {   // Asset has video tracks
        _playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
        self.playerLayer.frame = self.layer.bounds;
        self.playerLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
        self.playerLayer.hidden = NO;
        [self.layer addSublayer:self.playerLayer];
        [self addObserver:self forKeyPath:@"playerLayer.readyForDisplay" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:RMVideoViewPlayerLayerReadyForDisplay];

    }

    // Create a new AVPlayerItem and make it our player's current item.
    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
    [self.player replaceCurrentItemWithPlayerItem:playerItem];
}
#pragma mark - Public

- (void) play {
    [self.player play];
}

@end

I am calling the above code from my entry function's -(void)drawView method this way: 我这样从我的输入函数的-(void)drawView方法调用以上代码:

-(void)drawView
{
   if(playVideo)
    {
        RMVideoView *rmVid = [[RMVideoView alloc]init];

        NSURL* MovieURL;
        NSBundle *bundle = [NSBundle mainBundle];
        if(bundle != nil)
        {
            NSString *moviePath = [bundle pathForResource:@"MyVideoResource" ofType:@"mov"];
            if (moviePath)
            {
                MovieURL = [NSURL fileURLWithPath:moviePath];
                [MovieURL retain];
                [rmVid setVideoURL:MovieURL];
            }
        }  
        playVideo = kFalse;
    }
}

The call made to [rmVid setVideoURL:MovieURL] returns when KVO is setup and the game runs forward. 设置KVO并且游戏向前运行时,返回对[rmVid setVideoURL:MovieURL]的调用。 Please help! 请帮忙!

You can listen for a notification, when the video playback reaches the end like this: 当视频播放结束时,您可以收听通知,如下所示:

         AVPlayerItem  *avPlayerItem =[[AVPlayerItem alloc]initWithAsset:avAsset];
         [[NSNotificationCenter defaultCenter] addObserver:self
                                                  selector:@selector(playerItemDidReachedEnd:)
                                                      name:AVPlayerItemDidPlayToEndTimeNotification
                                                    object:avPlayerItem];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AVPlayer未准备就绪,无法显示 - AVPlayer is not readyForDisplay, does not show AVPlayer 元数据图稿未在 tvOS 上显示 - AVPlayer metadata artwork does not show on tvOS 当移动设备变为横向时,在AVPlayer中以全屏显示视频 - Show video in AVPlayer with full screen when mobile is turned to landscape 启动AVPlayer时如何显示暂停的视频而不是黑屏 - How to show paused video instead of black screen when starting AVPlayer UICollectionViewCell中的AVPlayer播放声音但不显示视频 - AVPlayer in UICollectionViewCell plays sound but doesn't show video AVPlayer不播放视频,而是播放带有行的按钮 - AVPlayer does not play Video, play Button with Line through 在AVPlayer中循环远程获取视频会导致重新下载吗? - Does Looping remotely fetched video in AVPlayer cause redownload? 为什么用AVCaptureSession,AVAssetWriter和AVPlayer口吃录制和重放视频? - Why does recording and replaying video with AVCaptureSession, AVAssetWriter and AVPlayer stutter? 如何从 AVPlayer iOS 中的 url 检测视频不存在状态 - How to detect Video does not exist state from url in AVPlayer iOS 当媒体片段数量较少时 AVPlayer 是否播放视频块 - does AVPlayer play the video chunk when number of media segments are less
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM