Playing a Movie from MPMediaItem (iPad/IOS5) - iphone

I need to play a movie already synchronised from iTunes to Apples 'Movies' App on a iPad, in a view.
I can play a movie from the bundle using MPMoviePlayerController OK. I can get a media Item of all movies (NSArray of MPMediaItem's using MPMediaQuery). However the MPMoviePlayerController only accepts an NSURL - not an MPMediaItem.
So, how can I play a movie when all I have is a MPMediaItem of the movie? Is there another object other than MPMoviePlayerController that does this? Several posts explain how to 'get' a media item but not how to 'set' an item.
Any help is greatly appreciated.

each MPMediaItem has an URL which can be accessed with valueForProperty:.
I don't know if you can use that to play it in MPMoviePlayerController though. In theory it should work.
NSURL *url = [mediaItem valueForProperty:MPMediaItemPropertyAssetURL];
EDIT: Looks like it's not possible to use that.
MPMediaItemPropertyAssetURL
A URL pointing to the media item, from which an AVAsset object (or other URL-based AV Foundation object) can be created, with any options as desired. Value is an NSURL object.
The URL has the custom scheme of ipod-library. For example, a URL might look like this:
ipod-library://item/item.m4a?id=12345
Usage of the URL outside of the AV Foundation framework is not supported.
from: General Media Item Property Keys

Try this
NSURL *url = [mediaItem valueForProperty:MPMediaItemPropertyAssetURL];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL: url];
[player prepareToPlay];
[player.view setFrame: myView.bounds]; // player's frame must match parent's
[myView addSubview: player.view];
[player play];
i think this should work..
MPMediaItem is inherited from MPMediaEntity which has the method valueForProperty:

Related

Play multiple videos

