How can I play an mp4 resource with AVPlayer? - objective-c

I have included an mp4 resource in my project navigator. I want to play it in an AVPlayer. I know how to create an AVPlayerItem for the AVPlayer object, and so now I'd like to load the appropriate AVAsset into it pointing to my mp4 resource. The problem is that AVAsset only has an assetWithURL: method to create an AVAsset. I want an assetWithName: method, but that method does not exist. How can I play my mp4 file if I don't have a URL for it? If it's not possible to play via name reference, how can I get a file URL for my mp4 file?

To get the URL, use
[[NSBundle mainBundle] URLForResource:#"my_video" withExtension:#"mp4"]

It will probably be in your main bundle, you can get its URL with
- (NSString*) saveFilePath: (NSString *) add
{
NSString *filename = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:
[[NSBundle mainBundle] pathForResource:add ofType:#"mp4"]isDirectory:NO]]];
return filename;
}
Copy this into your code and then do [self saveFilePath:#"Name of your file"] to get the URL.
Full code:
AVPlayer *player = [[AVPlayer alloc] initWithURL:[self saveFilePath:#"fileName"];
[player play];

Related

AVPlayer playerWithURL not working after app restart

I am picking a video from the user photo library and than I save the video in the user Documents Folder to be able to play the video even if the user deletes this video from his photo Library. The URL to this file is stored in Core Data.
Everything works fine until the next time I run the App. Somehow it seems like the URL is no longer valid, which is strange because I am able to delete the video file when [AVPlayer playerWithURL:videoURL] fails.
Here is how I pick the video URL:
- (void) imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
NSURL* videoURL = info[UIImagePickerControllerMediaURL];}
This is how I save the video:
+ (NSURL*) saveVideoInDocumentsFolder:(NSURL*)videoURL name:(NSString*)name {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* pathComponent = [NSString stringWithFormat:#"/%#.%#", name, [videoURL pathExtension]];
NSString* path = [documentsDirectory stringByAppendingPathComponent:pathComponent];
NSError* error = nil;
NSData* videoData = [NSData dataWithContentsOfURL:videoURL options:0 error:&error];
if (error)
return nil;
BOOL success = [videoData writeToFile:path options:NSDataWritingAtomic error:&error];
if (success)
return [NSURL fileURLWithPath:path];
return nil;}
This is how I play the video:
AVPlayer* player = [AVPlayer playerWithURL:videoURL]; // <- AFTER I RESTART THE APP THIS METHOD ALWAYS RETURNS nil!!
AVPlayerViewController* viewController = [[AVPlayerViewController alloc] init];
[self presentViewController:viewController animated:YES completion:nil];
viewController.player = player;
[player play];
Many thanks in advance!
The URL to this file is stored in Core Data
That's the problem. The documents directory URL changes every time you run the app (because you are sandboxed), so it isn't valid the second time. Never never never save an absolute file URL in iOS!
You need to take every time the path directory when close and open app , because when app close it it removes documentDirectory, so you have to take it another time , and if you want to get your video file then save the FILE NAME of that video into preference or Core Data then get documentDirectory path by appending this video name file and you will get your video.
Just have a look: - (code is in swift you can convert it objective c easily)
let fileName = "recording.mp4"
let tempPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let tempDocumentsDirectory: AnyObject = tempPath[0] as AnyObject
let tempDataPath = tempDocumentsDirectory.appendingPathComponent(fileName) as String as String
that FILE NAME you will save in preference or coreData
and when you close and open the app just check do you have FILE NAME save in preference or in core data if yes then take it by appending with documentsDirectory and you will get your video

Objective-C UIDocumentInteractionController Couldn't issue file extension for path

I am having an issue with UIDocumentInteractionController, here is my code:
NSURL *URL = [NSURL fileURLWithPath:#"http://www.domain.com/pdf/35.pdf"];
//NSURL *URL = [[NSBundle mainBundle] URLForResource:#"35" withExtension:#"pdf"];
if (URL) {
// Initialize Document Interaction Controller
self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:URL];
// Configure Document Interaction Controller
[self.documentInteractionController setDelegate:self];
// Preview PDF
[self.documentInteractionController presentPreviewAnimated:YES];
}
my console log says this:
Couldn't issue file extension for path: /http:/www.domain.com/pdf/35.pdf
and in my app it displays a gray background and says 35.pdf Portable Document Format (PDF)
what am i doing wrong?
An http URL is not a file URL.
This:
NSURL *URL = [NSURL fileURLWithPath:#"http://www.domain.com/pdf/35.pdf"];
needs to be:
NSURL *URL = [NSURL URLWithString:#"http://www.domain.com/pdf/35.pdf"];
But note that UIDocumentInteractionController expects a URL to a local resource, not an Internet URL. So you can't use the above URL at all.
You would need to download and save the PDF file locally first and then create a proper file URL to the local file.

How do I find the URL of a mp4 resource file?

Why can't I find a resource when it's an ".mp4"?
My code is:
- (IBAction)babelFishButton:(id)sender {
NSURL *url = [[NSBundle mainBundle] URLForResource:#"BabelFish" withExtension:#"mp4"];
MPMoviePlayerController *player =[[MPMoviePlayerController alloc] initWithContentURL: url];
[player prepareToPlay];
[player.view setFrame: self.imageView.bounds]; // player's frame must match parent's
[self.imageView addSubview: player.view];
[player play];
}
BabelFish.mp4 exists in the project navigator, and finder tells me it's in the app root folder, along with main.m, etc.
But the video does not play because url is nil (the file is not being found). I can paste in a copy of the file and rename it "BabelFish.txt", change the extension in the code and it finds the file.
Why won't it find "mp4" files? How do I get the URL of an mp4 file?
Jeff
Try this:
NSString *myUrlSTR = [[NSBundle mainBundle] pathForResource:#"BabelFish" ofType:#"mp4"];
Another thing make sure that your file is not only listed in your Project Explorer, but also included in your Copy Bundle Resources list.

(iOS) Why does AVAudioPlayer initWithContentsOfURL always fail with error code=-43

NSString *songNameEscaped = [songName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *songURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", #"http://somerootpath/Music/", songNameEscaped]];
NSLog(#"songURL = %#", songURL);
NSError *avPlayerError = nil;
AVAudioPlayer *avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:songURL error:&avPlayerError];
if (avPlayerError)
{
NSLog(#"Error: %#", [avPlayerError description]);
}
else
{
[avPlayer play];
}
If I copy the NSLog output from NSLog(#"songURL = %#", songURL); and paste it in safari, Quicktime plugin plays the files no problem so I know the URLs are valid. I've tried with .m4a and .mp3 files and have tried removing the spaces from songName but not matter what I always get Error:
Error Domain=NSOSStatusErrorDomain Code=-43 "The operation couldn’t be completed. (OSStatus error -43.)".
But they are just standard .m4a / .mp3 files created in iTunes.
Apparently AVAudioPlayer doesn't support streaming. Apple recommends AVPlayer for this although it is not as conveinient for finding things like current time and duration .
Error -43 indicates an inability to find the data. This could be because the url was in fact malformed, or because the server doesn't support streaming. You should try to pre-load the song data with an NSData object.
NSString *songNameEscaped = [songName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *songURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", #"http://somerootpath/Music/", songNameEscaped]];
NSLog(#"songURL = %#", songURL);
NSError *avPlayerError = nil;
NSData* songData = [NSData dataWithContentsOfURL:songURL error:&avPlayerError];
if (songData)
{
AVAudioPlayer *avPlayer = [[AVAudioPlayer alloc] initWithData error:&avPlayerError];
if (avPlayer)
{
[avPlayer prepareToPlay];
[avPlayer play];
}
else
{
NSLog(#"Error initializing data for AVAudioPlayer. Possibly an Unsupported Format");
NSLog(#"Error: %#", [avPlayerError description]);
}
}
else
{
NSLog(#"Error initializing data for AVAudioPlayer. Possibly Malformed URL");
NSLog(#"Error: %#", [avPlayerError description]);
}
I had the same problem yesterday. Turns out my url was wrong.
I had something like you here:
NSURL *songURLID = [NSURL URLWithString:[NSString stringWithFormat:#"%#%d", #"http://somerootpath/Music/", songNameEscaped]];
NSLog(#"songURL = **%d**", songURL**ID**);
But, my songURL was of NSString type. My NSLog wrote it correctly but when I put %d in url it turn out wrong. I suggest you try to check out your AVAudioPlayer url again.
try something like described here to see the players url.
You may want to try checking the targets on your audio file. I had a similar issue and fixed it by making sure that my mp4 file target membership check box was checked. I must not have checked it when I was importing the file originally.
in Apple documentation
An instance of the AVAudioPlayer class, called an audio player,
provides playback of audio data from a file or memory.
Apple recommends that you use this class for audio playback unless you
are playing audio captured from a network stream or require very low
I/O latency.

playing music by url

I want to play the music from internet by url.
I create a simply project that has one button with the following code:
NSURL *url = [[NSURL alloc] initWithString:#"http://someURL.mp3"];
NSError **err;
QTMovie *movie = [[QTMovie alloc] initWithURL:url error:err];
[movie play];
It works but with some delay (I think because it waits while file has been fully downloaded).
So what I need to do that the music starts to play immediately (when, for example, 10% of file has been downloaded)?
Use -[QTMovie autoplay] to automatically play the music once enough data has been downloaded.
In your case:
NSURL *url = [[NSURL alloc] initWithString:#"http://someURL.mp3"];
NSError **err;
QTMovie *movie = [[QTMovie alloc] initWithURL:url error:err];
[movie autoplay];
From the QTMovie class reference:
The autoplay method configures a QTMovie object to begin playing as soon as enough data is available that the playback can continue uninterrupted to the end of the movie.
If you can consider displaying a Quicktime window over your app, you can use this code :
NSString *url = #"http://someURL.mp3";
UIWebView* tempAudioPlayer = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[tempAudioPlayer loadHTMLString:[NSString stringWithFormat:#"<iframe frameborder=\"0\" width=\"0\" height=\"0\" src=\"%#\"></iframe>", url] baseURL:nil];
[self addSubview:tempAudioPlayer];
I first create a UIWebView which will not be displayed. Then I loadHTMLString a <iframe> in it, with the URL of my file as the src value. And I add it to my view. Quicktime appears immediately.