How to stop AVPlayer after did Fast Forward in ios app? - ios

Hi in my application i am launching AVPlayerViewController and while playing content i will fast forward the player after fast forward it will take sometime to start play before it start play again i will close the player.In this scenario i can able to hear audio even after close player.How to resolve this issue please let me know.
I am making player nil and setRate to zero when closing the player.
#try {
[self.player.currentItem removeObserver:self forKeyPath:#"status"];
[self.player.currentItem removeObserver:self forKeyPath:#"playbackBufferEmpty"];
[self.player replaceCurrentItemWithPlayerItem:nil];
[self.player setRate:0.0];
self.player=nil;
} #catch (NSException *exception)
{
NSLog(#"Execption is %#",exception);
}
Player audio should stop when ever we close player. Thanks in advance.

Related

Audio is playing in Avplayer after close AvPlayerViewController ios

Hi in my application I have avplayerViewController. I just launch the application and click on start play button - which will launch avplayerviewcontroller. There i just drag the seek bar and content is buffering before content start play i just close the playerViewcontroller. After few seconds content is start playing (audio is coming). It's very serious issue please guide me how to resolve this issue. As of now when ever i close the player i am doing below operations.
#try{
[self.player replaceCurrentItemWithPlayerItem:nil];
[self.player setRate:0.0];
[self.player seekToTime:CMTimeMake(0, 1)];
[self.player pause];
dispatch_async(dispatch_get_main_queue(), ^{
[self.contentOverlayView sendSubviewToBack:self->playerActivityIndicator];
[self->playerActivityIndicator stopAnimating];
});
// [[self.player currentItem] removeObserver:self forKeyPath:#"status"];
[[self.player currentItem] removeObserver:self forKeyPath:#"playbackBufferEmpty"];
[self.player removeTimeObserver:self->playerPeriodicTimeObserver];
}#catch(id anException){
//do nothing, obviously it wasn't attached because an exception was thrown
NSLog(#"No observer for a player in hide placeholder");
}

Stop AVPlayer and restart MP3 file again

I want to start, pause and stop (same as restart) my mp3 File and I'm using AVPlayer. I get the files from a server.
To start the song I do:
[self.player start];
To pause I do:
[self.player pause];
but when I want to stop the song and reload it, so that the song starts from the beginning when the User clicks on the "start button" next time, I have no idea what to do.
I tried something like this:
[self.player pause];
self.player = nil;
But then the player is nil of course and I can't restart the file again without a new initialization. Any ideas how to stop it?
Stop the video using [player pause]
Then use this code when you start the video.
[player seekToTime:kCMTimeZero];
[player play];
I like this better than the comment that solved the OP it b/c it eliminates a warning and uses a constant.
Best solution to do this in Swift < 4:
player.seek(to: kCMTimeZero)
player.play()
Swift >= 4:
player.seek(to: .zero)
player.play()
In Xamarin.ios
player.Seek(CoreMedia.CMTime.Zero);
player.Play();
seek#to has a completion handler.
p?.seek(to: .zero)
p?.rate = 1
is not really correct. You can get audio jitter.
p?.seek(to: .zero) { [weak self] _ in
self?.p?.rate = 1
}
is probably what you want.
If it is already playing, and you just do the seek and nothing else, again you could get the jitters.
You are probably best to
p?.rate = 0
p?.seek(to: .zero) { [weak self] _ in
self?.p?.rate = 1
}
If it's a really important app, you'll also have to consider the error condition in the seek completion.
In Swift 4: self.player.seek(to: CMTime.zero)
// If conti. play Video or audio apply this code
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd
:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[avPlayer currentItem]];
[avPlayer play];
- (void)playerItemDidReachEnd:(NSNotification *)notification
{
NSLog(#"Replay video in method");
AVPlayerItem *p = [notification object];
[p seekToTime:kCMTimeZero];
}

How can I register for when AVPlayer actually starts playing (from external source)

I'm having some trouble with registering WHEN the player is starting to play external videos (over internet) using AVPlayer. Please read the question before suggesting solutions.
I initialize the player like this:
player = [[AVPlayer alloc] initWithURL:[[NSURL alloc] initWithString:#"http://example.com/video.mp4"]];
playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
[playerLayer setFrame:[videoView bounds]];
[videoView.layer addSublayer:playerLayer];
This adds the player to the view correctly. I have added the following two lines of code to keep track of when the player is ready, and what the status/rate is;
[player addObserver:self forKeyPath:#"rate" options:0 context:nil];
[player addObserver:self forKeyPath:#"status" options:0 context:nil];
These two line will call the method - (void)observeValueForKeyPath:.... when something changes with the status or the rate of the AVPlayer.
So far it looks like this:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
//To print out if it is 'rate' or 'status' that has changed:
NSLog(#"Changed: %#", keyPath);
if ([keyPath isEqualToString:#"rate"]) //If rate has changed:
{
if ([player rate] != 0) //If it started playing
{
NSLog(#"Total time: %f", CMTimeGetSeconds([[player currentItem] duration]));
// This NSLog is supposed to print out the duration of the video.
[self setControls];
// This method (setControls) is supposed to set play/pause-buttons
// as well as labels for the current and total time of the current video.
}
}
else if ([keyPath isEqualToString:#"status"]) // If the status changed
{
if(player.status == AVPlayerStatusReadyToPlay) //If "ReadyToPlay"
{
NSLog(#"ReadyToPlay");
[player play]; //Start the video
}
}
}
The state of the AVPlayer changes to readyToPlay almost immediately after initializing it, and I then call [player play]. When this happens, the rate changes to 1.00000, meaning it's actually playing at that rate, but the video is now just starting to buffer, not playing. The screen is black, and it takes a couple of seconds, and then it starts playing. The rate, however, indicates it starts playing before it does. The rate stays at 1.00000, not going down to 0 when start-buffering, which makes it very difficult for me to know when the player has enough information to start setting the controls (I.E time stamps etc).
The NSLog() printing out the duration of the video above prints out nan (Not A Number), which leads me to think that the item isn't ready to be played, however, the rate stays at 1.0000 until it has buffered a while, then it will actually play, still with rate at 1.0000.
It does, however, get called twice. The rate "changes" to 1.0000 twice without being anything else in between. In neither calls, the duration of the video is an available variable.
My goal is to fetch the current and total timestamp of the video as fast as possible (I.E 0:00/3:52). This will also be used to register the scrubbing of a slider (for fast-forward etc.).
These values are not ready when the player notifies me it's playing at a rate of 1.0000, twice. If I manually click "play" after a second or so (and call [player play]), then it's working. How can I register to know when the video is ready, not just 'ready to get ready'?
See addBoundaryTimeObserverForTimes:queue:usingBlock: on AVPlayer and this example from Apple.
AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:#"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"]];
[player play];
// Assumes a property: #property (strong) id playerObserver;
// Cannot use kCMTimeZero so instead use a very small period of time
self.playerObserver = [player addBoundaryTimeObserverForTimes:#[[NSValue valueWithCMTime:CMTimeMake(1, 1000)]] queue:NULL usingBlock:^{
//Playback started
[player removeTimeObserver:self.playerObserver];
}];
I think the nearest you'll get to is to observe player.currentItem.playbackLikelyToKeepUp

iPhone SDK Custom Video Player with YouTube [duplicate]

This question already has answers here:
Play YouTube videos in iPhone app without using UIWebView?
(5 answers)
Closed 9 years ago.
I'm making this iPhone app that allows people to watch youtube videos and vimeo videos. I was wondering if there's a custom player I can incorporate into my app that will play the video from the youtube link or vimeo link. This has to be iOS 7 compatible as well. Thanks!
Possibly you are looking for AVFoundation.framework. Just add it to your project and you can use its AVPlayer component to allow a total customization of your interface. It would be something like this:
-(void)viewDidLoad {
//prepare player
self.videoPlayer = [AVPlayer playerWithURL:<# NSURL of your youtube video #>];
self.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndPause;
//prepare player layer
self.videoPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.videoPlayer];
self.videoPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.videoPlayerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:self.videoPlayerLayer];
//add player item status notofication handler
[self addObserver:self forKeyPath:#"videoPlayer.currentItem.status" options:NSKeyValueObservingOptionNew context:NULL];
//notification handler when player item completes playback
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.videoPlayer.currentItem];
}
//called when playback completes
-(void)playerItemDidReachEnd:(NSNotification *)notification {
[self.videoPlayer seekToTime:kCMTimeZero]; //rewind at the end of play
//other tasks
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"videoPlayer.currentItem.status"]) {
//NSLog(#"player status changed");
if (self.videoPlayer.currentItem.status == AVPlayerItemStatusReadyToPlay) {
//player is ready to play and you can enable your playback buttons here
}
}
}
And like normal VC you can add buttons or other items to invoke these methods for playback:
-(IBAction)play:(id)sender {
[self.videoPlayer play];
}
-(IBAction)pause:(id)sender {
[self.videoPlayer pause];
}
Make sure that you remove the observers previously added before you leave the VC or else those are gonna leak:
//remove observers
#try {
[self removeObserver:self forKeyPath:#"videoPlayer.currentItem.status" context:NULL];
}
#catch (NSException *exception) {}
#try {
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.videoPlayer.currentItem];
}
#catch (NSException *exception) {}
A detailed explanation from Apple is available here. Hope you would find it helpful.
1) Youtube uses flash which does not work with native mediaplayer.
2) Native media player either needs a file or it can live stream url which use HTTPLiveStreaming (it does not support RTSP).
In simple words they work on different protocol and can't talk to each other.
However, you can use third party API's to download youtube video and then play but this requires your user to wait until the entire file is downloaded.
I would recommend you to use webview. here is a good article which shows how to do so.
YoutubeHacks is an opensource tool for the same.

iOS > possible play a partially downloaded video?

Say we are downloading a large video - its 50Mb - but only 25Mb has downloaded so far - is it possible to start playing the video before its completely downloaded?
I am going to assume you are using MPMoviePlayerController for your video...
MPMoviePlayerController has a loadState property that you can monitor with this notification. Check to see if the video has been downloaded to a playable extent and then play.
//Begin observing the moviePlayer's load state.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerLoadStateChanged:) name:MPMoviePlayerLoadStateDidChangeNotification object:moviePlayer];
- (void)moviePlayerLoadStateChanged:(NSNotification *)notification{
//NSLog(#"State changed to: %d\n", moviePlayer.loadState);
if(moviePlayer.loadState == MPMovieLoadStatePlayable && [videoIndicator isAnimating]){
//if load state is ready to play
[videoIndicator stopAnimating];//Pause and hide the indicator
[self.contentView addSubview:[moviePlayer view]];
[moviePlayer setFullscreen:YES animated:YES];
[moviePlayer play];//play the video
}
}
And this is very important: If you are trying to download a video more than 10 ten minutes long, you will need to use HTTP Live Streaming.

Resources