How to play 'http:/....... /mp3' with AVAudioPlayer - ios

I can't play mp3 audio file.
URL_PATH = #"http://...../.…./A1.mp3";
NSError *error;
player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL URLWithString:URL_PATH] error:&error];
if (error)
{
NSLog(#"error:%#",error.localizedDescription);
}
if (player ==nil)
{
NSLog(#"nil");
}
else
{
NSLog(#"playing");
[player play];
}
error code :
error:The operation couldn’t be completed. (OSStatus error -43.)
nil
How can I do?
Please tell me hint. pre-Thanks!

You are using the wrong player to play audio captured from a network stream. See Apple's documentation on AVAudioPlayer:
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. For an overview of audio technologies, see Audio & Video
Starting Point and “Using Audio” in Multimedia Programming Guide.
One work around way to use AVAudioPlayer is to fetch the audio's data and put it in a NSData. Then you can init your AVAudioPlayer by initWithData:error:. Also, don't put the code in your main queue. Else it will block your user interface from reacting to user's input.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *mp3URL = [NSURL URLWithString:#"http://zhangmenshiting.baidu.com/data2/music/44799433/4479927746800128.mp3?xcode=dbff90a141d5d136fdc7275fdc3fae126077a44adc974ad8"];
NSData *data = [NSData dataWithContentsOfURL:mp3URL];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:NULL];
[self.audioPlayer play];
});

