MPMoviePlayerController переключения фильмов вызывает белую вспышку
У меня есть небольшой UIView, который отображает повторный фильм. Когда пользователь нажимает кнопку, другой фильм загружается и отображается в том же UIView.
Проблема заключается в том, что между удалением первого фильма и отображением второго происходит "мигание" в полсекунды. Есть ли, чтобы удалить это?
- (void) setUpMovie:(NSString*)title {
NSString *url = [[NSBundle mainBundle] pathForResource:title ofType:@"mp4"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]];
[[player view] setFrame:self.movieView.bounds];
[self.movieView addSubview:player.view];
if ([title isEqualToString:@"Bo_idle_02"]) {
[player setRepeatMode:MPMovieRepeatModeOne];
} else {
[player setRepeatMode:MPMovieRepeatModeNone];
}
[player setControlStyle:MPMovieControlStyleNone];
[player play];
}
- (void) startDanceAnimation { [self setUpMovie:@"Bo_dance_02"]; return; }
4 ответа
Мне удалось изменить свои фильмы без белой вспышки, используя AVFoundation, как предлагалось ранее. Код sudo ниже, надеюсь, это поможет кому-то:)
Справочные документы по яблокам можно найти здесь, и я использовал их, чтобы получить большую часть моей информации: http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref / DOC / UID /TP40010188-CH1-SW3
Первым делом я добавил в свой проект следующий класс с именем PlayerView (не могу вспомнить, где я его получил). Это подкласс UIView и представление, в котором будет отображаться фильм. Как только вы добавите его в свой проект, откройте UI Builder, добавьте новый вид к существующему xib и измените его класс на PlayerView. Подключите это с помощью IBOutlet. Снова помните, что это вид, который будет отображать фильм.
PlayerView.h
#import
#import
#import
@interface PlayerView : UIView {
AVPlayer *player;
}
@property (nonatomic,retain) AVPlayer *player;
@end
PlayerView.m
#import "PlayerView.h"
@implementation PlayerView
@synthesize player;
+ (Class)layerClass {
return [AVPlayerLayer class];
}
- (AVPlayer*)player {
return [(AVPlayerLayer *)[self layer] player];
}
- (void)setPlayer:(AVPlayer *)player {
[(AVPlayerLayer *)[self layer] setPlayer:player];
}
- (void) dealloc {
[super dealloc];
[player release];
}
@end
В ViewContoller, который отображает фильмы, у меня есть следующее:
DisplayMovies.h
#import
#import
@class PlayerView;
@interface DisplayMovies : UIViewController {
IBOutlet AVPlayer *player;
AVPlayerItem *movieOneItem;
AVPlayerItem *movieTwoItem;
}
@property (nonatomic, retain) AVPlayer *player;
@property (retain) AVPlayerItem *movieOneItem;
@property (retain) AVPlayerItem *movieTwoItem;
DisplayMovies.m
@implementation DisplayMovies
@synthesize player, movieOneItem, movieTwoItem;
- (void)viewDidLoad {
// load the two movies
NSURL *movieOneItemURL = [[NSBundle mainBundle] URLForResource:@"movieOne" withExtension:@"mp4"];
AVURLAsset *movieOneItemAsset = [AVURLAsset URLAssetWithURL:movieOneItemURL options:nil];
self.movieOneItem = [AVPlayerItem playerItemWithAsset:movieOneItemAsset];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(movieOneItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.movieOneItem];
NSURL *movieTwoItemURL = [[NSBundle mainBundle] URLForResource:@"movieTwo" withExtension:@"mp4"];
AVURLAsset *movieTwoItemAsset = [AVURLAsset URLAssetWithURL:movieTwoItemURL options:nil];
self.movieTwoItem = [AVPlayerItem playerItemWithAsset:movieTwoItemAsset];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(movieTwoItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.movieTwoItem];
[self.player play];
}
- (void) movieOneItemDidReachEnd:(NSNotification*)notification {
// play movie two once movie one finishes
[self.player seekToTime:kCMTimeZero];
[self.player replaceCurrentItemWithPlayerItem:self.movieTwoItem];
[self.player play];
}
- (void) movieTwoItemDidReachEnd:(NSNotification*)notification {
// play movie one once movie two finishes
[self.player seekToTime:kCMTimeZero];
[self.player replaceCurrentItemWithPlayerItem:self.movieOneItem];
[self.player play];
}
Вышеуказанное решение не работает для меня. Я все еще получал короткие вспышки между треками. Я смог решить эту проблему, создав два представления, каждое со своим собственным AVPlayer. Я заставляю их обоих играть, а затем переключаюсь между ними, скрывая вид сверху. Это избавило от вспышки, и я смог анимировать переход между двумя дорожками, скрыв вид сверху, установив его альфа в 0.0 вместо использования setHidden. Вот мой код:
AVPlayerItem *theAsset = [self generatePlaylistAssetWithVideoOne]; //In my app this returns an AVPlayer Item
layerView1 = [[VideoLayerView alloc] initWithFrame:CGRectMake(-50, 0, 580, 320)]; //VideoLayerView is a subclass of UIView with the video layer stuff added in.
[layerView1 setPlayer:thePlayer];
[thePlayer play];
[self.view addSubview:layerView1];
AVPlayerItem *theAsset2 = [self generatePlaylistAssetWithVideoTwo];
[thePlayer2 setActionAtItemEnd:AVPlayerActionAtItemEndNone];
layerView2 = [[VideoLayerView alloc] initWithFrame:CGRectMake(-50, 0, 580, 320)];
[layerView2 setPlayer:thePlayer2];
[thePlayer2 play];
[self.view addSubview:layerView2];
Затем для анимации между видео, которые я использовал:
if (water) //Water is a BOOL set up earlier in the file
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
///DO STUFF
[layerView2 setAlpha:0];
[UIView commitAnimations];
water = NO;
}
else
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
///DO STUFF
[layerView2 setAlpha:1.0];
[UIView commitAnimations];
water = YES;
}
Чтобы изменить видео, вам просто нужно установить скрытый вид, чтобы начать воспроизведение того, что вы хотите, а затем выполнить переключение после вспышки.
Мне еще нужно вернуться к этому проекту, но я получил еще несколько советов. Я вернусь к работе над этим проектом через две недели, надеюсь, я дам вам знать, какое решение сработало (скрестив пальцы) для меня. А пока вот мои варианты:
1. Вы не сможете использовать MPMoviePlayerController для переключения фильма без вспышки.
В качестве альтернативы вы можете использовать AV Foundation. AVPlayer -replaceCurrentItemWithPlayerItem: метод будет плавно переходить от старого элемента проигрывателя к новому без вспышек.
Для получения дополнительной информации о программировании с помощью AV Foundation см. "Руководство по программированию AV Foundation", которое вы можете найти здесь:
http://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/
2. Вы можете объединить все свои фильмы в один (большой) фильм, а затем использовать свойства currentPlaybackTime / endPlaybackTime MPMediaPlayback, чтобы "выбрать" и воспроизвести нужный фильм (в большом фильме). Если вы используете эту технику, вам также необходимо убедиться, что есть ключевой кадр в тот момент, когда начинается новый фильм.
3. Альтернативно, создайте один объект MPMoviePlayerController, используйте -setContentURL: для установки URL нового фильма и используйте свойство backgroundView для более плавного перехода. Размер backgroundView автоматически изменяется с помощью свойства view, но он будет скрыт до предварительной загрузки фильма. Вы можете поместить черный вид позади обоих просмотров фильма, а затем сделать backgroundView backgroundColor = black, что должно сделать его более прозрачным.
Надеюсь это поможет.
Найти решение можно здесь http://joris.kluivers.nl/blog/2010/01/04/mpmovieplayercontroller-handle-with-care/ из iOS 6, который необходимо использовать [self.moviePlayer prepareToPlay]; и перехватить MPMoviePlayerReadyForDisplayDidChangeNotification для использования [self.moviePlayer play];