AVComposition breaks on Airplay - ios

I have a video composition which I'd like to play over Airplay (without mirroring). The app works as expected when using normal Airplay mirroring, but I'd like to get the speed, reliability, and resolution bump you get from using Airplay video instead.
The problem is that when I set
player.usesAirPlayVideoWhileAirPlayScreenIsActive = YES;
...the player goes blank.
Notes:
Since I don't create separate windows for each display, they are both trying to use the same AVPlayer.
My AVVideoComposition contains different files and adds opacity ramps between them.
This unanswered question suggests that the problem is more likely due to the fact that I'm playing an AVComposition than the use of a shared player: AVComposition doesn't play via Airplay Video
Two questions:
Do I have to get rid of the player on the iPad?
Can an AVVideoComposition ever be played over AirPlay?

I can't make comments so I had to post this as an answer although it might not fully respond to the questions.
I had similar issue and at the end I found out that when AVPlayer plays AVComposition it simply doesn't display anything on the external display. That's why I had to do it myself by listening to UIScreen connection notifications.
I have to say that all worked pretty perfect. I'm checking first if there are more than one screen and if there are I simply move the AVPlayer on that screen while displaying a simple message on the device's screen that content is played on... plus the name of AirPlay device. This way I can put whatever I want on the external display and is not very complicated. Same thing is when I receive UIScreenDidConnectNotification.
That was fine until I noticed that the composition plays really choppy on the the external display. Even if it consists of only one video without any complex edits or overlays. Same video plays perfectly if I save it to the Camera Roll or if I use MPMoviePlayerController.
I've tried many things like lowering resolutions, lowering renderScale and so on but with no success.
One thing bothers me more is how actually Apple do this in iMovie - if you have AirPlay enabled and you play a project (note it's still not rendered so it must use a composition in order to display it) right after tapping play button it opens a player that plays content really smoothly on the external monitor. If you however activate AirPlay from the player it closes and start rendering the project. After that it plays it I thing by using MPMoviePlayerController.
I'm still trying to find a solution and will post back if I have any success.
So for the two questions:
I don't see why you have to get rid.
Yes it can be played but with different technique and obviously issues.

in the app .plist create a new item called:
required background modes
add a new array element called:
App plays audio or streams audio/video using AirPlay
Not sure if you have already tried this, but you don't mention it in your post.
Cheers!

Related

Airplay background streaming like Spotify / Amazon Music

Is it possible to do Airplay audio streaming like Spotify or Amazon Music. When i setup an Airplay stream with Audio from my App the screen (on the Apple-TV) turns black and shows only the progressbar.
Is it possible to show the small hint in the top corner with all the audio information which disappears after a few Seconds and don't block the whole Apple TV Ui?
Or is this kind of a Spotify / Amazon Music privilege?
We had this problem as well. I believe that there are some bugs here in Apple's court, but we found a decent workaround that seems to be pretty safe from side effects.
We found that setting the player's allowsExternalPlayback field to NO would sometimes correctly stream the audio without the blank video screen (along with correct display of the now playing information, correct response to volume rocker etc...). However, we found that very often it would fail to play anything at all.
Doing some runtime introspection, we found that the player would always correctly buffer from the network. But when it would hit the isPlaybackLikelyToKeepUp event, it would set the player's rate field to 1 indicating that it is playing, but more often than not, not actually play the audio. No errors were reported and so from all we could tell, the player itself thinks that it is indeed playing when it is not. We found this hangup to only occur when we had set an AirPlay device for audio output.
So we found that in certain event callbacks and other key places, if we added a simple one-liner:
if( self.avPlayer.rate == 1 ){ self.avPlayer.rate = 1; }
It would kick whatever internal hold ups were causing the player to not actually AirPlay and correctly stream the audio. If the player was already correctly playing, then no harm done.

MPMoviePlayerViewController locks up application with unusual appearance?

So, I've tried this a number of ways with the same result.
I've tested by using a YouTube MP4 URL, such as:
This
The way I do it looks pretty much like:
self.moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:videoUrlString]];
And then I play the video. If I play the video and it goes fullscreen, the whole app locks up. The video player appears, but parts of the status bar (such as the time and bars) disappear leaving only the carrier name. The volume slider is only half there, and it loads indefinitely, and ignores any further touch input until I kill the app. If I rotate the iPhone, the volume slider and the rest of the status bar reappear, but it still will not respond to touch or finish loading. Screenshot of issue.
If, instead, I pass the MPMoviePlayerViewController object to a UINavigationController with presentViewController:, the app seems to hang: until I rotate, then suddenly the video appears correctly and starts playing! However, again, all touch input is ignored and the application is essentially locked.
This is one of the strangest issues I've troubleshot.
So I tried using tools others have built. I tried XCDYouTubeKit and YKMediaKit using the Youtube ID instead of the direct link, with the exact same result. After looking at their code, they both use MPMoviePlayerViewControllers.
What's happening here? Can anyone help me figure out what's wrong?
That's surprising. Have you tried playing around with AV Foundation? It's a more modern media API than MediaPlayer.framework.
If you can target iOS 8 only, then AVPlayerViewController is a simple way to playback media via AVPlayer.

Switch between audio tracks in MPMoviePlayerController

In the app I'm currently working on I have some videos with multiple audio tracks (in different languages) and I'd like to have the ability to switch between these tracks programmatically. There is a button that allows the user to switch between them manually (which presents this screen by tapping on it: http://i.stack.imgur.com/mkUTZ.png) so I assumed this wouldn't be too hard. However, after two hours of research I haven't found anything useful. There's this StackOverflow question that suggests it's impossible to play video with multiple audio streams in the first place, but apparently that doesn't stand true anymore. There are also some examples with AVFoundation (I haven't really looked into the), but none with MPMoviePlayer or MPMoviePlayerController.
So I'd like to know if my goal is achievable with stock MPMoviePlayerController and if not, what are the good alternatives to it.

AVPlayer not working with AirPlay

I have a sequence of AVMutableCompositions that I am playing with AVPlayer. Everything works great when I am playing via speaker, headphones, or bluetooth. However, as soon as I connect to AirPlay, everything falls apart.
I can play one asset, and I try to switch to a new asset, I get an AVAudioSessionMediaServicesWereResetNotification and the device disconnects from AirPlay. I tried exporting the AVMutableCompositions to files and then using AVURLAssets, but this didn't seem to change anything.
Does anyone know what is going on here? It looks like I won't be able to support AirPlay...
I get the feeling that I could switch to AVAudioPlayer and this would fix the problem, but I am generating dozens of AVMutableCompositions and don't want to be reading and writing them to disk.
This is counter-intuitive, but try setting
myPlayer.allowsExternalPlayback = NO;
The documentation is not completely clear on this, but it seems that this will disallow video playback only. When I do this in my app (which uses AVPlayer), Airplay with an AVComposition works. Even the artwork shows up nicely (via an MPNowPlayingInfoCenter).

how to implement a audio player interface?

I'm using AVAudioPlayer to play mp3 files, but I need to implement ui interface as shown following:
I think it maybe a iOS system control I can use, but I can't find which control it is.
That is an MPMoviePlayerController. Compare, for example this illustration from my book:
The same section of my book tells you how to make and work with one of these. Despite the name, it's great for playing audio with a user interface. The only difference between our screen shots is that you had an AirPlay device present on the network at the time.

Resources