I am using the MPMoviePlayerController to play an audio stream. To verify that there isn't a problem with playback, I set a movie playback error timer and I implement moviePreloadDidFinish. When moviePreloadDidFinish is called, I check the loadState for MPMovieLoadStatePlaythroughOK. If it is not called and my timer expires, I assume the download has failed.
- (void) moviePreloadDidFinish:(NSNotification*)notification
{
if (self.moviePlayer.loadState & MPMovieLoadStatePlaythroughOK) {
NSLog(#"The movie or mp3 finished loading and will now start playing");
// cancel movie playback error timer.
}
}
Occasionally, I do not receive this notification, yet audio keeps playing until my movie playback error timer expires (30 seconds). Does the absence of this moviePreloadDidFinish imply that the download of the audio stream is going to fail soon? If not, is there a better way to programmatically determine that there is a playback problem?
Related
I have an AVAudioPlayerNode object that is linked with an AVAudioEngine. I used the schedule method to load them in the queue. How can I know the state of the playback and when a single file start and finish to play?
This is the code I use for scheduling :
playerNode.scheduleFile(file, at: audioTime) {
// Completion
}
I use MPMoviePlayerController to play m3u8 stream. But it doesn't support me a method to check if the m3u8 link is working, so if the link is dead I must waiting for MPMoviePlayerController playing a while to make sure that it's not working. In this situation, I want to show an AlertView if the link is dead to keep user from not waiting before send the link to MPMoviePlayerController. Is there any way to do it ?
Try this once..
Normally we check this after some time, for that we can set a time delay
[self performSelector:#selector(movieTimedOut) withObject:nil afterDelay:20.f];
-(void)movieTimedOut
{
if (!(self.loadState & MPMovieLoadStatePlayable) || !(self.loadState & MPMovieLoadStatePlaythroughOK))
{
//AlertView
}
}
Quoted from Xcode doc,
AVAudioSessionSilenceSecondaryAudioHintNotification Posted on the main
thread when the primary audio from other applications starts and
stops.
Subscribe to this notification to ensure that your app is notified
when optional secondary audio muting should begin or end.
However, when my app's audio is playing, and I press the remote-control to start playing music from the Music app. This notification is not triggered in my observer callback. I believe the registration was successful.
Am I having the wrong expectation? Is it supposed to be triggered in a different scenario? Any examples?
You need to set your AVAudioSession Category to AVAudioSessionCategoryAmbient, then your app will allow background apps (such as music or podcasts) to play. If you set it to AVAudioSessionCategorySoloAmbient then it will not accept background music
You can do it like this:
NSError *categoryError = nil;
if ([[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&categoryError]) {
printf("Setting AVAudioSession CategoryAmbient Succeeded\n");
} else {
printf("Setting AVAudioSession CategoryAmbient Failed\n");
}
Check out Audio Session Categories for more details
I just started testing this very simple audio recording application that was built through Monotouch on actual iPhone devices today. I encountered an issue with what seemed to be the re-use of the AVAudioRecorder and AVPlayer objects after their first use and I am wondering how I might could solve it.
Basic Overview
The application consists of the following three sections :
List of Recordings (TableViewController)
Recording Details (ViewController)
New Recording (ViewController)
Workflow
When creating a recording, the user would click the "Add" button from the List of Recordings area and the application pushes the New Recording View Controller.
Within the New Recording Controller, the following variables are available:
AVAudioRecorder recorder;
AVPlayer player;
each are initialized prior to their usage:
//Initialized during the ViewDidLoad event
recorder = AVAudioRecorder.Create(audioPath, audioSettings, out error);
and
//Initialized in the "Play" event
player = new AVPlayer(audioPath);
Each of this work as intended on the initial load of the New Recording Controller area, however any further attempts do not seem to work (No Audio Playback)
The Details area also has a playback portion to allow the user to playback any recordings, however, much like the New Recording Controller, playback doesn't function there either.
Disposal
They are both disposed as follows (upon exiting / leaving the View) :
if(recorder != null)
{
recorder.Dispose();
recorder = null;
}
if(player != null)
{
player.Dispose();
player = null;
}
I have also attempted to remove any observers that could possible keep any of the objects "alive" in hopes that would solve the issue and have ensured they are each instantiated with each display of the New Recording area, however I still receive no audio playback after the initial Recording session.
I would be happy to provide more code if necessary. (This is using MonoTouch 6.0.6)
After further investigation, I determined that the issue was being caused by the AudioSession as both recording and playback were occurring within the same controller.
The two solutions that I determined were as follows:
Solution 1 (AudioSessionCategory.PlayAndRecord)
//A single declaration of this will allow both AVAudioRecorders and AVPlayers
//to perform alongside each other.
AudioSession.Category = AudioSessionCategory.PlayAndRecord;
//Upon noticing very quiet playback, I added this second line, which allowed
//playback to come through the main phone speaker
AudioSession.OverrideCategoryDefaultToSpeaker = true;
Solution 2 (AudioSessionCategory.RecordAudio & AudioSessionCategory.MediaPlayback)
void YourRecordingMethod()
{
//This sets the session to record audio explicitly
AudioSession.Category = AudioSessionCategory.RecordAudio;
MyRecorder.record();
}
void YourPlaybackMethod()
{
//This sets the session for playback only
AudioSession.Category = AudioSessionCategory.MediaPlayback;
YourAudioPlayer.play();
}
For some additional information on usage of the AudioSession, visit Apple's AudioSession Development Area.
I'm using AVPlayer to play streamed network audio. I observer status of the streamed item as this post:
ios avplayer trigger streaming is out of buffer
Work seems well, but I encounter a strange problem. I meet the key "playbackLikelyToKeepUp" before the key "playbackBufferEmpty". I placed a log
NSLog(#"___path: %#", path)
in the first line of the function
observeValueForKeyPath.....
and the log I received is:
...
2012-10-29 17:24:35.412 NhacSo[236:907] ___path: rate
2012-10-29 17:24:35.413 NhacSo[236:907] ___path: playbackLikelyToKeepUp
2012-10-29 17:24:35.415 NhacSo[236:907] ___path: playbackBufferEmpty
2012-10-29 17:24:35.416 NhacSo[236:907] ___path: rate
...
Do you know why I receive "playbackLikelyToKeepUp" before "playbackBufferEmpty"? Thank you!!!
You receive playbackLikelyToKeepUp first because that property changes first. What I believe is confusing you is that it changes from YES to NO and not the other way around - that is, playback will no longer be able to keep up.