sunkehappy is right, AVAudioPlayer isn't meant for streaming audio. It is meant for playing audio files and for data that is already in memory. That's why you need to init it with the data and not with the URL.
Here's the apple answer (which you can find here http://developer.apple.com/library/ios/#qa/qa1634/_index.html ):
The AVAudioPlayer class does not provide support for streaming audio
based on HTTP URL's. The URL used with initWithContentsOfURL: must be
a File URL (file://). That is, a local path.
If you look for an audio streamer, you can test that audio streamer.

Related

I am trying to play audio from server using AVAudioPlayer, but file not Playing

i am trying to make an online audio player. but i can't paly audio using AVAudioPlayer object. Please Help Me. Thanks in Advance.
Here is my audio player code.
================>>
NSURL *url =[[NSURL alloc] initWithString:#"My Url"];
xPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
xPlayer.numberOfLoops = 0;
xPlayer.volume = 1.0f;
[xPlayer prepareToPlay];
[xPlayer play];
Q: Does the AVAudioPlayer provide support for streaming audio content?
A: The AVAudioPlayer class does not provide support for streaming audio based on HTTP URL's. The URL used with initWithContentsOfURL: must be a File URL (file://). That is, a local path.
Source: https://developer.apple.com/library/ios/qa/qa1634/_index.html

iOS Audio Streaming and save audio file to document directry after audio playing finished

I want to play audio file from server to my iOS app and after audio playing complete want's to save audio to document directry for offline playing.
I have a code to play audio from server. please provide me any code to save file for offline playing.
NSURL *fileURL = // your url.
myAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:AudioFileURL error:nil];
myAudioPlayer.numberOfLoops = -1; //infinite loop
[myAudioPlayer play];
I have got a Streaming kit Frame work for this Audio streaming kit from Github
Play an MP3 over HTTP
STKAudioPlayer* audioPlayer = [[STKAudioPlayer alloc] init];
[audioPlayer play:#"http://www.abstractpath.com/files/audiosamples/sample.mp3"];
And append its data to NSMutabledata to play offline by using this delegate.
Intercept PCM data just before its played
[audioPlayer appendFrameFilterWithName:#"MyCustomFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames)
{
...
}];

iOS Streaming mp3

I've been searching for a good tutorial for playing and streaming audio finally I found this which seems to offer an offline audio playing.
in the YMCAudioPlayer class I've commented loading a resource and provided NSURL* generated by a direct link instead like so.
- (void)initPlayer:(NSString*) audioFile fileExtension:(NSString*)fileExtension
{
//NSURL *audioFileLocationURL = [[NSBundle mainBundle] URLForResource:audioFile withExtension:fileExtension];
NSURL *audioFileLocationURL = [NSURL URLWithString:#"http://188.95.64.47/AghaninaDownload/Content/per_singer/JFire/Audios/J-FirE_and_Omar_khalid_wlaKelmeh-sample.mp3"];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileLocationURL error:&error];
}
And I've ensured that it's a valid link, but seems not to play on emulator. what have I missed there?
EDIT
It generates the following error
Error Domain=NSOSStatusErrorDomain Code=-43 "The operation couldn’t be completed. (OSStatus error -43.)
Might be a stupid question, but did you make it play ?
[self.audioPlayer play];
Then I would try this, to ensure your settings are correct :
[self.audioPlayer prepareToPlay];
[self.audioPlayer setCurrentTime:0.0];
[self.audioPlayer setVolume:1.0];
[self.audioPlayer play];
You can also use the delegate of AVAudioPlayer to check if something happens when you play.
Else it might be an URL of format issue.
I think you cannot play audio on EMULATOR, you have to test it on device.
Here mentioned on apple developer guid -
https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/TestingontheiOSSimulator/TestingontheiOSSimulator.html#//apple_ref/doc/uid/TP40012848-CH4-SW1
I've found the answer in the accepted answer here
"I was able to fix the issue by loading the file first into an NSData element and then using that to initialize the AVAudioPlayer instead, like so:"
NSData *songFile = [[NSData alloc] initWithContentsOfURL:songCacheURL options:NSDataReadingMappedIfSafe error:&error1 ];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:songFile error:&error2];

How can I stream audio and also be able to control volume on iOS?

I've developed an iOS app that plays two separate audio streams simultaneously. To do this I am using AVPlayer thus:
//Use URL to set up the speech radio player.
NSURL *urlStreamSpeech = [NSURL URLWithString:self.urlAddressSpeech];
playerSpeech = [AVPlayer playerWithURL:urlStreamSpeech];
//Use URL to set up the music player.
NSURL *urlStreamMusic = [NSURL URLWithString:self.urlAddressMusic];
playerMusic = [AVPlayer playerWithURL:urlStreamMusic];
I am now trying to implement a volume control so that the user will be able to control the volume for the audio streams individually. As I've tried this I have come to the conclusion that there is no volume property for the AVPlayer class. I also looked at the AVAudioPlayer class, but from what I gather that class is only able to play local audio files, not streamed audio.
So my question is: how can I control the volume of streamed audio on iOS?
NSString* resourcePath = url; //your url
NSData *_objectData = [NSData dataWithContentsOfURL:[NSURL URLWithString:resourcePath]];
NSError *error;
app.audioPlayer = [[AVAudioPlayer alloc] initWithData:_objectData error:&error];
app.audioPlayer.numberOfLoops = 0;
app.audioPlayer.volume = 1.0f;
[app.audioPlayer prepareToPlay];
if (app.audioPlayer == nil)
NSLog(#"%#", [error description]);
else
[app.audioPlayer play];
Look into the AVPlayer class, part of the AVFoundation framework... this is the objective-c (iOS) class you use for streaming audio.
look at this post Live streaming
MPMusicPlayerController* musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
[musicPlayer setVolume:[SliderVolumen value]];
Only work in the device, no simulator.
Compatible with AVPlayer.

iPhone AVAudioPlayer app freeze on first play

I'm using AVAudioPlayer from iOS SDK for playing short sounds on each click in tableView rows.
I have manually made #selector on button in each row that fires up method playSound:(id)receiver {}. From receiver I get sound url so I can play it up.
This method looks like that:
- (void)playSound:(id)sender {
[audioPlayer prepareToPlay];
UIButton *audioButton = (UIButton *)sender;
[audioButton setImage:[UIImage imageNamed:#"sound_preview.png"] forState:UIControlStateNormal];
NSString *soundUrl = [[listOfItems objectForKey:[NSString stringWithFormat:#"%i",currentPlayingIndex]] objectForKey:#"sound_url"];
//here I get mp3 file from http url via NSRequest in NSData
NSData *soundData = [sharedAppSettingsController getSoundUrl:defaultDictionaryID uri:soundUrl];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithData:soundData error:&error];
audioPlayer.numberOfLoops = 0;
if (error) {
NSLog(#"Error: %#",[error description]);
}
else {
audioPlayer.delegate = self;
[audioPlayer play];
}
}
Everything works fine except for the first play of some sound. The application freezes for about 2 seconds and than sound is played. Second and every other sound play works just right after click on sound button.
I wonder why there is that about 2 seconds freeze on first play when application starts?
From your code snippet, audioPlayer must be an ivar, right?
At the top of the method, you invoke -prepareToPlay on the existing audioPlayer instance (which could be nil, at least on the first pass).
Later in the method, you replace this existing audio player with a brand new AVAudioPlayer instance. The previous -prepareToPlay is wasted. And you're leaking memory with each new AVAudioPlayer.
Instead of caching sound data or URLs, I would try creating a cache of AVAudioPlayer objects, one for each sound. In your -playSound: method, get a reference to the appropriate audio player for the table row, and -play.
You can use -tableView:cellForRowAtIndexPath: as the appropriate point to get the AVAudioPlayer instance for that row, maybe lazily creating the instance and caching it there as well.
You can try -tableView:willDisplayCell:forRowAtIndexPath: as the point where you would invoke -prepareToPlay on the row's AVAudioPlayer instance.
Or you could just do the prepare in -tableView:cellForRowAtIndexPath:. Experiment and see which works best.
Check whether you are getting data asynchronously in function..
NSData *soundData = [sharedAppSettingsController getSoundUrl:defaultDictionaryID uri:soundUrl];
If you are getting asynchronously the execution will be blocked until it will get data.
If your audio is less than 30 seconds long in length and is in linear PCM or IMA4 format, and is packaged as a .caf, .wav, or .aiff you can use system sounds:
Import the AudioToolbox Framework
In your .h file create this variable:
SystemSoundID mySound;
In your .m file implement it in your init method:
-(id)init{
if (self) {
//Get path of VICTORY.WAV <-- the sound file in your bundle
NSString* soundPath = [[NSBundle mainBundle] pathForResource:#"VICTORY" ofType:#"WAV"];
//If the file is in the bundle
if (soundPath) {
//Create a file URL with this path
NSURL* soundURL = [NSURL fileURLWithPath:soundPath];
//Register sound file located at that URL as a system sound
OSStatus err = AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &mySound);
if (err != kAudioServicesNoError) {
NSLog(#"Could not load %#, error code: %ld", soundURL, err);
}
}
}
return self;
}
In your IBAction method you call the sound with this:
AudioServicesPlaySystemSound(mySound);
This works for me, plays the sound pretty damn close to when the button is pressed. Hope this helps you.
This sometimes happens in the simulator for me too. Everything seems to work fine on the device. Have you tested on actual hardware?

Resources