I want to play a video in my iPhone app. I used this code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *movieUrl = [NSURL fileURLWithPath:
[[NSBundle mainBundle] pathForResource:#"Myvideo"
ofType:#"mp4"]];
//create a new instance of MPMoviePlayerController
MPMoviePlayerController* myMovie=[[MPMoviePlayerController alloc]
initWithContentURL:movieUrl];
//disable scaling of our movie
myMovie.scalingMode = MPMovieScalingModeNone;
//don't show any controls
// myMovie.movieControlMode = MPMovieControlModeHidden;
//you can specify at which time the movie should
//start playing (default is 0.0)
myMovie.initialPlaybackTime = 2.0;
//register a callback method which will be called
//after the movie finished
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinished:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:myMovie];
//start the movie (asynchronous method)
[myMovie play];
// Do any additional setup after loading the view from its nib.
}
Only the sound works with this code. Can someone help me please?
You need to allocate a frame to your movie and add it to the view. See here.
So you can add:
[myMoview.view setFrame: self.view.bounds]; // player's frame must match parent's
[self.view addSubview:myMovie.view];
Apple Technical Q&A 1240:
MPMoviePlayerController plays movie audio but not video
Q: I'm able to successfully play movies using MPMoviePlayerController on iOS 3.1.3. When I run this same code on the iPad and on the iPhone with iOS 4 I can hear the movie audio, but the video is no longer displayed. What's going on?
A: Starting with iPhone iOS 3.2, calling the -play: method still starts playback of the movie but it does not ensure that the movie is visible. In order to display a movie, you must get the new view property from your MPMoviePlayerController object and add that view to your view hierarchy. Here's a code snippet:
Listing 1 How to add the MPMoviePlayerController view property to your view hierarchy to play a movie.
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
[[player view] setFrame:[myView bounds]]; // size to fit parent view exactly
[myView addSubview:[player view]];
[player play];
See Important Porting Tip for Using the Media Player Framework and the MPMoviePlayerController Class Reference for more information.
Related
I created a MPMoviePlayerViewController which plays a live video. However, if I play the video twice meaning opening the player, clicking done, and playing the stream again. The result is only a black screen with no controls of the MPMoviePlayerViewController. And I need to stop the simulator cause I think the application is crashing. Here's how I did it
- (void) playUrl:(NSURL *)movieInfo
{
NSURL *streamUrl = movieInfo;
MPMoviePlayerViewController *mpvc = [[MPMoviePlayerViewController alloc] initWithContentURL:streamUrl];
[[mpvc view] setFrame:self.view.bounds];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
mpvc.moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
[mpvc.moviePlayer setControlStyle:MPMovieControlStyleFullscreen];
[mpvc.moviePlayer setShouldAutoplay:YES];
[mpvc.moviePlayer setFullscreen:NO animated:YES];
[mpvc setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[mpvc.moviePlayer setScalingMode:MPMovieScalingModeNone];
[mpvc.moviePlayer setUseApplicationAudioSession:NO];
[self presentMoviePlayerViewControllerAnimated:mpvc];
}
- (void) movieFinishedCallback:(NSNotification*) aNotification
{
MPMoviePlayerController *player = [aNotification object];
[player stop];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[player.view removeFromSuperview];
NSLog(#"stopped?");
}
I see that in your movieFinishedCallback: implementation, you remove the MPMoviePlayerController view, but in your playUrl: implementation, you are only setting the view's frame, presumably after you have already added the view in viewDidLoad.
One obvious change which is worth trying, is update you code to use the AVPictureInPictureController or AVPlayerViewController class from the AVKit framework, or the WKWebView class from WebKit. According to the MPMoviePlayerViewController docs, it is deprecated as of iOS 9:
The MPMoviePlayerViewController class is formally deprecated in iOS 9. (The MPMoviePlayerController class is also formally deprecated.) To play video content in iOS 9 and later, instead use the AVPictureInPictureController or AVPlayerViewController class from the AVKit framework, or the WKWebView class from WebKit.
Try moving the line where you add the view to the hierarchy, to the playUrl: method. Generally, it is good practice to have countering implementations in opposing methods for your event counterparts. For instance, implement a method to build and add a view when an event starts, and have a corresponding method where you tear down and remove the same view when the same event ends. But, I say 'generally' because there are always exceptions, and you may have very compelling reasons for not doing so. So, in this case, the opposing calls are presentMoviePlayerViewControllerAnimated: and dismissMoviePlayerViewControllerAnimated:, available from the UIViewController category.
After changing the view access to using dot-notation, to be consistent with your callback implementation, here is what your new playUrl: implemntation would look like, assuming you're adding the view to self.view:
- (void) playUrl:(NSURL *)movieInfo
{
NSURL *streamUrl = movieInfo;
MPMoviePlayerViewController *mpvc = [[MPMoviePlayerViewController alloc] initWithContentURL:streamUrl];
[mpvc.view setFrame:self.view.bounds];
[self.view addSubview:mpvc.view];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
mpvc.moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
[mpvc.moviePlayer setControlStyle:MPMovieControlStyleFullscreen];
[mpvc.moviePlayer setShouldAutoplay:YES];
[mpvc.moviePlayer setFullscreen:NO animated:YES];
[mpvc setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[mpvc.moviePlayer setScalingMode:MPMovieScalingModeNone];
[mpvc.moviePlayer setUseApplicationAudioSession:NO];
[self presentMoviePlayerViewControllerAnimated:mpvc];
}
Another option is to simply not remove the player's view in your callback method. If that is not the culprit, then the next thing I would investigate is check if you are sending messages to nil objects. Also, see what happens when you take out all the implementation from movieFinishedCallback:, except for getting and stopping the player.
I hope that helps!
Fixed the issue by removing the [player.view removeFromSuperview] line
I played with the AVCam demo sample in order to add a player (MPMoviePlayerController) that allows the preview of the recorded video
I added a play button in the xib and the corresponding IBOutlet and IBActions + a player:
#property (nonatomic,retain) IBOutlet UIBarButtonItem *playerButton;
#property (nonatomic, assign) MPMoviePlayerController *player;
- (IBAction)playVideo:(id)sender;
I do initialize the player in the viewdidload:
player = [[MPMoviePlayerController alloc] init];
the play Action is as follows
- (IBAction)playVideo:(id)sender {
if(player) {
[player stop];
}
// Create a new movie player object.
[player setContentURL:[[[self captureManager] recorder] outputFileURL]];
player.movieSourceType = MPMovieSourceTypeFile;
[player prepareToPlay];
CGRect viewInsetRect = CGRectMake( 0, 0, 200, 300);
// Inset the movie frame in the parent view frame.
[[player view] setFrame:viewInsetRect];
player.scalingMode = MPMovieScalingModeAspectFill;
player.controlStyle = MPMovieControlStyleNone;
//player.useApplicationAudioSession = NO;
//[self.view addSubview: [_player view]];
[self.view addSubview:player.view];
if(player) {
[player play];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playComplete) name:MPMoviePlayerPlaybackDidFinishNotification object:player];
}
and the playComplete called when play is finished:
-(void)playComplete {
[player.view removeFromSuperview];
}
result:
When I launch the app, I can record as many videos as I want.
when I play the last recorded video, I can play it without problems
but after playing the video, if i try to record again, I encounter this error as soon as it starts recording:
Error Domain=AVFoundationErrorDomain Code=-11803 "Cannot Record" UserInfo=0x152e60 {NSLocalizedRecoverySuggestion=Try recording again., AVErrorRecordingSuccessfullyFinishedKey=false, NSLocalizedDescription=Cannot Record}
i thought it was a problem on the temp output file, but it seems not.
I'm wondering if introducing a MPMoviePlayerController breaks the behavior of the app in some way that I cannot figure out.
do some of you have any idea?
Thanks
P
found that the -11803 was due to the fact that the captureManager session was not running (found the answer on Stackoverflow but i did not understand it very fast...)
at the end of the video preview play, in playComplete, I added a test to check the capture manager session status, to make it run if this was not the case anymore.
-(void)playComplete {
[player.view removeFromSuperview];
if(![[[self captureManager] session] isRunning]) {
// Start the session. This is done asychronously since -startRunning doesn't return until the session is running.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[[self captureManager] session] startRunning];
});
}
}
It is working now, but if anyone knows why the video preview stops the captureManager session, I would be happy to understand it.
P
I'm having trouble playing a video on the iPhone. I have a file in the app bundle and I am trying to play it in a MPMoviePlayerController but it is just displaying a black screen. This is the following code:
-(UIView*)createVideoPlayerOfWidth:(CGFloat)width
{
// The width for one of these can be half of the max width
//CGFloat widthAndHeight = width / 2.0f;
// TODO: Create a video player
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"myVideo" ofType:#"mov"]];
MPMoviePlayerController *playerController = [[MPMoviePlayerController alloc] initWithContentURL:url];
[playerController prepareToPlay];
[playerController setShouldAutoplay:NO];
[playerController setScalingMode:MPMovieScalingModeAspectFit];
[playerController setControlStyle:MPMovieControlStyleEmbedded];
[playerController setRepeatMode:MPMovieRepeatModeNone];
// Resize the thumbnail of the video
[[playerController view] setFrame:CGRectMake(0, 0, width, width)];
return [playerController view];
}
It is returning a valid URL (pathForResource would return nil if it couldn't find the file). I am displaying it to the screen by just adding a subView (the view returned by the function) to a scroll view. I've been trying to solve this for ages now and am getting nowhere. Any help is much appreciated.
Thanks!
Make sure you are retaining a reference to the MPMoviePlayerController instance:
If this is an ARC project, then playerController will be destroyed when createVideoPlayerOfWidth returns, and your video probably won't play. You should store the player in a strong instance variable or property.
You could add something like this to the top of your view controller file:
#interface MyViewController ()
#property (nonatomic,retain) MPMoviePlayerController *player;
#end
And insert this after you create the MPMoviewPlayerController instance:
self.player = playerController;
If you're not using ARC, this is probably not the problem, but you should still keep a reference in an instance variable, so that you can release it later.
I trying to show video on my App. The App hides the iPhone top panel. The player seems to work fine. There is just one annoying problem: when the player shows the video, it sometimes show the top panel and sometime hides it. When it is hidden, the video player panel is pushed a little (the same size of the panel that used to be there). Is is Apple bug? Am I doing something wrong?
Here is my code:
- (void) showFullscreenMediaWithURL: (NSURL *) mediaURL
{
MPMoviePlayerViewController *ctrl = [[MPMoviePlayerViewController alloc] initWithContentURL: mediaURL];
[[NSNotificationCenter defaultCenter] addObserver:self selector: #selector(playbackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:ctrl.moviePlayer];
ctrl.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
ctrl.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[ctrl setWantsFullScreenLayout:YES];
[self presentMoviePlayerViewControllerAnimated:ctrl];
[ctrl release];
}
-(void) playbackDidFinish:(NSNotification*)aNotification
{
NSLog(#"Finished playback");
MPMoviePlayerController *player = [aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[player stop];
[self dismissMoviePlayerViewControllerAnimated];
[[captureManager session] startRunning];
}
if by iPhone top panel you mean the iPhone Status bar, then the solution should be simple.
Just before present/dismissMoviePlayerViewControllerAnimated add the following:
// Hide Status Bar
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
// Show Status Bar
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
Update: I can see what seems to be your problem.
First, the upper bar with the network indication icons and other information is the status bar (and nothing else). Your problem seems to be more ViewController related then a MediaPlayer. In other words, If you would have try to "push" some other ViewController to full screen (as the player is) you would have experience the exact same issue.
Second, the proper way, or I might say: my preferred way, of loading a view controller to full screen is the following:
Setup a full screen rootViewController which will be loaded on applicationDidFinishLaunchingWithOptions on your appDelegate.
On the rootViewController init put your default viewController (the one you used to load from appDelegate). Make sure that the rootViewController.view's frame is filling the screen.
Create 2 messages on rootViewController: LoadFullscreen:viewController and dismissFullscreen using present/dismissModelViewController. the setStatusBarHidden messages should be called from here.
To Lunch the player on full screen, create the player viewController and perform [rootViewController LoadFullscreen:player];
There are some other ways, but generally, this is the best practice and the method I recommend. It's relatively "a lot of code" to implement, thats why I couldn't help you with code snippers, but the general idea is relatively simple.
I hope that's help, E.G :)
Thank you in advance for any help, I am a newbie and would appreciate any help here..
I have this code to play a movie and it works great. Can somebody PLEASE tell me how to make this movie loop and replay from the beginning non stop ( any code would help). Also I would like to know how to play 2 movies, one after the other, preferably with a fade or smooth transition. Thank you for any help
#import "MyAppViewController.h"
#implementation MyAppViewController
-(IBAction)button:(id)sender{
NSString *path = [[NSBundle mainBundle]
pathForResource:#"mymovie" ofType:#"mp4"];
player = [[MPMoviePlayerViewController alloc]
initWithContentURL:[NSURL fileURLWithPath:path]];
[self presentMoviePlayerViewControllerAnimated:player];
}
Set the repeatMode property of your MPMoviePlayerController to MPMovieRepeatModeOne
player = [[MPMoviePlayerViewController alloc]
initWithContentURL:[NSURL fileURLWithPath:path]];
player.moviePlayer.repeatMode = MPMovieRepeatModeOne;
MPMovieRepeatModeOne is nice but it doesn't loop the video very smoothly. Try this below (copied from another post) :
(I just got this working on my iPad 3 running iOS 5.1.1, base SDK iOS 5.1.)
When setting up the movie player, set the repeat mode to MPMovieRepeatModeNone then add the notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
Then set up your selector to filter when the movie finishes playing:
- (void)moviePlayerDidFinish:(NSNotification *)note
{
if (note.object == self.moviePlayer) {
NSInteger reason = [[note.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] integerValue];
if (reason == MPMovieFinishReasonPlaybackEnded)
{
[self.moviePlayer play];
}
}
}
For the timer you can create an Int variable that has the value of your slider and then use a performSelector afterDelay:
int delayInt = 8; // Substitute the 8 for the value of your slider
[self performSelector:#selector(myMethod) withObject:nil afterDelay:delayInt];
And then in your "myMethod"
-(void) myMethod{
//the code to stop your player and remove view controller
}