AVAssetResourceLoaderDelegate setup issue - ios

I have a weird issue when trying to setup AVAssetResourceLoaderDelegate. When using this code it works most of the time on a device but it doesn't work on the simulator at all:
NSURL *url = [NSURL URLWithString:#"xxx://name"];
AVURLAsset *asset = [AVURLAsset assetWithURL:url];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
[asset.resourceLoader setDelegate:self queue:self.queue];
AVPlayer *avPlayer = [AVPlayer playerWithPlayerItem:playerItem];
[avPlayer play];
The issue is that the delegate method is never getting called:
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest
However, this code works perfectly fine:
NSURL *url = [NSURL URLWithString:#"xxx://name"];
AVURLAsset *asset = [AVURLAsset assetWithURL:url];
[asset.resourceLoader setDelegate:self queue:self.queue];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
AVPlayer *avPlayer = [AVPlayer playerWithPlayerItem:playerItem];
[avPlayer play];
The only difference is that we set the delegate first and then we create AVPlayerItem with the asset. In the first case, the asset is not being copied when creating AVPlayerItem and if we check playerItem.asset.resourceLoader.delegate the delegate is set correctly but it's never getting called.
I would appreciate any help with it.
Thanks,
Michal

Related

[AVPlayerViewController setPlayer:]: unrecognized selector sent to instance

[AVPlayerViewController setPlayer:]: unrecognized selector sent to instance 0x101b91980 error.
I am trying to play a video using AVPlayerViewController.
#property (nonatomic) AVPlayer *avPlayer;
#property (nonatomic) AVPlayerViewController* avPlayerView;
NSString *path = [[NSBundle mainBundle] pathForResource:#"SampleVideo_1280x720_1mb" ofType:#"mp4"];
NSURL *url = [[NSURL alloc] initFileURLWithPath: path];
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *anItem = [AVPlayerItem playerItemWithAsset:asset];
_avPlayer = [AVPlayer playerWithPlayerItem:anItem];
[AVPlayer addObserver:self forKeyPath:#"status" options:0 context:nil];
self.avPlayerView = [[AVPlayerViewController alloc] init];
self.avPlayerView.view.frame = self.view.bounds;
[self.avPlayerView setPlayer:_avPlayer];
[self.view addSubview:_avPlayerView.view];
but it is crashing. If i use same code in a new project, video play nicely.What is the problem?Please help.
Make sure you import AVFoundation/AVFoundation.h and AVKit/AVKit.h in your controller and try to assign a player to playerController like this.
self.avPlayerView.player = self.avPlayer;
Instead of adding observer to AVPlayer Class add observer to Avplayer instance.
[avPlayer addObserver:self forKeyPath:#"status" options:0 context:nil];

custom resourceLoader with AVComposition

Is there any way to use a custom resourceLoader with an AVComposition? I get the AVAssetResourceLoaderDelegate callbacks when I set the resourceLoader on an AVURLAsset and create an AVPlayerItem with that asset. But if I use that same AVURLAsset in an AVComposition, I don't get the delegate callbacks. In fact it never returns from the call to insert the asset into the composition.
AVAssetResourceLoaderDelegate methods called with AVURLAsset:
NSURL* mungedURL = [self mungeURL:itemURL];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:mungedURL options:nil];
[asset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()];
self.playerItem = [AVPlayerItem playerItemWithAsset:asset];
AVAssetResourceLoaderDelegate methods NOT called with AVURLAsset inserted into AVComposition:
NSURL* mungedURL = [self mungeURL:itemURL];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:mungedURL options:nil];
[asset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()];
AVMutableComposition* composition = [AVMutableComposition composition];
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
[composition insertTimeRange:timeRange ofAsset:asset atTime:kCMTimeZero error:nil];
self.playerItem = [AVPlayerItem playerItemWithAsset:composition];
(actually, it hangs at insertTimeRange:ofAsset:atTime:error. I guess it tries to load from the munged url at that point - but doesn't use delegate.)
Method to tweak url scheme so resource loader delegate is called:
- (NSURL*)mungeURL:(NSURL*)url
{
NSURLComponents* components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
components.scheme = #"fake-scheme";
return [components URL];
}

How to play mp3 file from url in iOS?

I am trying to play mp3 file located somewhere on remote server.I have the url of that music fileI have tried it playing it using AVAudioPlayer or AVPlayer but i am not able to play the mp3 file.Please tell me how can i play the mp3 file.
code to play music:
NSString *aSongURL = [NSString stringWithFormat:#"http://megdadhashem.wapego.ru/files/56727/tubidy_mp3_e2afc5.mp3"];
// NSLog(#"Song URL : %#", aSongURL);
AVPlayerItem *aPlayerItem = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:aSongURL]];
AVPlayer *anAudioStreamer = [[AVPlayer alloc] initWithPlayerItem:aPlayerItem];
[anAudioStreamer play];
// Access Current Time
NSTimeInterval aCurrentTime = CMTimeGetSeconds(anAudioStreamer.currentTime);
// Access Duration
NSTimeInterval aDuration = CMTimeGetSeconds(anAudioStreamer.currentItem.asset.duration);
Please tell me how do i do it?
Try Below Code.
NSURL *url = [NSURL URLWithString:#"http://megdadhashem.wapego.ru/files/56727/tubidy_mp3_e2afc5.mp3"];
self.playerItem = [AVPlayerItem playerItemWithURL:url];
self.player = [AVPlayer playerWithPlayerItem:playerItem];
self.player = [AVPlayer playerWithURL:url];
[self.player play];
Try use AVAudioPlayer, see below
NSString *aSongURL = [NSString stringWithFormat:#"http://megdadhashem.wapego.ru/files/56727/tubidy_mp3_e2afc5.mp3"];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:aSongURL] error:nil];
[audioPlayer play];
Hope it works.
Cheers.

MPMusicPlayerController live streaming

I am developing an application that plays a live HTTP web radio streaming (.pls, .mp3 ...). Can i use the MPMusicPlayerController to play the stream ? Thaks.
I don't think you can play streaming audio using MPMusicPlayerController. You should look at AVPlayer.
NSURL *url = [NSURL URLWithString:url];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
AVPlayer *audioPlayer = [AVPlayer playerWithPlayerItem:playerItem];
[audioPlayer play];

Playing video from within app?

I am trying to play a local video from my app using AVPlayer. I have looked everywhere but can't find any useful tutorials/demos/documentation. Here is what I am trying, but it is not playing. Any idea why? The URL is valid because I was using the same one to play a video using MPMoviePlayer successfully.
Video *currentVideo = [videoArray objectAtIndex:0];
NSString *filepath = currentVideo.videoURL;
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
AVURLAsset *asset = [AVURLAsset assetWithURL: fileURL];
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset: asset];
self.player = [[AVPlayer alloc] initWithPlayerItem: item];
AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:self.player];
self.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
layer.frame = CGRectMake(0, 0, 1024, 768);
[self.view.layer addSublayer: layer];
[self.player play];
I believe the problem is that you're assuming that after executing this line AVURLAsset *asset = [AVURLAsset assetWithURL: fileURL]; the asset is ready to use. This is not the case as noted in the AV Foundation Programming Guide:
You create an asset from a URL using AVURLAsset. Creating the asset, however,
does not necessarily mean that it’s ready for use. To be used, an asset must
have loaded its tracks.
After creating the asset try loading it's tracks:
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
NSString *tracksKey = #"tracks";
[asset loadValuesAsynchronouslyForKeys:#[tracksKey] completionHandler:
^{
NSError *error;
AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error];
if (status == AVKeyValueStatusLoaded) {
// At this point you know the asset is ready
self.playerItem = [AVPlayerItem playerItemWithAsset:asset];
...
}
}];
Please refer to this link to see the complete example.
Hope this helps!

Resources