How to programmatically control Play button in MPNowPlayingInfoCenter - ios

In Radio app where for pausing the AVPlayer we are not really pausing it just muting it for some time as per the app requirement.
Here the issue is everything is working fine but MPNowPlayingInfoCenter is not updating to pause when I mute the player. Is there is any way I can control MPNowPlayingInfoCenter controlls programmatically?
Tried the all possible solutions like making setActive(false) but this is causing issue in normal player.
Here is the solution for it
When Pausing I'm muting it for 120 secs and if it still in that mode I'm pausing the player here is the code i'm using for it.
self.player.rate = 0.0 // Automatically handles the MPNowPlayingInfoCenter Controls to Pause state
self.player.isMuted = true
secs = 120

To set MPNowPlayingInfoCenter to paused, you can set playbackRate to 0.0:
let nowPlayingInfo : [String: AnyObject] =
[MPNowPlayingInfoPropertyPlaybackRate: 0.0]
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo

Related

AVPlayerLayer flashes black on AVPlayer.replaceCurrentItem(with:)

I have an AVPlayer object that I am using to play a video. When the user taps a button, the video is swapped out for a different video, which continues playing. Just using replaceCurrentItem(with:) is resulting in a few tenths of a second of a black frame appearing on my AVPlayerLayer that is displaying the video content.
I have code in place to render an image at the current frame before the AVPlayerItem is swapped out, to bridge the gap before the new AVPlayerItem has a frame ready to display, but the black frame is blocking this image from view. Is there any way to control what the AVPlayerLayer will render before it has actual video data to display?
Alternatively, is there a way to be notified that the AVPlayerLayer (or the AVPlayerItem has actually begun displaying video data? Observing for when the state of the item becomes .readyToPlay triggers too early, hiding the image at that point still leaves the black frame visible.
I had the same flash problem with my macOS app. I resolved it by renewing AVPlayerLayer each time I play a new file.
I have an AVPlayer subclass. The function below removes AVPlayerLayer from its super layer and add a new layer to the view.
class MyVideoPlayer: AVPlayer {
func addLayer(view: NSView) {
view.layer!.sublayers?
.filter { $0 is AVPlayerLayer }
.forEach { $0.removeFromSuperlayer() }
let layer = AVPlayerLayer.init(player: self)
layer.videoGravity = AVLayerVideoGravity.resize
layer.frame = view.bounds
view.layer!.addSublayer(layer)
}
}
In my ViewController, I call this before I play a video content.
myVideoPlayer.addLayer(view: self.view)

iOS how to slow down specific duration of video's playback speed

I want to make part of video slow down while rest of it are normal speed, just like the slow mode video taken by iOS camera. How to do that? I've search AVFoundation but found nothing.
Thanks!
If you are only talking about creating this effect during playback (and not exporting it), you should be able to do so by just changing the rate property of AVPlayer at specific times. Use addBoundaryTimeObserverForTimes:queue:usingBlock: to get notified when it's time to change the rate.
CMTime interval = CMTimeMake(10, 1);
NSArray *times = #[[NSValue valueWithCMTime:interval]];
_boundaryTimeObserver = [_avPlayer addBoundaryTimeObserverForTimes:times
queue:nil
usingBlock:^{
[_weakPlayer setRate:0.5];
}];
The rate property works as follows:
rate = 0.0; // Stopped
rate = 0.5; // Half speed
rate = 1.0; // Normal speed
For slow motion playback, the AVPlayer property canPlaySlowForward must be set to true.
Remember to remove the time observer when you're finished with it, and make sure to use an unretained reference to self or to the player within the block in order to avoid retain cycles.

iOS - How to make a UISlider into a "Scrubber / Seekbar" for video playback?

I have an instance of AVAudioPlayer that plays a local audio file from disk. The playback progress is reflected with a UIProgressView. I'm trying to replace that with a UISlider. To accomplish the task, the slider will:
move in response to timer event to indicate the current playback position
respond to manual touch to allow for video scrubbing
I'm not sure how to make the UISlider smart enough to know that when human touch began, it should stop responding to timer events, and when the touch is released, it should resume the audio player at a new position and start updating with timer events again.
Which "Send event" outlets in storyboard would I use to create the behavior
above?
Currently I have a generic "value changed" callback.
- (IBAction)sliderChanged:(id)sender {
if(self.backgroundMusicPlayer == nil)
{
NSError* error = nil;
NSData* data = [self.audioFile data];
self.backgroundMusicPlayer = [[AVAudioPlayer alloc]initWithData:data error:&error];
[self.backgroundMusicPlayer prepareToPlay];
}
self.backgroundMusicPlayer.currentTime = self.slider.value;
[self.backgroundMusicPlayer play];
}
What you have is right. To make your code respond to the user adjusting the slider, use the Value Changed event. If you want to be notified that the slider has been touched, use the Touch Down event, or add a gesture recognizer to the slider.
I would keep things simple and just check the isTracking property of UISlider which it inherits from UIControl.

MPMoviePlayerController slowmotion

Can't change currentPlaybackRate... Any value < 0 make playing little slower than normal speed. I want to change playing speed from 1 to 1/2...1/4 and 1/8. But any changes not working. The Player continues playing with own speed(little slower or normal. Even if I set 0.00001 for currentPlaybackRate the playing speed not change). So, How to make slow motion effect on MPMoviePlayerController.
// Little slower than normal, but same for any value
moviePlayerController.currentPlaybackRate = 0.5;
moviePlayerController.currentPlaybackRate = 0.25;
moviePlayerController.currentPlaybackRate = 0.75;
moviePlayerController.currentPlaybackRate = 0.125;
// Normal
moviePlayerController.currentPlaybackRate = 1;
MPMoviePlayerController is deprecated in iOS 9. You should use AVPlayerViewController instead and use avplayer.Rate property to set the playback rate of the current video.

Putting a video to pause state before playing

I am using MVMoviePlayer to play videos in the app. Right now, a black screen comes after taping the play button and the video starts playing. But, the black screen is casing some discofort from the user end point of view. So, i want to start the video from a paused state.
In order to do this, i thought of putting the player to paused state before playing it..
Is there a way to do this???
You can hide your MPMoviePlayer until that annoying black flicker is gone.
To ensure that the black flicker is gone, you can check if the MPMoviePlayer's loadState is 3 ( which means MPMovieLoadStatePlayable | MPMovieLoadStatePlaythroughOK ) and playbackState is 1 (which means MPMoviePlaybackStatePlaying)
First hide your MPMoviePlayer:
yourMPMoviePlayer.view.hidden = YES;
Just add an observer to be notified when loadState changes:
[NSNotificationCenter.defaultCenter addObserver:self
selector:#selector(loadStateChanged:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
And make your MPMoviePlayer visible again when you are notified and conditions are met:
- (void)loadStateChanged:(NSNotification *)sentNotification
{
if (player.loadState == (MPMovieLoadStatePlaythroughOK | MPMovieLoadStatePlayable) && player.playbackState == MPMoviePlaybackStatePlaying)
yourMPMoviePlayer.view.hidden = NO;
}

Resources