commonMetadata array empty for some songs from iPod library - iphone

I'm using a MPMediaPickerControllerto enable the user to pick songs from the device's iPod library. Then I put this songs into an array (in this case playerQueue) and use an AVPlayer instance to play one song after the other:
- (void)setQueueWithItemCollection:(MPMediaItemCollection *)theCollection {
for (MPMediaItem *theMediaItem in theCollection.items) {
NSURL *mediaURL = [theMediaItem valueForProperty:MPMediaItemPropertyAssetURL];
AVPlayerItem *thePlayerItem = [AVPlayerItem playerItemWithURL:mediaURL];
// Don't add protected tracks to queue as they cannot be played
if (!thePlayerItem.asset.hasProtectedContent && thePlayerItem.asset.isPlayable) [self.playerQueue addObject:thePlayerItem];
// Further implementation
}
}
Now I get the song title using this code snippet (with AVPlayer *musicPlayer):
AVPlayerItem *currentItem = self.musicPlayer.currentItem;
AVAsset *asset = currentItem.asset;
// Further implementation
NSLog(#"DEBUG: Meta data: %#", asset.commonMetadata);
NSArray *titles = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
Most times this works without any problem. But there are are also songs for which asset.commonMetadata returns an empty array. However the Music app on my iPhone is able to display the song title (and album artwork etc.) just like iTunes (on the Mac).
The song file is an Apple MPEG 4 Audio file purchased from the iTunes Store.
Why is asset.commonMetadata returning an empty array even though there are meta data available?

I was having this same problem with downloaded m4b audio files. Turns out that AVURLAsset requires the URL string to end in '.m4b' (other audio extensions would work, I suspect). You can't use the URL as is if it is something like http://source.com/download.php?id=12345. Otherwise, the asset.commonMetaData just returns an empty array. I don't know if this is a problem with iTunes assetURLs, but it would be easy to check.

The only solution that worked for me:
Use AudioToolbox.framework to retrieve metadata from such files, i.e. use AudioFileGetProperty function.
It seems like a real bug in AVFoundation…

Related

how to get iphone ipod playlist images and display it in image view

I am working with iphone ipod to read the album and playlist and play it in my application.
My question is that that i get the image from the album i have selected. and it is also working well in my application.
But i never get images from the playlist which i have selected their are different songs in my playlist and also having different image for that songs. for the album i have get the code and it work great. i am new for this and i cant found any reference code for this.
And i am using AVPlayer to play the songs.
So please help me and provide some sample code. for how to get all images from playlist and convert that image to data in iphone.
Please help me.
You're looking for is the MPMediaItemPropertyArtwork for MPMediaItem. As stated in the docs. After getting the artwork property you can make a MPMediaItemArtwork object, as stated in the docs.
An MPMediaItemArtwork object, or media item artwork, represents a graphical image, such as music album cover art, associated with a media item. Media items are described in MPMediaItem Class Reference.
With this you can do something like this. Assuming song is an MPMediaItem:
UIImage *image = nil;
MPMediaItemArtwork *itemArtwork = [song valueForProperty:
MPMediaItemPropertyArtwork];
if(itemArtwork != nil)
image = [itemArtwork imageWithSize:CGSizeMake(100,100)];
Now you have image containing your MPMediaItem artwork, set it to your image view ([myImageView setImage:image]). Keep in mind, this will only work if artwork IS available.
Hope this helps.
You can use VTM_AViPodReader demo for this.

Fetching video through file name from video gallery in iphone

I have name of some videos which are going to be stored in video gallery of iphone, can I get the url of the video I specify through file name, i.e. if I specify a.png video name then it should return the url of that video.
It sound like you want to access a video in the user's folders directly. You can not do this.
Instead you must get the user to select a Video using a standard picker, something like this:
myImagePickerController.mediaTypes =
[[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
See this question.

Playing a video in ipad

I want to play a movie in my app and the video is stored in my ipad library.
Can anyone provide me the necessary guidance for it?
Get the MPMediaItem of the video you want using MPMediaQuery
Get the Asset URL like this:
NSURL *videoURL = [mediaItem valueForProperty:MPMediaItemPropertyAssetURL];
Instantiate an MPMoviePlayerViewController using videoURL as the content URL.
If the video is stored in your App's bundle then do this to get the URL:
NSURL *videoURL = [[NSBundle mainBundle] URLForResource:#"nameoffile" withExtension:#"mp4"];
See a sample of a custom view/viewController combo in Pragmatic iPad Programming. Check the source code for chapter 8 (free download from that page). They use a video provided as a file inside the project. Btw, if the file in the video appears red in XCode, you'll have to remove it and re add it, I think the project definition is a bit screwed.

Extracting ID3 tags from MP3 over HTTP Live Streaming

I've been having quite a difficult time extracting ID3 information from an MP3 being streamed over Live HTTP Streaming (using the Wowza media server, if anyone is curious). I know that the tags (right now the album tag and the album artwork tag) are being properly embedded in each of the file segments because when I download them manually I can see them in each segment as listed in the .m3u index file generated by the server.
I am using the AVFoundation classes to do this, and I have it setup as such:
- (void)initializeAudioStream {
NSURL *streamUrl = [NSURL URLWithString:self.urlField.text];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:streamUrl];
self.musicPlayer = [AVPlayer playerWithPlayerItem:playerItem];
self.musicPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[self.musicPlayer addObserver:self forKeyPath:#"status" options:NSKeyValueObservingOptionNew context:NULL];
}
Once my KVO method is triggered, I start playing self.musicPlayer and I call addPeriodicTimeObserverForInterval on it for each 1/4 second. It is in this method that I try to extract the ID3 metadata.
I have tried everything I can think of on the iOS side of things to accomplish this, including printing out
self.musicPlayer.currentItem.asset.commonMetadata
as well as iterating over each of the AVAssetTrack instances and printing out their metadata.
for (AVAssetTrack *track in self.musicPlayer.currentItem.asset.tracks) {
NSLog(#"Media type of track: %#", track.mediaType);
NSLog(#"Track metadata: %#", track.commonMetadata);
}
What's interesting is that the asset always says it has 2 tracks. When I print out their mediaType property I get "soun" for the first one and "tmet" for the second. My assumption is that the first track is the audio data itself and the second track is metadata. However, I only ever see an empty array in commonMetadata.
I also check the status of the properties using statusOfValueForKey:error on the tracks, and the commonMetadata key always comes back as AVKeyValueStatusLoaded.
Any ideas? I'm at a complete loss here.
Also, I am currently running this through the iPhone 4 simulator running iOS 4.2.1. I can't yet put it on a device since Apple is still approving my company's developer account.
Instead of using commonMetadata you might want to try using timedMetadata on the AVPlayerItem:
[playerItem addObserver:self forKeyPath:#"timedMetadata" options:NSKeyValueObservingOptionNew context:NULL];
Just an idea: using fiddler/othersniffer to sniff the http request content to see if metadata is present ?
You need to register a subclass of NSURLProtocol in Appdelegate didFinishLaunchingWithOptions method.
then you can see the response of the request made by your video player

How do you implement seeking using the AudioStreamer sample application as a base?

I need to play some audio streaming contents on iPhone, but there are some options and problems I can't solve:
1. http://cocoawithlove.com/2009/06/revisiting-old-post-streaming-and.html
It is a library provided by Matt Gallagher, but I saw the Limited scope, and I would play
a single song, not a radio station.
2. Suggestion from zonble
NSURL *URL = [NSURL URLWithString:#"http://zonble.net/MIDI/orz.mp3"];
NSData *data = [NSData dataWithContentsOfURL:URL];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:data error:nil];
But I need streaming for each "single song".
3. Using MPMoviePlayerController to wrapper.
Since the Class update new method, and
#interface MyAudioStreamer : UIViewController {
MPMoviePlayerController *mp ;
}
instead of [self addSubview:mp.view] I use my own xib file to implement play and
stop methods, but in this case, I have no idea to implement seekForward or seekBackward.
Is there any good idea to do AudioStreamer?
==== Update ====
after google 'AVPlayer' ,i used 3. Using MPMoviePlayerController to wrapper. to implement a auidoStreamer-like player ,there is something to share :
1.'playbackDidFinished' state
there're 2 conditions : a song did finished and play next song or a song interrupt by user press stop or exception, i used enum to filter my state.
2 multi-task playing your song in background
reference from https:// devforums.apple.com/message/264397
and if iOS SDK update, the solution might be changed because method would be diplicated. so i suggest to read library provided by Matt Gallagher.
anyone who konws when the library have no codec match download item (for example, my item encode by .AAC 128-bit and the library not support or at most .AAC 64-bit), what happen would the player be ?
You can either parse the icy meta data yourself, or if you're using iOS 4.0 you can playback using an AVPlayer and observe the timed metadata to discover the song boundaries and titles.