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.
Related
I am trying to use the native player (AVPlayer) to reproduce a live stream on iOS. However, I have trouble resuming the playback. When I stop the playback and resume it after few seconds, the playback starts from the moment I paused instead of reproducing the current (last) sample of the live stream.
Is there a way to get the last sample, o configure AVPlayer to reproduce from last sample when tapping on Play Button?
My solution is based on denying user to keep the player paused. This is, destroying the player each time playback is resumed. And creating a new instance each time, playback is intended to be resumed.
According to Apple recommendation, the only solution to know if the AVPlayer was stopped is to add KVO. This is:
- (void)setupPlayer {
AVPlayer *player = [AVPlayer playerWithURL:streamURL];
AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
playerViewController.player = player;
self.playerViewController = playerViewController;
[self configureConstraintsForView:self.playerViewController.view]; //Add Player to View
[self setupObservers];
[player play];
}
- (void)setupObservers {
[self.playerViewController.player addObserver:self
forKeyPath:#"rate"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
if ([keyPath isEqualToString:#"rate"] && self.playerViewController.player.rate == CGPointZero.x) {
[self.playerViewController.view removeFromSuperview];
[self.playerViewController.player removeObserver:self forKeyPath:#"rate"];
[self.playerViewController.player pause];
self.playerViewController = nil;
}
}
Then, when user wants to re-engage the player, just call -(void)setupPlayer which start the playback from the last live sample.
I have a collection view with an AVPlayer inside the cell and the AVPlayer starts playing the AVPlayerItem in a loop when
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
gets called. this works well but the problem is that after the AVPlayer is playing the item a few times the video is no longer shown but i can hear its sound.
I also add an observer for the value #"playbackBufferFull" for each item that is played like that:
[item addObserver:self forKeyPath:#"playbackBufferFull" options:NSKeyValueObservingOptionNew context:nil];
i noticed that when the video stops the observer method of the value #"playbackBufferFull" gets called, first of all i would like to know what causes the buffer the get full, the second and most important is how can i resume the AVPlayer when the video stops;
i tried calling [cell.videoPlayer play]; and to replace the item with a new one and it didnt work, the observer method:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
if ([object isKindOfClass:[AVPlayerItem class]] && [keyPath isEqualToString:#"playbackBufferFull"])
{
//this method is get called when the video stop showing but i can still hear it
//how can i resume the video?
}
}
my solution is :
first add observe for AVPlayerItemPlaybackStalledNotification in viewDidLoad or ...
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemPlaybackStalledNotification
object:self.avPlayer.currentItem];
-(void)playerItemDidReachEnd:(NSNotification*)noti
{
//thisisn't good way but i can't find the best way for detect best place for resume again.
NSLog(#"\n\n give Error while Streaminggggg");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.avPlayer play];
});
}
BUT
maybe you can find the best way to call play method again for resume!
please check do you get AVPlayerStatusReadyToPlay keypatch ?
if you get , you can call play method there.
please notify me about the result
In iOS9, the MPMoviePlayer classes have all been deprecated in favor of AVPlayer. I have an existing app using MPMoviePlayerPlaybackDidFinishReasonUserInfoKey to determine how to log events on how the video player ended. How do I do the same with AVPlayer?
The following are the ending reason keys:
MPMovieFinishReasonPlaybackEnded
MPMovieFinishReasonPlaybackError
MPMovieFinishReasonUserExited
There is no equivalent to MPMoviePlayerPlaybackDidFinishReasonUserInfoKey and MPMoviePlayerPlaybackDidFinishNotification in AVKit. To accomplish the same functionality in AVKit, you must listen to three notifications separately, rather than one notification with different possible reasons.
MPMovieFinishReasonPlaybackEnded >>> AVPlayerItemDidPlayToEndTimeNotification
MPMovieFinishReasonPlaybackError >>> AVPlayerItemFailedToPlayToEndTimeNotification
MPMovieFinishReasonUserExited. No conversion. There are multiple ways to detect that the user has killed the player. One is detecting a modal has closed.
If you want to know if the video is playing or not, you can do a KVO:
[self.player addObserver:self forKeyPath:#"rate" options:0 context:nil];
Then add this method:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:#"rate"]) {
if ([self.player rate]) {
[self changeToPause]; // This changes the button to Pause
}
else {
[self changeToPlay]; // This changes the button to Play
}
}
}
Try, in viewDidLoad:
AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:#"yoururl"]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
AVPlayer* player = [[[AVPlayer alloc] initWithPlayerItem:playerItem] autorelease];
[player play]
And
-(void)itemDidFinishPlaying:(NSNotification *) notification {
// Will be called when AVPlayer finishes playing playerItem
}
I want to play a video in seprate view controller, where I can Play/Pause or dismiss that view controller. In my case, I recorded the video in my app and calling this delegate method in order to save this video in assets, but I want to play it first before using the ALAssetsLibrary.
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error
And the TEMO URL im getting is :
file:///private/var/mobile/Containers/Data/Application/EA6D31AC-6CC3-4BDF-B874-BC6F30BA5677/tmp/output.mov
How can I play this video in next view controller or in same view controller??
My try:
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:outputFileURL];
player.view.frame = CGRectMake(184, 200, 400, 300);
[self.view addSubview:player.view];
[player play];
PS: This is showing a black screen area but not actually playing this video.
I had the same problem a few days ago. It ends up that I was calling play method to soon, before the video become ready to play. So, add this before call [player play]. This will notify whenever your video become read to play in MPMoviePlayerController.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(videoPlayBackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:player];
Then setup the observer:
- (void)videoPlayBackDidFinish:(NSNotification *)notification {
[[NSNotificationCenter defaultCenter]removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
}
This worked for me.
Hope it helps.
I am trying to display UIToolBar with BarButtonItems on MPMoviePlayerController. Not sure how will I implement it.
I am trying to play the video file when user taps on one of the cell of UITableView. At that time I would like to give an option to user to share the video on FB or tweeter.
Not sure how will I display the share BarButtonItem on MPMoviePlayerController. I am trying to implement something similar to the photo app that comes with iPhone.
Can anyone please help me out?
Thank you!
MPMovieplayer is not the right choice for this purpose. You can create a custom movie player with AVPlayer(found under AVFoundation.framework) that would serve your purpose. Create any normal ViewController in your project and add an AVPlayer with code something like below:
-(void)viewDidLoad {
//prepare player
self.videoPlayer = [AVPlayer playerWithURL:<# NSURL for the video file #>];
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
}
}
}
As this would be normal view controller, you can add a toolbar buttons/buttons to it, for playing/sharing, etc. and trigger the player actions and any other related action like below:
-(IBAction)play:(id)sender {
[self.videoPlayer play];
}
-(IBAction)pause:(id)sender {
[self.videoPlayer pause];
}
//etc.
Also make sure to remove the observers in your dealloc:
-(void)dealloc {
//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) {}
//other deallocations
[super dealloc];
}
More detailed and sophisticated explanation of the process can be found under apples companion guide, available here