Play sound from NSData using AVAudioPlayer iOS - ios

I would like to play a sound file retrieved from my server, as a base 64 encoded file.
So far, I have decoded the file using base64 and written it to a file as so:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"voicemail.wav"]];
[fileManager createFileAtPath:filepath contents:[responseDict objectForKey:#"ResponseData"] attributes:nil];
However, I am having trouble actually playing the sound file. My code returns the error:
The operation couldn't be completed. OSStatus error 2003334207.
Please can you tell me where I am going wrong?
NSURL * url = [NSURL fileURLWithPath:filePath];
AVAudioPlayer *sound = [[[AVAudioPlayer alloc] initWithContentsOfURL:url error:&err] autorelease];
if (! sound) {
NSLog(#"Sound had error %#", [err localizedDescription]);
} else {
[sound prepareToPlay];
[sound play];
}

#Himanshu
As suggested by the Mattias Wadman, I tried to play downloaded file using vlc/iTunes media player and the file were not playing.
So the problem may be in the encoding or in decoding of file, not in the play audio code. I checked for the same and there were some extra characters embedded while encoding.
We worked on encoding and resolved the issue.
Hope this helps.

NSData *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"FileName.mp3"]
NSURL *url = [[NSURL alloc] initFileURLWithPath: path];
AVAudioPlayer *sound = [[[AVAudioPlayer alloc] initWithContentsOfURL:url error:&err] autorelease];
if (! sound) {
NSLog(#"Sound had error %#", [err localizedDescription]);
} else {
[sound prepareToPlay];
[sound play];
}

Related

unable to play mp3 file in avplayer in ios app

I tried to play mp3 file using AVP player. But i couldn't play it..my code is
NSString *fileurl=[FILE_URL_Array objectAtIndex:indexPath.row];
NSArray *parts = [fileurl componentsSeparatedByString:#"/"];
NSString *filename = [parts lastObject];
NSLog(#"file name is %#",filename);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,filename];
//NSString* documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString* foofile = [documentsDirectory stringByAppendingPathComponent:filename];
NSLog(#"foofile %#",foofile);
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
NSLog(#"boolean value is %hhd",fileExists);
if (fileExists)
{
NSURL *audioURL = [NSURL fileURLWithPath:filePath];
NSLog(#"existig url is%#",audioURL);
NSData *urlData =[NSData dataWithContentsOfURL:audioURL];
// NSString *sourcePath =[audioURL path];
//UISaveVideoAtPathToSavedPhotosAlbum(sourcePath,nil,nil,nil);
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,filename];
[urlData writeToFile:filePath atomically:YES];
audioPlayer = [[AVAudioPlayer alloc]initWithData:urlData error:NULL];
audioPlayer.delegate = self;
[audioPlayer play];
}
but i am unable to play that audio file....Please give your valuable solution.Thanks in advance...
You're currently appending documentsDirectory twice.
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,filename];
//NSString* documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString* foofile = [documentsDirectory stringByAppendingPathComponent:filename];
Once in filePath, and again in foofile.
Additionally, you seem to be doing a whole bunch of extra processing that you don't need to be doing. You should be able to create the audio player from the initial file url:
NSString *fileurl=[FILE_URL_Array objectAtIndex:indexPath.row];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL urlWithString:fileUrl] error:&error];
if (error != nil) {
NSLog(#"Error creating player: %#", error);
}
audioPlayer.delegate = self;
[audioPlayer prepareToPlay];
[audioPlayer play];

Download Audio file from URL and play it in iOS App

I have an URL which I get from JSON response, When I hit the URL in browser the file is downloaded, Now am wondering how can I play such URL which is a Download URL.I've been looking around many post But none of them could help me.
type of url am getting : http://www.smartivr.in/sounds/voicemail/download/f77245d9-e7ee-4424-850c-6a45022d0a54_1
Below is the code I tried.
NSString *audio=[NSString stringWithFormat:#"%#.mp3",cell.url];
NSLog(#"url:%#",audio);
NSURL *url = [NSURL fileURLWithPath:audio];
NSData *soundData = [NSData dataWithContentsOfURL:url];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:#"sound.caf"];
[soundData writeToFile:filePath atomically:YES];
NSError *error;
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:filePath] error:&error];
[_audioPlayer play];
NSLog(#"error %#", error);
Try this:
//download your audio file
NSString *urlString = #"http://www.smartivr.in/sounds/voicemail/download/f77245d9-e7ee-4424-850c-6a45022d0a54_1.mp3";
NSURL *url = [NSURL fileURLWithPath:urlString];
NSData *soundData = [NSData dataWithContentsOfURL:url];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:#"sound.caf"];
[soundData writeToFile:filePath atomically:YES];
// get the file from directory
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsDirectory = [pathArray objectAtIndex:0];
NSString *soundPath = [documentsDirectory stringByAppendingPathComponent:#"sound.caf"];
NSURL *soundUrl;
if ([[NSFileManager defaultManager] fileExistsAtPath:soundPath])
{
soundUrl = [NSURL fileURLWithPath:soundPath isDirectory:NO];
}
// play audio file
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
[audioPlayer prepareToPlay];
[audioPlayer play];
You should download your audio file asynchronously.
Thank You Dipankar Das for you help.
I am posting the whole solution here.
which worked for me absolutely.
NSString *audio=#"http://www.smartivr.in/sounds/voicemail/download/f77245d9-e7ee-4424-850c-6a45022d0a54_1.mp3";
NSURL *url = [NSURL URLWithString:audio];
NSData *soundData = [NSData dataWithContentsOfURL:url];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:#"sound.caf"];
[soundData writeToFile:filePath atomically:YES];
// get the file from directory
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsDirectory = [pathArray objectAtIndex:0];
NSString *soundPath = [documentsDirectory stringByAppendingPathComponent:#"sound.caf"];
NSURL *soundUrl;
if ([[NSFileManager defaultManager] fileExistsAtPath:soundPath])
{
soundUrl = [NSURL fileURLWithPath:soundPath isDirectory:NO];
}
// plau audio file
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
[_audioPlayer prepareToPlay];
[_audioPlayer play];
[_audioPlayer setVolume:5.0];
try use AVPlayer or AVPlayerViewController, you can use direct URL to play mp3 files
even with local file as you will first download it to device, then play from local URL
do not forget that object AVPlayer has to be as property of your Class not local object because of auto-releasing, so declare your player variable in class and set in function not just locally in function and try to play ...
[update]
more details how to do it -> How to play video with AVPlayerViewController (AVKit) in Swift
Here is the mistake
NSString *audio=[NSString stringWithFormat:#"%#.mp3",cell.url];
NSURL *url = [NSURL fileURLWithPath:audio];
I assume that it is a remote url and you cannot treat it as a file url. So you must use
NSURL *url = [NSURL urlWithString:audio];

Download and play mp3 file from URL

I have downloaded a mp3 file but i'm not able to play it. The file is downloaded, i've checked but when i try to play the local file, nothing happens. If i directly play it without downloading it, it plays.
- (IBAction)downloadTrack:(id)sender {
NSData *soundData = [NSData dataWithContentsOfURL:self.song.ticket.url];
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documents stringByAppendingPathComponent:self.song.slug];
[soundData writeToFile:filePath atomically:YES];
NSURL *urlFile = [NSURL URLWithString:filePath];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:urlFile error:nil];
player.numberOfLoops = -1; //Infinite
[player play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Download
NSString *urlString = #"https://oi.net/songs/5-dope-ski-128k.mp3";
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSData *soundData = [NSData dataWithContentsOfURL:url];
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documents stringByAppendingPathComponent:#"5-dope-ski-128k.mp3"];
[soundData writeToFile:filePath atomically:YES];
// Play
NSString *filename = #"Ola.mp3";
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsDirectory = [pathArray objectAtIndex:0];
NSString *yourSoundPath = [documentsDirectory stringByAppendingPathComponent:filename];
NSURL *soundUrl;
if ([[NSFileManager defaultManager] fileExistsAtPath:yourSoundPath])
{
soundUrl = [NSURL fileURLWithPath:yourSoundPath isDirectory:NO];
}
// Create audio player object and initialize with URL to sound
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
[_audioPlayer play];
}

Getting Exc_Bad_access in AVAssetReader

I am getting Exc_bad_Access exception while reading a file with AVAssetReader .
The File is located in document directory and is in m4a format. Here is the code i am using. Not able to figure out where m getting it wrong:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filepath = [documentsDirectory stringByAppendingPathComponent:#"My_Recording2.m4a"];
NSURL *newURL=[NSURL URLWithString:filepath];
if ([[NSFileManager defaultManager] fileExistsAtPath:newURL.absoluteString])
{
NSLog(#"File exists");
}
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:newURL options:nil];
NSError *assetError;
if(asset)
NSLog(#"all ok");
self.assetReader = [AVAssetReader assetReaderWithAsset:asset error:&assetError];
I am getting the exception at last line i.e.
self.assetReader = [AVAssetReader assetReaderWithAsset:asset error:&assetError];
I think your [NSURL URLWithString:filepath] is not right.
Can you try with fileURLWithPath method. Hopefully that will solve your issue.

Load audio in DOCUMENTS when UITableView "cell" is pressed

I have a UITableView displaying a llist f files in the Documents Directory... and I want it to play the audio file in the Documents directory when pressed...
It runs with no errores but doesn't play the audio when pressed...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.caf",indexPath.row+1]];
NSURL *audioURL = [NSURL URLWithString:fileName];
NSData *audioData = [NSData dataWithContentsOfURL:audioURL];
NSError *error;
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
_audioPlayer.delegate = self;
[_audioPlayer play];
}
Change this line:
NSURL *audioURL = [NSURL URLWithString:fileName];
to this:
NSURL *audioURL = [NSURL fileURLWithPath:fileName isDirectory:NO];
And then just do:
if(_audioPlayer == nil)
{
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
}
else
{
_audioPlayer = [self.audioAlert initWithContentsOfURL:audioURL error:nil];
}
To start out, the best way to declare a files path is this
- (NSString *)docsdir {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
}
in your header, declareNSString *Path;
then, declare the path like this when the view loads
Path = [[self docsdir]stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.caf",indexPath.row+1]];
if (![[NSFileManager defaultManager]fileExistsAtPath:Path]) {
[[NSFileManager defaultManager]copyItemAtPath:[[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:#"%d",indexPath.row+1] ofType:#"caf"] toPath:Path error:nil];
}
now to play it, do this
AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:Path] error:&error];
player.delegate = self;
[player play];

Resources