sprite-kit avplayer skvideonode

sprite kit - La reproducción de video en un SKVideoNode causa un destello negro antes de que comience la reproducción



sprite-kit avplayer (3)

Estoy usando Sprite Kit y un SKVideoNode para reproducir un video corto. Cuando el nodo de video se agrega a la escena, antes o después de la configuración inicial, el reproductor parpadea en negro durante un breve segundo.

He intentado usar un AVPlayer para el video en lugar del video directamente, también he usado KVO para cargar solamente el SKVideoNode cuando el video dice que está listo para jugar.

De cualquier manera, recibo un flash negro antes de que mi video comience a reproducirse.

Además, no parece haber una manera de agregar un AVPlayerLayer al SKScene / SKView, aunque no sé si eso ayudaría.

Cualquier sugerencia sobre qué probar a continuación sería genial.

Aquí está el código que estoy usando

- (void)didMoveToView:(SKView *)view { if (!self.contentCreated) { [self createSceneContents]; } } - (void)createSceneContents { NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"IntroMovie" ofType:@"mov"]; NSURL *introVideoURL = [NSURL fileURLWithPath:resourcePath]; self.playerItem = [AVPlayerItem playerItemWithURL:introVideoURL]; self.player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem]; [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; SKSpriteNode *playButton = [SKSpriteNode spriteNodeWithImageNamed:@"PlayButton"]; [playButton setPosition:CGPointMake(CGRectGetMidX(self.view.frame), (CGRectGetMidY(self.view.frame) / 5) * 3)]; [self addChild:playButton]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"status"]) { if ([[change objectForKey:NSKeyValueChangeNewKey] integerValue] == AVPlayerItemStatusReadyToPlay) { NSLog(@"Change has the following %@", change); [self.player prerollAtRate:0 completionHandler:^(BOOL done){ SKVideoNode *introVideo = [SKVideoNode videoNodeWithAVPlayer:self.player]; [introVideo setSize:CGSizeMake(self.size.width, self.size.height)]; [introVideo setPosition:self.view.center]; [self addChild:introVideo]; [introVideo play]; [self.playerItem removeObserver:self forKeyPath:@"status"]; }]; } } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } }

Aquí hay una pieza alternativa de código que solo reproduce el video y brinda el mismo destello negro entre el video que se está cargando y el que se está reproduciendo.

NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"IntroMovie" ofType:@"m4v"]; NSURL *introVideoURL = [NSURL fileURLWithPath:resourcePath]; self.playerItem = [AVPlayerItem playerItemWithURL:introVideoURL]; self.player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem]; SKVideoNode *introVideo = [SKVideoNode videoNodeWithAVPlayer:self.player]; [introVideo setSize:CGSizeMake(self.size.width, self.size.height)]; [introVideo setPosition:self.view.center]; [self addChild:introVideo]; [introVideo play];


extraño problema ... ¿puedes probar sin usar AVPlayerItem ? Me gusta esto:

NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"IntroMovie" ofType:@"m4v"]; NSURL *introVideoURL = [NSURL fileURLWithPath:resourcePath]; AVPlayer *player = [AVPlayer playerWithURL: introVideoURL]; SKVideoNode *introVideo = [[SKVideoNode alloc] initWithAVPlayer: player]; [introVideo setSize:CGSizeMake(self.size.width, self.size.height)]; [introVideo setPosition:self.view.center]; [self addChild:introVideo]; [introVideo play];


Tuve un problema similar y lo resolvió así:

Exporté el primer fotograma del video como PNG. Luego agregué un SKSpriteNode con ese PNG en frente del SKVideoNode . Cuando comienzo el video, establezco la propiedad hidden del SKSpriteNode en YES .


Aquí hay un ejemplo simplificado de mi código con las partes relevantes:

-(void)didMoveToView:(SKView *)view { // add first frame on top of the SKVideoNode firstFrame = [SKSpriteNode spriteNodeWithImageNamed:@"firstFrame"]; firstFrame.zPosition = 1; [self addChild:firstFrame]; // here I add the SKVideoNode with AVPlayer ...... // Add KVO [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (object == player.currentItem && [keyPath isEqualToString:@"status"]) { if (player.currentItem.status == AVPlayerItemStatusReadyToPlay) { [introVideo play]; firstFrame.hidden = YES; } } }


Esta es la mejor solución que he encontrado hasta ahora. ¡Espero que eso te ayude!


Teniendo el mismo problema Mi solución:

videoNode = SKVideoNode(AVPlayer: player) videoNode.hidden = true player.addBoundaryTimeObserverForTimes([1/30.0], queue: dispatch_get_main_queue()) { [unowned self] () -> Void in self.videoNode.hidden = false }