I'm creating a video player view where I download URLs from the Internet to play using an AVQueuePlayer. It generally works pretty fine except sometimes I'll get the play icon slashed out and the AVQueuePlayer breaks.
I'm not sure what triggers this broken AVQueuePlayer state.
I create new AVQueuePlayers on viewappear and on viewdisappear I run these lines on the player
ViewAppear
if (self.player == nil){
self.player = AVQueuePlayer()
}
ViewDisappear
self.player.pause()
self.player.replaceCurrentItemWithPlayerItem(nil)
The main thing I'm curious of are there any potential reasons why a AVQueuePlayer will sometimes work and sometimes not? (It'll stop working after I trigger viewAppear, viewDisappear, viewAppear, etc. a few times)
Checking the network requests, when I do get the play button of death, no videos are streamed at all (0 network activity).
Potential reasons:
1)I'm thinking it might have something to do with the number of AVPlayers instantiated and I'm just not removing them correctly?
2) I also build the app on my phone a lot and close it while running it. Maybe this breaks the phone's avplayer over time?
Any directions for this type of behavior are appreciated.
EDIT: Interestingly enough, once in a while, it breaks so hard that I break every single app that plays video. Snapchat and Youtube don't work either after a certain point. I'm not sure how I broke every single player.
UPDATE: Getting this generic error for BOTH the AVPlayer & AVPlayerItem
Optional(Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action" UserInfo={NSLocalizedDescription=Cannot Complete Action, NSLocalizedRecoverySuggestion=Try again later.})
I am doing alarm based application in which my application is being prevent from deep sleep and fire local notification when time is comes up.For Prevent deep sleep i am using the mmpdeepsleeppreventer but it raise one problem in my application.When any one play music in music player and start my application then music player stop play music.How can i over come from this?
This is because audio session initialization in MMPDeepSleepPreventer.m in - (void)mmp_setUpAudioSession it uses audio session category kAudioSessionCategory_MediaPlayback.
Look for this Apple docs:
https://developer.apple.com/library/prerelease/ios/documentation/AudioToolbox/Reference/AudioSessionServicesReference/index.html
"This category normally prevents audio from other apps from mixing with your app's audio. To allow mixing for this category, use the kAudioSessionProperty_OverrideCategoryMixWithOthers property."
Try to set audion session property kAudioSessionProperty_OverrideCategoryMixWithOthers
I am not sure what the issue is but when i try to play MP4 videos hosted on akamai server, the MPMoviePlayerViewController fails to play it. I added notifications for monitoring playback state and it quickly switches from playing to stopped. If i print the error then i get the following:
MPMoviePlayerPlaybackDidFinishReasonUserInfoKey = 1;
error = "Error Domain=MediaPlayerErrorDomain Code=-11850 \"Operation Stopped\" UserInfo=0x1e5a6750 {NSLocalizedDescription=Operation Stopped}";
Above message is not very helpful in understanding what the actual issue might be. It is important to note that i am able to play the same URL in Safari and my app is able to play youtube videos without any issues.
The issue was pretty trivial - I was passing in an incorrect streaming URL :(. Thanks.
I'm setting up an AVAudioSession when the app launches and setting the delegate to the appDelegate. Everything seems to be working (playback, etc) except that beginInterruption on the delegate is not being called when the phone receives a call. When the call ends endInterruption is being called though.
The only thought I have is that the audio player code I'm using used to be based on AVAudioPlayer, but is now using AVPlayer. The callbacks for the AVAudioPlayer delegate for handling interrupts are still in there, but it seems odd that they would conflict in any way.
Looking at the header, in iOS6, it looks like AVAudioSessionDelegate is now deprecated.
Use AVAudioSessionInterruptionNotification instead in iOS6.
Update: That didn't work. I think there's a bug in the framework.
Yes, in my experience, beginInterruption, nor the newly documented AVAudioSessionInterruptionNotification work properly. What I had to do was track the status of the player using a local flag, then handle the endInterruption:withFlags: method in order to track recovery from interruptions.
With iOS 6, the resuming from an interruption will at least keep your AudioPlayer in the right place, so there was no need for me to store the last known play time of my AVAudioPlayer, I simply had to hit play.
Here's the solution that I came up with. It seems like iOS 6 kills your audio with a Media Reset if an AVPlayer stays resident too long. What ends up happening, is the AVPlayer plays, but no sound comes out. The rate on the AVPlayer is 1, but there's absolutely no sound. To add pain to the situation, there's no error on either the AVAudioSession setActive, nor the AVPlayer itself that indicates that there's a problem.
Add to the fact that you can't depend on appWillResignActive, because your app may already be in the background if you're depending on remote control gestures at all.
The final solution I implemented was to add a periodic observer on the AVPlayer, and record the last known time. When I receive the event that I've been given back control, I create a new AVPlayer, load it with the AVPlayerItem, and seekToTime to the proper time.
It's quite an annoying workaround, but at least it works, and avoids the periodic crashes that were happening.
I can confirm that using the C api, the interruption method is also not called when the interruption begins; only when it ends
(AudioSessionInitialize (nil, nil, interruptionListenerCallback, (__bridge void *)(self));
I've also filed a bug report with apple for the issue.
Edit: This is fixed in iOS 6.1 (but not iOS 6.0.1)
Just call:
[[AVAudioSession sharedInstance] setDelegate: self];
I just checked on my iPhone 5 (running iOS 6.0) by setting a breakpoint in the AudioSessionInterruptionListener callback function that was declared in AudioSessionInitialize(), and this interrupt callback does, in fact, get called when the app has an active audio session and audio unit and is interrupted with an incoming phone call (Xcode shows the app stopped at the breakpoint at the beginning of the interruption, which I then continue from).
I have the app then stop its audio unit and de-activate its audio session. Then, on the end interruption callback, the app re-activates the audio session and restarts the audio unit without problems (the app is recording audio properly afterwards).
I built a brand new audio streaming (AVPlayer) application atop iOS 6.0.x and found the same problem.
Delegates are now deprecated and we have to use notifications, that's great, however here's my findings:
During an incoming phone call I get only AVAudioSessionInterruptionTypeEnded in my handler, along with AVAudioSessionInterruptionOptionShouldResume. Audio session gets suspended automatically (audio fades) and I just need to resume playback of AVPlayer.
However when attempting to launch a game, such as CSR Racing, I oddly get the dreaded AVAudioSessionInterruptionTypeBegan but no sign when my application can resume playback, not even killing the game.
Now, this may depend on other factors, such as my audio category (in my case AVAudioSessionCategoryPlayback) and the mixing settings of both applications (kAudioSessionProperty_OverrideCategoryMixWithOthers), I'm not sure, but definitely I see something out of place.
Hopefully others reported that on 6.1beta this is fixed and I yet have to upgrade, so we'll see.
I'm a new iOS developer, I'm working on a video player app for a video sharing site, where sometimes a recording consists of two video streams (one showing the presenter, the other showing the recording of his screen). I'm trying to play this second video with AVFoundation, creating an AVPlayer. With some videos it works very well, but with some others it runs out of memory. After lot of investigating I figured that it tries to buffer the whole video into the memory.
I've spent hours googling it, but couldn't find anything.
I created a small project just to demonstrate this:
github project. It sets up two AVPlayer's, for two different video streams, and updates the UI to show the loadedTimeRanges of the players' AVPlayerItem. For the first video it only buffers ~60 seconds, which is nice, but for the second video it keeps buffering.
self.player1 = [AVPlayer playerWithURL:url1];
self.player2 = [AVPlayer playerWithURL:url2];
and the two text labels:
self.data1.text = [NSString stringWithFormat:#"Player 1 loadedTimeRanges: %#",
self.player1.currentItem.loadedTimeRanges];
self.data2.text = [NSString stringWithFormat:#"Player 2 loadedTimeRanges: %#",
self.player2.currentItem.loadedTimeRanges];
Maybe this could be important: The over-buffering video does not have an audio track, just a video.
UPDATE: I reproduced the problem with using MPMoviePlayerController instead of AVPlayer, and checking the playableDuration property. With the first movie it stops around 60 seconds, with the second movie it keeps going and then it runs out of memory.
UPDATE2: I got the actual video files and put them up to Dropbox, and tried to stream those: then I don't have the problem! It buffers the whole movie, but it does not run out of memory. It only runs out of memory if I stream them from the original site (our video sharing site). The URLs are there in the github project.
I'm really looking forward to any hints what could cause this.
Thank you!
This problem is indeed caused by the lack of an audio track for video streams sent from Wowza media server. (I have inferred from your stream URLs that you're using Wowza media server to stream your videos).
To verify this issue, I created a 5 minute video file with no audio track.
mplayer -nolirc -vo null -ao null -frames 0 -identify test_60.mp4
...
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
Selected video codec: [ffh264] vfm: ffmpeg (FFmpeg H.264)
==========================================================================
ID_VIDEO_CODEC=ffh264
Audio: no sound
Starting playback...
...
Then I added a mp3 track to that video file using mp4box.
MP4Box -new -add test_60.mp4 -add test_music.mp3 test_60_music.mp4
And verified that there was indeed an audio track.
mplayer -nolirc -vo null -ao null -frames 0 -identify /tmp/test_60_music.mp4
...
AUDIO: 44100 Hz, 2 ch, floatle, 320.0 kbit/11.34% (ratio: 40000->352800)
ID_AUDIO_BITRATE=320000
ID_AUDIO_RATE=44100
ID_AUDIO_NCH=2
Selected audio codec: [ffmp3float] afm: ffmpeg (FFmpeg MPEG layer-3 audio)
==========================================================================
AO: [null] 44100Hz 2ch floatle (4 bytes per sample)
ID_AUDIO_CODEC=ffmp3float
Starting playback...
...
Then, I put both the test_60.mp4 and test_60_music.mp4 in the Wowza content directory, and tested them. I actually wrote a small test app similar to yours to examine the loadedTimeRanges, but just loading the videos via safari from the device should be sufficient to see the difference.
I opened wowza_server:1935/vod/mp4:test_60.mp4/playlist.m3u8 and pressed pause as soon as it started playing. The buffer indicator kept increasing until the full 5 minute video was loaded.
Then, I opened wowza_server:1935/vod/mp4:test_60_music.mp4/playlist.m3u8 and did the same, but only the first 1/5th (roughly 1 minute) was loaded.
So it seems like a problem with the Wowza server's packetization - note this problem does not happen for me on adobe (flash) media server 5.0. Only 60 seconds is buffered regardless of whether the video contains an audio track.
Hope that's helpful. I've asked for input from Wowza folks at the Wowza forums