Воспроизведение видео в SKVideoNode вызывает черную вспышку перед началом воспроизведения
Я использую Sprite Kit и SKVideoNode для воспроизведения короткого видео. Когда видео узел добавляется к сцене, будь то до или после первоначальной настройки, проигрыватель мигает черным в течение короткой секунды.
Я попытался использовать AVPlayer для видео вместо видео напрямую, также я использовал KVO для загрузки SKVideoNode только тогда, когда видео говорит о готовности к воспроизведению.
В любом случае, я получаю черную вспышку до того, как мое видео начнет воспроизводиться.
Также, похоже, нет способа добавить AVPlayerLayer в SKScene/SKView, хотя я не знаю, поможет ли это.
Любые предложения о том, что попробовать дальше, было бы здорово.
Вот код, который я использую
- (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];
}
}
Вот альтернативный фрагмент кода, который просто воспроизводит видео и дает ту же самую черную вспышку между загружаемым видео и его воспроизведением.
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];
3 ответа
У меня была похожая проблема, и я решил ее так:
Я экспортировал первый кадр видео в формате PNG. Затем я добавил SKSpriteNode
с этим PNG перед SKVideoNode
, Когда я начинаю видео, я устанавливаю hidden
собственность SKSpriteNode
в YES
,
Вот упрощенный пример моего кода с соответствующими частями:
-(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;
}
}
}
Это лучшее решение, которое я нашел до сих пор. Я надеюсь, что это поможет вам!
Имея ту же проблему. Мой обходной путь:
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
}
Странная проблема... можно попробовать без использования AVPlayerItem
? как это:
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];