백그라운드에서 실행 중일 때 AVPlayer를 다운로드하면 오디오 (예 : podcast)를 재생할 수 없지만 다운로드 한 오디오는 재생할 수 없지만 로컬에 저장된 노래는 재생할 수 있습니다. 배경에서 재생하지 못하는 것은 휴대 전화가 내 컴퓨터에서 분리되었을 때뿐입니다. 내 전화기가 내 컴퓨터/디버거에 직접 연결되어 있으면 로컬 또는 다운로드 된 모든 미디어가 문제없이 재생됩니다. 포 그라운드에서는 미디어 유형을 재생하는 데 문제가 없습니다.AVPlayer 백그라운드에서 미디어가로드되지 않음
AVPlayer *moviePlayer;
AVPlayerItem *playerItem;
NSURL *address = /* the url of either a local song or remote media */
if (moviePlayer != nil) {
NSLog(@"removing rate, playbackBufferEmpty, playbackLikelyToKeepUp observers before creating new player");
[moviePlayer removeObserver:self forKeyPath:@"rate"];
[playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"];
[playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
[playerItem removeObserver:self forKeyPath:@"status"];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:playerItem];
[self setMoviePlayer:nil]; // release and nilify
}
// The following block of code was an experiment to see if starting a background task would resolve the problem. As implemented, this did not help.
if([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive)
{
NSLog(@"Experiment. Starting background task to keep iOS awake");
task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {
}];
}
playerItem = [[AVPlayerItem alloc]initWithURL:address];
moviePlayer = [[AVPlayer alloc]initWithPlayerItem:playerItem];
// Add a notification to make sure that the player starts playing. This is handled by observeValueForKeyPath
[moviePlayer addObserver:self
forKeyPath:@"rate"
options:NSKeyValueObservingOptionNew
context:nil];
[playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
// The following 2 notifications handle the end of play
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackDidFinish:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:playerItem];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackDidFinish:)
name:AVPlayerItemFailedToPlayToEndTimeNotification
object:playerItem];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackStalled:)
name:AVPlayerItemPlaybackStalledNotification
object:playerItem];
// Indicate the action the player should take when it finishes playing.
moviePlayer.actionAtItemEnd = AVPlayerActionAtItemEndPause;
moviePlayer.automaticallyWaitsToMinimizeStalling = NO;
업데이트 : 위의 구현에, 나는 또한 백그라운드에서 팟 캐스트를 재생 AVPlayer를 수 있도록 희망 백그라운드 작업을 시작하는 실험적인 시도를 보여주는하고
여기 내 구현입니다. 이것은 도움이되지 못했지만 참조 용으로 포함 시켰습니다. 표시되지 않지만 AVPlayerItem playbackLikelyToKeepUp 상태가 TRUE로 변경된 후에도 백그라운드 작업이 종료됩니다. 그런 다음
나는 키 패스 알림 처리하기 위해 다음과 같은 코드가 있습니다
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"rate"]) {
NSString *debugString = [NSString stringWithFormat: @"In observeValueForKeyPath: rate"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
}
else if (object == playerItem && [keyPath isEqualToString:@"playbackBufferEmpty"]) {
NSString *debugString = [NSString stringWithFormat: @"In observeValueForKeyPath: playbackBufferEmpty"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
}
else if (object == playerItem && [keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {
NSString *debugString = [NSString stringWithFormat: @"In observeValueForKeyPath: playbackLikelyToKeepUp"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
}
else if (object == playerItem && [keyPath isEqualToString:@"status"]) {
NSString *debugString = [NSString stringWithFormat: @"In observeValueForKeyPath: status"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
}
}
을 그리고 알림 notificationCenter 처리하기 위해 다음과 같은 한 :
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
NSLog(@"moviePlaybackDidFinish. Time to stopMoviePlayerWithMusicPlayIndication");
[self stopMoviePlayer: YES]; // stop the movie player
}
- (void) moviePlayBackStalled:(NSNotification*)notification {
NSString *debugString = [NSString stringWithFormat: @"In moviePlayBackStalled. Restarting player"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
[moviePlayer play];
}
을 실행을 추적하는 로깅 툴을 구현함으로써 분리 할 때 컴퓨터에서 여기 내가 관찰하고있는 것이 있습니다 :
컴퓨터에서 연결이 끊긴 백그라운드에서 실행될 때, playerItem URL 주소가로드되고 AVPlayer는 playerItem으로 초기화됩니다. 이로 인해 observeValueForKeyPath : rate 알림이 게시되지만 마지막 수신 된 알림입니다. 오디오가 재생되지 않습니다. 플레이어가 멈 춥니 다. 다음과 같이 다양한 moviePlayer 및 playerItem 플래그를 보여주는 내 로그의 출력은 다음과 같습니다
ready to play movie/podcast/song dedication/Song from url: http://feedproxy.google.com/~r/1019TheMix-EricAndKathy/~5/ZZnF09tuxr0/20170309-1_1718764.mp3
In observeValueForKeyPath: rate - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusUnknown, playbackToKeepUp: 0, playbackBufferEmpty: 1, playbackBufferFull: 0, rate: 1.0
을하지만, 직접 컴퓨터에 연결하거나 포 그라운드에서 실행하면 백그라운드에서 실행하는 경우, 아래의 로그 출력에서 볼 수 url 주소가로드되고 AVPlayer가 playerItem으로 초기화되면 keyPath : rate, playbackBufferEmpty, playbackLikelyToKeepUp 및 status에 대한 일련의 알림이 게시됩니다. 그러면 오디오가 재생되기 시작합니다. 다음과 같이 다양한 moviePlayer 및 playerItem 플래그를 보여주는 출력은 다음과 같습니다 포 그라운드에서 직접 컴퓨터/디버거에 연결하면 백그라운드에서 실행하는 경우
는ready to play movie/podcast/song dedication/Song from url: http://feedproxy.google.com/~r/1019TheMix-EricAndKathy/~5/d3w52TBzd88/20170306-1-16_1717980.mp3
In observeValueForKeyPath: rate - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusUnknown, playbackToKeepUp: 0, playbackBufferEmpty: 1, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: playbackBufferEmpty - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusUnknown, playbackToKeepUp: 0, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: playbackLikelyToKeepUp - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusUnknown, playbackToKeepUp: 0, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: status - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusReadyToPlay, playbackToKeepUp: 0, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: playbackLikelyToKeepUp - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusReadyToPlay, playbackToKeepUp: 1, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: rate - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusReadyToPlay, playbackToKeepUp: 1, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
그래서 요약, 그 위에 참조 AVPlayer를 성공적으로 재생 버퍼를로드 오디오를 재생합니다. 그러나 백그라운드에서 실행 중이고 컴퓨터/디버거에 연결되어 있지 않으면 플레이어가 미디어를로드하지 않고 멈추는 것처럼 보입니다.
모든 경우에 AVPlayerItemPlaybackStalledNotification은 절대로 수신되지 않습니다.
대단히 죄송합니다. 컴퓨터에 연결되어 있지 않을 때 플레이어가 백그라운드에서 멈추는 원인을 누가 볼 수 있습니까?
재생을 시작할 때'beginBackgroundTask'를 호출 해 보았습니까? 문서는 백그라운드로 실행해서는 안되며, 끝나지 않은 비즈니스에도 유용하다고 말합니다. https://developer.apple.com/reference/uikit/uiapplication/1623031-beginbackgroundtask –
@ 리듬의 주먹 예, 나는 그것을 시도했다. 도움이되지 않았다. 게다가 AVPlayer는 백그라운드에서 로컬 미디어를 재생할 때 아무런 문제가 없으므로 iOS를 잠자기 상태로 만드는 것과 같은 문제는 아닙니다. – JeffB6688
로컬 파일의 타이밍 속성이 다릅니다. 일정이 잡히지 않게하려면 백그라운드 오디오 앱이 오디오를 재생 중이어야합니다. AVPlayer가 재생하기 전에 오디오 데이터를 스트리밍 할 시간이 필요하다는 사실이 문제 일 수 있습니다. –