HysteriaPlayer
HysteriaPlayer copied to clipboard
HysteriaPlayer stops playing in background after some time
Hi, I have noticed such issue - hysteriaplayer stopps playing in background after some time and doesn't continue. I am working on radio application so playing only one url stream. I have configured remote status logs each 20 seconds. When player stopped getPlayingItemCurrentTime was 5345.68 seconds and getPlayingItemDurationTime was 0.0, getHysteriaPlayerStatus = 0 (HysteriaPlayerStatusPlaying). Seems that buffer become empty and AVplayer can't fill it due to some reason. After some time app was terminated due to the fact that playback is paused.
I am testing on a ipad 2 with ios 9.3.2 installed.
Before i have configured hysteria player i tried a lot of different approaches with AVPlayer but results were the same: After some time in background application stopped playing due to the fact that AVPlayer can't fill buffer.
Any ideas or workarounds regarding this issue?
I don't have such issue.
But one thing seems really weird.
If your player stopped, how come you get HysteriaPlayerStatusPlaying
status. This status simply indicates self.audioPlayer.rate ==1
, means AVPlayer
still playing.
If this really happens, this might a issue on AVFoundation
supporting streaming source.
@saiday Hi I am still investigating the issue and I have found some other details. Maybe you can help me with it. Right after app stops playing, delegate method is called hysteriaPlayerItemPlaybackStall. Player status still = HysteriaPlayerStatusPlaying. And after 180s background process is terminated because app is not playing any audio. There is no any fixed pattern. App can play audio without any issues during 3 hours or even 43 min and then it stops. Do you have an idea how i should process that scenario?
@sheff1422 May I have a sample URL and the code blocks you did when you received hysteriaPlayerItemPlaybackStall?
Sample url looks like this. And my delegate is placed at view controller. It looks like this http://mp3.nexus.org:8000/radiouniversallife.mp3
- (void)hysteriaPlayerItemPlaybackStall:(AVPlayerItem *)item{
PFObject *log = [PFObject objectWithClassName:@"RadioLogYura"];
HysteriaPlayer *hysteriaPlayer = [HysteriaPlayer sharedInstance];
log[@"Status"] = @"hysteriaPlayerItemPlaybackStall";
log[@"isPlaying"] = [NSString stringWithFormat:@"%d",hysteriaPlayer.isPlaying];
log[@"playerState"] = [NSString stringWithFormat:@"%ld",(long)[hysteriaPlayer getHysteriaPlayerStatus]];
log[@"CurrentTime"] = [NSString stringWithFormat:@"%.2f", hysteriaPlayer.getPlayingItemCurrentTime];
log[@"CurrentDuration"] = [NSString stringWithFormat:@"%.2f", hysteriaPlayer.getPlayingItemDurationTime];
[log saveInBackground];
}
Instance is created like this:
-(void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[HysteriaPlayer sharedInstance].delegate = self;
[HysteriaPlayer sharedInstance].datasource = self;
[[HysteriaPlayer sharedInstance] setPlayerRepeatMode:HysteriaPlayerRepeatModeOn];
[self configurePlayer];
[self configureTimer];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
Playback toggle
- (void)togglePlayerState {
if (self.playerState == RadioPlayerStatePause) {
self.playerState = RadioPlayerStatePlay;
} else if (self.playerState == RadioPlayerStatePlay){
self.playerState = RadioPlayerStatePause;
}
}
Playback state setter
- (void)setPlayerState:(RadioPlayerState)playerState {
_playerState = playerState;
if (playerState == RadioPlayerStatePlay) {
HysteriaPlayer *hysteriaPlayer = [HysteriaPlayer sharedInstance];
[hysteriaPlayer play];
[self.antena startAnimating];
[self.playButton setImage:[UIImage imageNamed:@"stop_button"] forState:UIControlStateNormal];
}
else if(playerState == RadioPlayerStatePause) {
HysteriaPlayer *hysteriaPlayer = [HysteriaPlayer sharedInstance];
[hysteriaPlayer pause];
[self.antena stopAnimating];
[self.playButton setImage:[UIImage imageNamed:@"play_button"] forState:UIControlStateNormal];
}
}
I am trying to add such thing to handle stall issue. But i am not sure that it will help
- (void)hysteriaPlayerItemPlaybackStall:(AVPlayerItem *)item{
PFObject *log = [PFObject objectWithClassName:@"RadioLogYura"];
HysteriaPlayer *hysteriaPlayer = [HysteriaPlayer sharedInstance];
log[@"Status"] = @"hysteriaPlayerItemPlaybackStall";
log[@"isPlaying"] = [NSString stringWithFormat:@"%d",hysteriaPlayer.isPlaying];
log[@"playerState"] = [NSString stringWithFormat:@"%ld",(long)[hysteriaPlayer getHysteriaPlayerStatus]];
log[@"CurrentTime"] = [NSString stringWithFormat:@"%.2f", hysteriaPlayer.getPlayingItemCurrentTime];
log[@"CurrentDuration"] = [NSString stringWithFormat:@"%.2f", hysteriaPlayer.getPlayingItemDurationTime];
[log saveInBackground];
self.playerState = RadioPlayerStatePause;
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
weakSelf.playerState = RadioPlayerStatePlay;
});
}
Unfortunately my workaround doesn't work. The flow looks like this:
- hysteriaPlayerItemPlaybackStall
- HysteriaPlayer *hysteriaPlayer = [HysteriaPlayer sharedInstance]; [hysteriaPlayer pause]; getHysteriaPlayerStatus = HysteriaPlayerStatusForcePause
- After 1.5 second [hysteriaPlayer play]; status is changed :getHysteriaPlayerStatus = HysteriaPlayerStatusPlaying However as i can see from my log buffer is not filling and app goes to sleep in 180s. Any ideas how can i fix that?
@saiday Hey Saiday, Do you have any ideas how i can fix that issue?
No, I don't have my computer till Nov. 7
I'll reply you soon
sheff1422 [email protected] 於 2016年11月5日星期六 寫道:
@saiday https://github.com/saiday Hey Saiday, Do you have any ideas how i can fix that issue?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/StreetVoice/HysteriaPlayer/issues/126#issuecomment-258603033, or mute the thread https://github.com/notifications/unsubscribe-auth/AB0vBwWOyYjsja_wgrqy6F3lvGa3c_gaks5q7FmigaJpZM4KiAfo .
@sheff1422
- hysteriaPlayerItemPlaybackStall
- HysteriaPlayer *hysteriaPlayer = [HysteriaPlayer sharedInstance]; [hysteriaPlayer pause]; getHysteriaPlayerStatus = HysteriaPlayerStatusForcePause
- After 1.5 second [hysteriaPlayer play]; status is changed :getHysteriaPlayerStatus = HysteriaPlayerStatusPlaying However as i can see from my log buffer is not filling and app goes to sleep in 180s. Any ideas how can i fix that?
in step 3, you got HysteriaPlayerStatusPlaying
, it simply indicates audioPlayer.rate == 1
, here's the code reference:
https://github.com/StreetVoice/HysteriaPlayer/blob/master/HysteriaPlayer/HysteriaPlayer.m#L619-L638
- did audio player actually play when you got
HysteriaPlayerStatusPlaying
? - you said log buffer is not filling, what is it? I can't find any relating code snippet from your comments.
- have you tried
hysteriaPlayerRateChanged:(BOOL)isPlaying
delegate? it can helps you monitoring player status.
@saiday Hi
- Audio player is playing till the time when delegate (void)hysteriaPlayerItemPlaybackStall:(AVPlayerItem *)item is called. Right after that moment player is not playing and remote log looks like this: [hysteriaPlayer getHysteriaPlayerStatus] = HysteriaPlayerStatusPlaying isPlaying = true getPlayingItemDurationTime is not changing getPlayingItemCurrentTime is not chaging
- I have configured log timer which is sending such parameters each 20 sec: getHysteriaPlayerStatus isPlaying getPlayingItemDurationTime getPlayingItemCurrentTime PreloadedTime Also application is sending status notifications when one of delegate methods is called. Due to the fact that getPlayingItemDurationTime&getPlayingItemDurationTime is not changing it looks like buffer is not filling anymore.
- hysteriaPlayerRateChanged:(BOOL)isPlaying is not called when stall delegate is triggered.
Also i tried to test it with other mp3 streams and situation was the same. After some time (1-3 hours of playback) it stopped playing and application goes to sleep due to the fact that player is not playing anymore.
Since I cannot reproduce, I can only provide you some clues. (If you can make a sample project contains your issue, it would be perfect)
The weirdest part is that when you received AVPlayerItemPlaybackStalledNotification sent by AVPlayer
instance, your AVPlayer
instance's rate still remains 1
, this make no sense and I have no such experience. (I never play streaming file, this issue might relating to streaming source type)
Due to the fact that getPlayingItemDurationTime&getPlayingItemDurationTime is not changing it looks like buffer is not filling anymore.
You can confirm "your buffer been filled or not" by set a breakpoint or add some logs on AVPlayerItem
's loadedTimeRanges
KVO callback, here's a quick code base ref:
https://github.com/StreetVoice/HysteriaPlayer/blob/master/HysteriaPlayer/HysteriaPlayer.m#L758
If you receive AVPlayerItem
's loadedTimeRanges
KVO callback after your player is stalled, then your buffer is filling properly.
@saiday
Thanks for your feedback.
I tried to monitor buffer with help of delegate - (void)hysteriaPlayerCurrentItemPreloaded:(CMTime)time
And as a result it is not fired after stalled notifications is received.
Would you be so kind to say what are you usually do when - (void)hysteriaPlayerItemPlaybackStall:(AVPlayerItem *)item
is called? Should i start playing from scratch?
Hi, Issue still exist. I user Hysteria Player in My Project and Apple reject it! Reason: "Specifically, the application plays silent audio to stay in the background."
So Weird, I check my app in debug mode, It's status really "playing" after music end.
Hi, I have found a couple of interesting things here. Isssue occurs predominantly for ios 9 (especially 9.3.5) When stalled delegate is called you need to stopp and then play again. that helped me to solve the issue.
@sheff1422
Sorry to reply you so late.
In case you're still interesting, I've done nothing on - (void)hysteriaPlayerItemPlaybackStall:(AVPlayerItem *)item
called.
@savasadar I suggest you resubmit your app or argue with them, HysteriaPlayer did play 0.1 sec sound on very first play request, this is because if your remote audio streaming have a high latency, in some cases app going to background and you are about to play, AudioSession will not initial hence we can not make any sound out.
This is really a big difference from "Specifically, the application plays silent audio to stay in the background."
And one following question:
So Weird, I check my app in debug mode, It's status really "playing" after music end.
which status you mean? HysteriaPlayer or OS?
@saiday Thanks for your reply. I will resubmit my app because I can't send message to reviewer from resolution center, message form is closed now.
[HysteriaPlayer sharedInstance].isPlaying
status still coming "YES".
I fixed it follows:
-(void)hysteriaPlayerDidReachEnd{ [[HysteriaPlayer sharedInstance] pause]; }
And I added my code this. Will this make a problem?
[[HysteriaPlayer sharedInstance] setSkipEmptySoundPlaying:YES];
@savasadar No, it's fine! Good luck~
@saiday I am still trying to get it accepted.
From Apple
- 10.0 Before You Submit: Program License Agreement (iOS) PLA 3.3.1
Your app uses public APIs in an unapproved manner, which does not comply with section 3.3.1 of the Apple Developer Program License Agreement.
Specifically, the app plays silent audio to stay in the background.
Since there is no accurate way of predicting how an API may be modified and what effects those modifications may have, Apple does not permit unapproved uses of public APIs in App Store apps.
Next Steps
Please revise your app to ensure that documented APIs are used in the manner prescribed by Apple.
If there are no alternatives for providing the functionality your app requires, we encourage you to file request enhancements to APIs and developer tools.
Alternatively, you may wish to consult with Apple Developer Technical Support to explore alternative solutions.