2014-03-24 1 views
5

Ich benutze Sprite Kit und einen SKVideoNode, um ein kurzes Video abzuspielen. Wenn der Videoknoten der Szene hinzugefügt wird, sei es vor oder nach der Ersteinrichtung, blinkt der Player für kurze Zeit schwarz.Das Abspielen von Video in einem SKVideoNode verursacht einen schwarzen Blitz, bevor die Wiedergabe beginnt.

Ich habe versucht, einen AVPlayer für das Video anstelle des Videos direkt zu verwenden, auch habe ich KVO verwendet, um nur den SKVideoNode zu laden, wenn das Video sagt, dass es bereit ist zu spielen.

In jedem Fall erhalte ich einen schwarzen Blitz, bevor mein Video abgespielt wird.

Auch scheint es keine Möglichkeit zu geben, einen AVPlayerLayer zu SKScene/SKView hinzuzufügen, obwohl ich nicht weiß, ob das helfen würde.

Alle Vorschläge, was als nächstes zu versuchen wäre großartig.

Hier ist der Code, den ich mit

- (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]; 
    } 
} 

Hier ist ein alternatives Stück Code, der gerade das Video spielt und gibt den gleichen schwarzen Blitz zwischen dem Video geladen und es zu spielen.

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]; 
+0

wo skvideonode initialisiert wird? Kannst du den Code von skvideonode eingeben? – Ilario

+0

Hinzugefügt den Code, wo ich es verwende. Ich habe versucht, den Preroll-Code, wie Sie sehen werden, und das machte keinen Unterschied zu den Dingen. –

+0

wo rufe [introVideo abspielen]? – Ilario

Antwort

1

hatte ich ein ähnliches Problem und löste es wie folgt aus:

ich den ersten Frame des Videos als PNG exportiert. Dann fügte ich ein SKSpriteNode mit dem PNG vor dem hinzu. Wenn ich das Video starte, stelle ich die hidden Eigenschaft von SKSpriteNode auf YES.


Hier ist ein vereinfachtes Beispiel für meinen Code mit den entsprechenden Teilen:

-(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;    
     } 
    } 
} 


Dies ist die beste Lösung, die ich bisher gefunden habe. Ich hoffe das hilft dir!

+0

Danke. Ich hatte darüber nachgedacht, etwas in diese Richtung zu tun, aber ich war zuversichtlich, dass es etwas einfacheres gegeben hätte. Vielen Dank für die Bestätigung, dass dies zumindest für den Moment der richtige Weg ist. –

0

seltsames Problem ... können Sie versuchen, ohne AVPlayerItem zu verwenden? dies wie:

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]; 
+0

Gleiches Ergebnis. Es scheint nichts mit der Verwendung eines AVPlayers oder AVPlayerItems zu tun zu haben und passiert immer noch, wenn keiner der beiden verwendet wird und der SKVideoNode direkt mit dem Video geladen wird. –

+0

Ich hatte in der Vergangenheit Probleme mit MPMoviePlayer, aber Sie konnten eine Hintergrundfarbe oder ein Bild in das einfügen, was dafür gesorgt hat.Keine Optionen, dies zu tun, da der AVPlayer und der SKVideoNode nicht von einer Ansicht unterstützt werden. –

1

Mit dem gleichen Problem. Meine Problemumgehung:

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 
}