MPMoviePlayerController fail to play audio - ios

I use MPMoviePlayerController to play a list of audio streams from url. I use the following code to init the player
self.player = [[[MPMoviePlayerController alloc] init] autorelease];
self.player.controlStyle = MPMovieControlStyleNone;
and later use the following code to set and reset contentUrl:
self.player.contentURL = url;
[self.player prepareToPlay];
but sometimes, not every time, it fails to play audio, post MPMoviePlayerPlaybackDidFinishNotification directly and gives following userInfo
{
MPMoviePlayerPlaybackDidFinishReasonUserInfoKey = 1;
error = "Error Domain=MediaPlayerErrorDomain Code=-11828 \"Cannot Open\" UserInfo=0xee7bf20 {NSLocalizedDescription=Cannot Open}";
}
anyone knows why?

I would suggest you use AVPlayer instead of MPMoviePlayerController.
I had seen such issues before when streaming audio with MPMoviePlayerController. AVPlayer is the more appropriate one for this task.

Related

Playing videos from data obtained in chunks

I have recently started adding videos to ios apps using AVPlayer.But,now I have to get video data in chunks(HLS) rather than getting all data together ,but I am not able to understand the difference between this concept of playing data obtained in chunks or playing the whole data obtained altogether as implemented below .I have tried understanding this thing and looked for examples on internet but got the same thing as already implemented by me.Kindly give your suggestions and guidance that can help me to move forward.Thanks in advance!
-(void)playVideo:(NSURL*)videoURL
{
AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:videoURL];
AVPlayer* playVideo = [[AVPlayer alloc] initWithPlayerItem:playerItem];
_playerViewController = [[AVPlayerViewController alloc] init];
_playerViewController.player = playVideo;
_playerViewController.view.frame = self.view.bounds;
[self.view addSubview:_playerViewController.view];
[playVideo play];
}
Read this Document from Apple.
When you init player, it doesn't mean that player is ready to play. You should observe player's status until you get AVPlayerStatusReadyToPlay status.
From your code, you init player and directly start playing video. You should observe status of player by following code.
[player addObserver:self forKeyPath:#"status" options:0 context:&PlayerStatusContext];

Play audio from video when phone is on silent mode

I am building an application that plays certain video files. However, when the phone is on vibrate the audio still plays. Apps like youtube still play the audio form their videos when the phone is on vibrate. How can I do this? I am using avplayer to play the video. Below is my code for playing the video
_player = [[AVPlayer alloc]initWithPlayerItem:pi];
AVPlayerViewController *playerController = [[AVPlayerViewController alloc]init];
playerController.player = _player;
[self presentViewController:playerController animated:YES completion:nil];
playerController.view.frame = self.view.frame;
[_player setMuted:false];
[self addChildViewController:playerController];
Found the solution. Adding this code allows whatever video is playing to produce audio even on silent mode.
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayback
error: nil];

Find out whether AVPlayer is loading or playing mp3 from internet

I would like to use AVPlayer to stream a .mp3 from internet
[[AVPlayer alloc] initWithURL:url];
It all works apart from the fact that I am unable to tell whether player is Loading (buffering) or playing ?
I have tried to use KVO on many properties, but none seem to provide me with a simple way of determining whether the AVPlayer is currently actually playing audio or whether it is loading data. It is driving me nuts.
Thank you for your suggestions in advance
You can detect when buffering is done and playback has started by creating a periodic time observation (using addPeriodicTimeObserverForInterval:queue:usingBlock:) to detect when the play time has started to move. For example:
AVPlayer *player;
// allocate AVPlayer and start playing
__weak PlayerController *blockSelf = self;
id observerToken = [player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.0, NSEC_PER_SEC)
queue:nil
usingBlock:^ (CMTime time)
{
if (CMTimeGetSeconds(time) > 0.0)
{
// done buffering, should be playing now
[player removeTimeObserver:[blockSelf playerTimeObserverToken]];
[blockSelf setPlayerTimeObserverToken:observerToken:nil];
}
}];
[self setPlayerTimeObserverToken:observerToken]; // Keep a reference to the token for later use in block.

Movieplayercontroller using a m4v with two audio tracks

I need use in my App a m4v video with two audio tacks. But when I play the video, it starts with the two audio tracks at the same time. I need to load the audio track with the device's default language (English by default).
Here is my code:
_moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[_moviePlayer shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft];
_moviePlayer.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[self presentMoviePlayerViewControllerAnimated:_moviePlayer];
MPMoviePlayerController just as well as the wrapping MPMoviePlayerViewController do not support the selection of audio tracks.

Getting first frame of a captured video in iOS 5.0+

My app used to be able to get the first video frame using the code below - works for iOS 4.0+. But once my device is upgraded to iOS 5.0.1, the returned image is always NULL.
+(UIImage *)fFirstVideoFrame:(NSString *)path
{
MPMoviePlayerController *mp = [[MPMoviePlayerController alloc]
initWithContentURL:[NSURL URLWithString:path]];
UIImage *img = [mp thumbnailImageAtTime:0.0
timeOption:MPMovieTimeOptionNearestKeyFrame];
[mp stop];
[mp release];
return img;
}
Does anyone know how to get video frames in iOS 5.0+? Thanks.
Here is why (from MPMoviePlayerController documentation):
Behavior in iOS 4.3 and Earlier
In iOS 4.3 and earlier, a new movie player was automatically prepared to play. Starting in iOS 5.0, in order to facilitate finer-grained playback control, a new movie player is not automatically prepared to play. See the discussion for the initWithContentURL: instance method.
The discussion says, in part:
.. To prepare a new movie player for playback, call the prepareToPlay method ..
To be notified when a new movie player is ready to play, register for the MPMoviePlayerLoadStateDidChangeNotification notification. You can then check load state by accessing the loadState property.
Once the movie is ready to play, then you can request thumbnail images from it.

Resources