how to play sound by AVAssetReader - ios

I am using AVAssetReader to get the individual frames from a video file. I would like to know how I can play the audio from Mp4 file.
the return value of method [player play] is false, so there is no sound to play, but why
thanks.
create AVAssetReader
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"zhang" ofType:#"mp4"]];
AVURLAsset *avasset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetTrack *track1 = [[avasset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
NSMutableDictionary *dic2 = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsNonInterleaved, nil];
output1 = [[AVAssetReaderTrackOutput alloc] initWithTrack:track1 outputSettings:dic2];
AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:avasset error:nil];
[reader addOutput:output1];
[reader startReading];
output code is as following:
CMSampleBufferRef sample = [output1 copyNextSampleBuffer];
CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sample);
size_t length = CMBlockBufferGetDataLength(blockBufferRef);
UInt8 buffer[length];
CMBlockBufferCopyDataBytes(blockBufferRef, 0, length, buffer);
NSData * data = [[NSData alloc] initWithBytes:buffer length:length];
NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/test.mp3", docDirPath];
[data writeToFile:filePath atomically:YES];
[data release];
NSError *error;
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
player.numberOfLoops = 0;
[player play];

One option would be to avoid using the AVAudioPlayer, and instead use the PCM data you have decoded to fill an AudioQueue for output.
The ideal method would be to create an AVComposition from the audio track of an AVAsset that was created from your source mp4 file. That AVComposition (as a subclass of AVAsset) can be used inside an AVPlayer, which will then play just the audio track for you.
You're not able to simply write out blocks of PCM data into a file with the extension ".mp3" - that's an encoded format. The AVAudioPlayer will be looking for certain encoded data in the file, and the file you have written will be incompatible, which is why you are receiving a return value of false. If you have your heart set on writing the audio out to a file, use an AVAssetWriter with the appropriate settings. This could be written out as a Core Audio file for maximum performance. This step could also encode the audio as another format (say, mp3, or AAC), however this will have a heavy performance cost associated with it, and it's likely that it will not be suitable for real-time playback.

The assets is not playable immediately. Need to observe the value of status using key-value observing. Refer to the AVCam sample of Apple.

Related

Playing a local video using AVPlayer

