【问题标题】:MPMoviePlayerController switching movies causes white flashMPMoviePlayerController 切换电影导致白闪
【发布时间】:2010-12-30 04:43:37
【问题描述】:

我有一个小的 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; }

【问题讨论】:

    标签: iphone ios mpmovieplayercontroller movie


    【解决方案1】:

    如前所述,我设法使用 AVFoundation 在没有白色闪光灯的情况下更改电影。下面的 sudo 代码,希望对某人有所帮助:)

    Apples 参考文档可以在这里找到,我使用它们来获取我的大部分信息: 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];
    }
    
    

    【讨论】:

    • 嗨@SoundBlaster 我不同意。正如我所说,上面是 sudo 代码,但它确实有效,无论是在我自己的项目中还是在其他人中。如果您解释您的项目中正在发生/未发生的事情,那么也许我们可以提供帮助。
    【解决方案2】:

    上面发布的解决方案对我不起作用。我仍然在曲目之间短暂闪烁。我能够通过创建两个视图来解决这个问题,每个视图都有自己的 AVPlayer。我将它们都设置为播放,然后通过隐藏顶视图在它们之间切换。这摆脱了闪光灯,我能够通过将其 alpha 设置为 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;
    }
    

    要切换视频,你只需设置隐藏视图开始播放你想要的,然后在闪烁后进行切换。

    【讨论】:

      【解决方案3】:

      我仍然需要回到这个项目,但我收到了更多建议。希望两周后我会回到这个项目上工作,所以我会让你知道哪个解决方案对我有用(手指交叉)。与此同时,这是我的选择:

      1。 如果没有闪光灯,您将无法使用 MPMoviePlayerController 切换电影。

      作为替代方案,您可以使用 AV Foundation。 AVPlayer -replaceCurrentItemWithPlayerItem: 方法将从旧的播放器项目无缝过渡到新的播放器项目,而不会闪烁。

      有关使用 AV Foundation 进行编程的更多信息,请参阅此处的“AV Foundation 编程指南”:

      http://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/

      2。 您可以将所有电影合并为单个(大)电影,然后使用 MPMediaPlayback currentPlaybackTime / endPlaybackTime 属性“选择”并播放所需的电影(在大电影中)。如果您使用这种技术,您还需要确保在新电影开始的时间点有一个关键帧。

      3。 或者,创建单个 MPMoviePlayerController 对象,使用 -setContentURL: 设置新电影 URL,并利用 backgroundView 属性进行更无缝的过渡。 backgroundView 使用 view 属性自动调整大小,但在预加载电影之前它将被隐藏。您可以在两个电影视图后面放置一个黑色视图,然后让 backgroundView 的 backgroundColor = black,这应该使它看起来更加无缝。

      希望这会有所帮助。

      【讨论】:

      • 我正在使用replaceCurrentItemWithPlayerItem,但仍然看到白色闪烁,尽管仅在设备上。模拟器工作没有闪光。 (iOS 9)
      【解决方案4】:

      在这里找到解决方案 http://joris.kluivers.nl/blog/2010/01/04/mpmovieplayercontroller-handle-with-care/ 从 iOS 6 你需要使用 [self.movi​​ePlayer prepareToPlay];并捕获 MPMoviePlayerReadyForDisplayDidChangeNotification 以使用 [self.movi​​ePlayer play];

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-10
        • 1970-01-01
        • 1970-01-01
        • 2011-02-12
        • 1970-01-01
        相关资源
        最近更新 更多