I'm actually using the MPMoviePlayerController for play video in my iPad app.
Actually, I can easly play 1 video but I'm trying to play in the same time 2 video, here is my code :
// Look for the video in the main bundle
NSString *urlStr = [[NSBundle mainBundle] pathForResource:#"3idiots.mov" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:urlStr];
NSString *urlStr2 = [[NSBundle mainBundle] pathForResource:#"3idiots.mov" ofType:nil];
NSURL *url2 = [NSURL fileURLWithPath:urlStr2];
videoPlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
[self.view addSubview:videoPlayer.view];
videoPlayer.view.frame = CGRectMake(0, 0,200, 200);
videoPlayer2 = [[MPMoviePlayerController alloc] initWithContentURL:url2];
[self.view addSubview:videoPlayer2.view];
videoPlayer2.view.frame = CGRectMake(0, 300,200, 200);
[videoPlayer2 play];
NSLog(#"Video 1 playing");
[videoPlayer play];
NSLog(#"Video 2 playing");
The first video is correctly launched but not the second. (and btw the second video does not lauch after the first finished)
Here is my output :
2012-06-18 13:47:23.015 testMosaique[2498:11f03] Video 1 playing
2012-06-18 13:47:23.016 testMosaique[2498:11f03] Video 2 playing
Is there a way while using MPMoviePlayerController to play 2 or more videos at the same time?
Thank's
If you want to play more than one video at the same time you have to use AVPlayer frameworks. MPMovie only allowed you play one video at a time.
See AVPlayer documentation.
As Safecase mentioned, MPMovieplayerController will only allow one video to be played at a time. But here is an example to play two simultaneously with the use of AVFoundation:
http://www.sdkboy.com/?p=66
Hope this helps!
What I did is display 4 videos using AVPlayer, but those video are made from 4 another video (I create each videos with AVFoundation). Si I'm able the display thousand and thousand videos in only 4 players, pretty good performances when you play the videos !

iPhone: Play videos automatically in a sequence, one after another

i built a very basic video player app in Xcode 4.3.2
i have 3 small videos and on my main menu i have 3 buttons. One button for each video
my code looks like this.....
- (IBAction)playMoviePressed1:(id)sender
{
NSString *path = [[NSBundle mainBundle]
pathForResource:#"HomeVideoOne" ofType:#"m4v"];
player = [[MPMoviePlayerViewController alloc]
initWithContentURL:[NSURL fileURLWithPath:path]];
[self presentMoviePlayerViewControllerAnimated:player];
}
And it repeats for videos 2 and 3. I would like to have a 4th button that played all 3 videos in order without stopping and having to select the next one. It's almost like having to play chapters in a movie one at a time.
Here's the kicker, I don't want to make any extra video files to add to the project size. So in other words the only way i am able to accomplish my goal so far is to edit all 3 videos into one .m4v file and import that to the project. But that is no good because it doubles my project size. I'd like to call on the existing files to play in one right after another with no break. I hope I didn't sound to repetitious.
Thank You
-ANthony
In this case you will need to use some more advanced API like AVQueuePlayer instead of a basic MPMoviePlayerController
Try look through the document here first http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html
You can always start another video whenever a video is finished playing. One way is to set your custom methods to be called to control the behavior when you create youMoviePlayerController:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(aMoviePlaybackComplete:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:youMoviePlayerController];
and then:
- (void)aMoviePlaybackComplete:(NSNotification*)notification
{
MPMoviePlayerController *moviePlayerController = [notification object];
if(urlIndex < yourUrlArray.count){
NSUrl* myUrl = [yourUrlArray objectAtIndex:urlIndex];
[moviePlayerController setContentURL:myUrl];
[moviePlayerController play];
urlIndex++;
}
else{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayerController];
[moviePlayerController.view removeFromSuperview];
[moviePlayerController release];
}
}
I'm assuming yourUrlArray is a pre-defined array of the urls of the movies you want to play and urlIndex is keeping count of the current movie being played. Of course, you'll have to tune this to your needs.
EDIT- For local files, you can form the NSUrl using bundle:
NSString *moviePath = [[NSBundle mainBundle] pathForResource:#"Movie" ofType:#"m4v"];
NSUrl* url = [NSURL fileURLWithPath:moviePath];
[yourUrlArray addObject:url];
and initialize the url array(yourUrlArray) and then continue as posted before.

How to play a NSData in video player

I have written an async call to download a video of mp4 format. The response result is an NSData. How can I open the NSData in any video player framework which should be supported in IOS 3.
An NSData is basically a container object, and thus not in a format you can play in a video player. Without seeing any code, or the results of your data, you can create an NSString from data with
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Now that you have a string, you can create an NSURL with
NSURL *movieURL = [NSURL URLWithString:dataString];
From there, you should be able to pass this into an MPMoviePlayerController with
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
It's not possible to directly play the NSData into AVPlayer. What you can do is download the Data into Document folder and later fetch the file path and give that path to AVPlayer.

Memory leaks when playing a video iPhone

I need to play a simple video on my app. I been looking on the internet on how to play a video and I found out that I need to import the MediaPlayer.framwork which I did. I have a Video named:
and the code that I have in order to play it:
NSString *url = [[NSBundle mainBundle]
pathForResource:#"Final_Valores_Pacific"
ofType:#"m4v"];
MPMoviePlayerController *player =
[[MPMoviePlayerController alloc]
initWithContentURL:[NSURL fileURLWithPath:url]];
I am missing the code to add it to a view but just that code creates a leak:
what is the right way of playing a video? how can avoid that memory leak?
When you alloc an object, you have to release it at the end:
// ...some code
NSString *url = [[NSBundle mainBundle]
pathForResource:#"Final_Valores_Pacific"
ofType:#"m4v"];
MPMoviePlayerController *player =
[[MPMoviePlayerController alloc]
initWithContentURL:[NSURL fileURLWithPath:url]];
// ...use player
[player release];
Are you getting this leak on the simulator? I got this on an app that I worked on in the past only on the simulator, but not on the iPhone.
There are similar questions about this too:
iPhone: OpenAL & AudioToolbox leak

Using MPMediaItems with AVAudioPlayer

Is it possible to pick media items using MPMediaPickerController and then load them into an AVAudioPlayer object?
If MPMusicPlayerController doesn't meet your needs, you can copy the audio to your local bundle so you can use AVAudioPlayer.
EDIT
You basically have three options for playing audio from the user's iPod library: MPMediaPlayer, AVPlayer and AVAudioPlayer.
Here are examples for MPMediaPlayer and AVPlayer:
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker
didPickMediaItems: (MPMediaItemCollection *) collection {
MPMediaItem *item = [[collection items] objectAtIndex:0];
NSURL *url = [item valueForProperty:MPMediaItemPropertyAssetURL];
[self dismissModalViewControllerAnimated: YES];
// Play the item using MPMusicPlayer
MPMusicPlayerController* appMusicPlayer = [MPMusicPlayerController applicationMusicPlayer];
[appMusicPlayer setQueueWithItemCollection:collection];
[appMusicPlayer play];
// Play the item using AVPlayer
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:url];
AVPlayer *player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
[player play];
}
If you need to use AVAudioPlayer for some reason, or you need access to the audio file's actual audio data, you have to first copy the audio file to your app's directory and then work with it there. The AVAsset + AVPlayer stuff is the closest analogy to ALAsset if you're used to working with photos and videos.
Just wanted to say that it appears that in iOS 6 and 7, AVAudioPlayer can play file URLs directly from the iPod without having to copy the audio data into your app directory as Art suggested.
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) collection {
MPMediaItem *item = [[collection items] objectAtIndex:0];
NSURL *url = [item valueForProperty:MPMediaItemPropertyAssetURL];
// Play the item using AVPlayer
self.avAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[self.avAudioPlayer play];
}
I wanted to add (and I can't comment on SO yet) that it seems like in iOS 8, and perhaps before, songs that are stored on iCloud do not have a value for the property assetURL and return null for [npItem valueForProperty:MPMediaItemPropertyAssetURL].
Here is a sample output:
MPMediaItem *npItem = self.musicPlayerController.nowPlayingItem;
NSLog(#"Song Title: %#\n assetURL: %#\n Cloud Item: %d", npItem.title, [npItem valueForProperty:MPMediaItemPropertyAssetURL], npItem.cloudItem)
// Log Output
Song Title: Time We Had
assetURL: (null)
Cloud Item: 1
Song Title: The Quiet
assetURL: ipod-library://item/item.m4a?id=1529654720874100371
Cloud Item: 0
I think you'll find that the [NSBundle mainBundle] is READ-ONLY. It's not possible to write files into the APP, therefore AVAudioPlayer will not work for iPod-Library MPMediaItems!