I just wasted like 3 hours on this and I can't see where I'm going wrong.
I'm trying to play a video I have stored locally using AVPlayer. This is how I launch the player:
- (void)openVideo:(NSURL *)videoURL {
NSLog(#"Playing video with the url:\n%#", videoURL);
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
AVPlayerViewController *playerViewController = [AVPlayerViewController new];
playerViewController.player = player;
[self presentViewController:playerViewController animated:YES completion:nil];
}
And this is the NSURL I'm passing:
+ (NSURL *)getURL:(NSString *)itemKey withType:(NSString *)itemType {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *dataFilePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: [NSString stringWithFormat:#"%#.%#", itemKey, itemType]]];
NSURL *itemURL;
if ([[NSFileManager defaultManager] fileExistsAtPath: dataFilePath]){ // if data exists
itemURL = [NSURL fileURLWithPath:dataFilePath];
}
else {
NSLog(#"The data requested does not exist! Returning an empty url file...");
itemURL = nil;
}
return itemURL;
}
When I run openVideo, the output I get is:
Playing video with the url:
/var/mobile/Containers/Data/Application/72C35DC4-9EF1-4924-91F4-EDA4BDB6AAD3/Documents/sample.vid
But I keep getting a disabled video player..
What am I doing wrong?
Finally figured the issue out. I was downloading my files and storing them as NSData, and had to use writeToFile and specify the correct extension to read them correctly.
NSString *saveFilePath; = [NSTemporaryDirectory()stringByAppendingPathComponent:#"temp.mp4"];
[fileData writeToFile:saveFilePath atomically:YES];
NSURL *filepath = [NSURL fileURLWithPath:saveFilePath];
AVPlayer *player = [AVPlayer playerWithURL:filepath];
Hopefully this helps someone out there.

AVAudioPlayer initialization with web URL crashes

I have a sound file on a server and I try to play it on device.
Using this code:
NSURL audioURL = [NSURL URLWithString:#"http://..."];
NSError *error;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error]
crashes with the error:
Description of exception being thrown: '-[NSTaggedPointerString getCharacters:range:]: Range {0, 12} out of bounds; string length 5
The url has the length 73.
Firstly, why is it crashing instead of populating my error object?
If I use this code:
NSURL audioURL = [NSURL URLWithString:#"http://..."];
NSData *audioData = [NSData dataWithContentsOfURL:audioURL];
NSError *error;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData:audioData error:&error]
it works.
Looking at the name of the methods, it looks like they do the same thing, so why isn't the first method working?
Reading the AVAudioPlayer init methods' documentation reveals nothing related to this problem.
Are you streaming your audio file?
AVAudioPlayer cannot stream from URL. You can use it with files stored on device.
If you want to stream your file from URL you need to use AVPlayer
The following code:
AVPlayerItem *item = [AVPlayerItem playerItemWithURL: audioURL];
AVPlayer *myAVPlayer = [AVPlayer playerWithPlayerItem: item];
EDIT
When you are going to use your AVAudioPlayer with URL you need to present your URL like this:
NSString *backgroundMusicPath = [[NSBundle mainBundle] pathForResource:#"myMusic" ofType:#"mp3"];
NSURL *backgroundMusicURL = [NSURL fileURLWithPath:backgroundMusicPath];
Taken from here
Hope it will help

iOS: How to save a video in your directory and play it afterwards?

I am working in an iOS project. I want may application to download a video from the internet programmatically. Then I want to play it. I know how can I play a local video from the Resources, but my question is how could I download it , and the find it to be played.
I am using MPMoviePlayerController to run the video.
Thanking in advance
I found the answer
here I saved the video
NSString *stringURL = #"http://videoURL";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
NSString *documentsDirectory ;
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"videoName.mp4"];
[urlData writeToFile:filePath atomically:YES];
}
and this code is for playing the video form its directory
NSString *filepath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"videoName.mp4"];
//video URL
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
[moviePlayerController play];
If you have a valid url of the video, Apple provides an API to directly buffer videos with NSURL.
You should hold a reference to the MPMoviePlayerController object from the controller so that ARC doesn't release the object.
#property (nonatomic,strong) MPMoviePlayerController* mc;
Make the URL
NSURL *url = [NSURL URLWithString:#"http://www.example.com/video.mp4"];
Init MPMoviePlayerController with that URL
MPMoviePlayerController *controller = [[MPMoviePlayerController alloc] initWithContentURL:url];
Resize the controller, add it to your view, play it and enjoy the video.
self.mc = controller; // so that ARC doesn't release the controller
controller.view.frame = self.view.bounds;
[self.view addSubview:controller.view];
[controller play]; //Start playing
For more detail you can visit this playing video from a url in ios7

Play mp3 files with AVAudioPlayer with PlayAndRecord category?

Hi I have a setup that records audio (with AVAudioSessionCategoryPlayAndRecord category), now I want to playback and MP3 file as usual with AVAudioPlayer instance, but no any sound can be hear.
AVAudioPlayer do not throw any error, nor in its delegate callbacks.
Has anybody similar experience? How to overcome this?
Please use this -
NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
filePath = [NSString stringWithFormat:#"%#/%#.mp3", docDirPath , #"Welcome"];
NSError *error;
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
if (avPlayer == nil)
{
NSLog(#"AudioPlayer did not load properly: %#", [error description]);
}
else
{
[avPlayer play];
avPlayer.delegate=self;
}
And tell me if it is working or not.

Using NSData with MPMoviePlayerViewController

I am trying to use NSData with MPMoviePlayerViewController.
NSData *data = [NSData dataWithBytesNoCopy:mData3->mappedAddress+100398125 length:2313453 freeWhenDone:NO];
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF16StringEncoding];
NSURL *movieURL = [NSURL fileURLWithPath:dataString];
MPMoviePlayerViewController *moviePlayerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
[self presentMoviePlayerViewControllerAnimated:moviePlayerViewController];
This leads to the player opening for a second and then being dismissed.
When I access the movie file locally using the URL to the file in the main bundle it plays perfectly.
How does one use NSData to play a video on iOS?
Thanks
There is no way to play a movie directly from an in-memory NSData blob.

Resources