I’m embedding YouTube videos in a UIWebView for an iOS app. I’m using “Method 2” at this YouTube blog post to embed the video. This works great, except that because iOS manages the media player, I can’t determine whether the video is playing or is done. I don’t want to swap that view out with another one while the video is playing, but I don’t see a good way to determine that. Any ideas? If there’s a way to get a JavaScript callback, that will work, or if there’s a way to embed YouTube videos using the HTML5 <video> tag, that will work as well (I’ve tried that and not gotten success).
Just add observer for MPAVControllerPlaybackStateChangedNotification.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playbackStateDidChange:)
name:#"MPAVControllerPlaybackStateChangedNotification"
object:nil];
then start listening:
- (void)playbackStateDidChange:(NSNotification *)note
{
NSLog(#"note.name=%# state=%d", note.name, [[note.userInfo objectForKey:#"MPAVControllerNewStateParameter"] intValue]);
int playbackState = [[note.userInfo objectForKey:#"MPAVControllerNewStateParameter"] intValue];
switch (playbackState) {
case 1: //end
;
break;
case 2: //start
;
break;
default:
break;
}
}
Explore other states if you're curious. Additionally everyone interested in bunch of other notifications can register to see all:
CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
NULL,
noteCallbackFunction,
NULL,
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
then check what's coming on:
void noteCallbackFunction (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
NSLog(#"notification name: %#", name);
NSLog(#"notification info: %#", userInfo);
}
Have fun!
you can inject javascript into a UIWebView (see http://iphoneincubator.com/blog/windows-views/how-to-inject-javascript-functions-into-a-uiwebview)... other interesting stuff about javascript and UIWebView can be found here and here.
try using this together with this experimental youtube API (see http://code.google.com/apis/youtube/iframe_api_reference.html)... this should be able to get you what you want.
Another useful resource for this to make a callback from javascript to your code is here.
For iPhone I used some tricky method. You could get a notification when video modal view controller was dismissed.
-(void) onUIWebViewButtonTouch:(id) sender
{
self.isWatchForNotifications = YES;
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(windowNowVisible:)
name:UIWindowDidBecomeVisibleNotification
object:self.view.window
];
}
- (void)windowNowVisible:(NSNotification *)note
{
if (isWatchForNotifications == YES)
{
//modal viewcontroller was dismissed
}
self.isWatchForNotifications = NO;
}
Related
I have this website which plays videos, then my ios app shows this website on an UIWebview. My question is that when ios plays video from this website, which player does ios use? I want to know the answer to this question because I want to get pause notification from the player, so I want to know which kind of notification to use. Thanks
Definitely when iOS plays a video from a website page using native controller, it most probably seems to be a Native iOS player that we can show using MPMoviePlayViewController .
The reason seems to be the VOD or streaming video service must be following Apple's guideline for HLS.
Here is code to listen to StateChange notification
MPMoviePlaybackState
Constants describing the current playback state of the movie player.
enum {
MPMoviePlaybackStateStopped,
MPMoviePlaybackStatePlaying,
MPMoviePlaybackStatePaused,
MPMoviePlaybackStateInterrupted,
MPMoviePlaybackStateSeekingForward,
MPMoviePlaybackStateSeekingBackward
};
typedef NSInteger MPMoviePlaybackState;
Register for the MPMoviePlayerPlaybackStateDidChangeNotification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(MPMoviePlayerPlaybackStateDidChange:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:nil];
//Check in this function MPMoviePlaybackState
(void)MPMoviePlayerPlaybackStateDidChange:(NSNotification *)notification
{
if (player.playbackState == MPMoviePlaybackStatePlaying)
{ //playing
}
if (player.playbackState == MPMoviePlaybackStateStopped)
{ //stopped
}if (player.playbackState == MPMoviePlaybackStatePaused)
{ //paused
}if (player.playbackState == MPMoviePlaybackStateInterrupted)
{ //interrupted
}if (player.playbackState == MPMoviePlaybackStateSeekingForward)
{ //seeking forward
}if (player.playbackState == MPMoviePlaybackStateSeekingBackward)
{ //seeking backward
}
}
Remove notification by
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
Refer :MPMoviePlaybackState
I am not sure what code to add, so let me know what you need to see. I am using MPMoviePlayer in conjunction with Widevine. I am having an issue where the movie stops playing. I check the MoviePlaybackStates and rarely, if ever does it catch. Most of the time it just stops. I want to believe it has something to do with buffering. I am streaming the video, and widevine callbacks gives me no errors. Any ideas how I can track this down or what the issue is?
You should follow loadState instead of playbackState.
The way to do it is to observe MPMoviePlayerLoadStateDidChangeNotification notification, to see how's that buffering going.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(loadStateChanged:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
somewhere before initializing your player.
and
-(void)loadStateChanged:(NSNotification *)notif
{
NSString *loadState=#"";
switch (self.player.loadState) {
case MPMovieLoadStateUnknown: {
loadState=#"MPMovieLoadStateUnknown";
break;
}
case MPMovieLoadStatePlayable: {
loadState=#"MPMovieLoadStatePlayable";
break;
}
case MPMovieLoadStatePlaythroughOK: {
loadState=#"MPMovieLoadStatePlaythroughOK";
break;
}
case MPMovieLoadStateStalled: {
loadState=#"MPMovieLoadStateStalled";
break;
}
}
NSLog(#"%#", loadState);
}
I am facing an issue with MPMoviePlayerController in iOS 7. When i single tap on the forward seek button the video stops and not allow to do anything like to play again full screen and slider change.
Here is my code.
remove the Observer for the MPMoviePlayerPlaybackDidFinishNotification
[[NSNotificationCenter defaultCenter] removeObserver:moviePlayerViewController name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayerViewController.moviePlayer];
and add New Notification MPMoviePlayerPlaybackDidFinishNotification
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(videoFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
Here is my custom method to handle the MPMoviePlayerPlaybackDidFinishNotification
-(void)videoFinished:(NSNotification*)aNotification{
MPMoviePlayerController *moviePlayer = [aNotification object];
NSLog(#"%f",moviePlayer.currentPlaybackTime);
int reason = [[[aNotification userInfo] valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
if (reason == MPMovieFinishReasonPlaybackEnded) {
}else if (reason == MPMovieFinishReasonUserExited) {
[self performSelector:#selector(dismiss:) withObject:aNotification afterDelay:0.5];
}else if (reason == MPMovieFinishReasonPlaybackError) {
}
}
I need to stop this strange behaviour on single click and continue to play.
Anyone know how to do this?
Thanks.
I think there are no any notifications or event are available on user
interaction with the standard player buttons, and i have to implement
own UI for the player controls. by this way we can then determine the
actions for a single touch, long touch, etc. Then, we can add whatever
functionality like increasing the play rate, or simply seeking to a
time.
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.
I’m embedding YouTube videos in a UIWebView for an iOS app. I’m using “Method 2” at this YouTube blog post to embed the video. This works great, except that because iOS manages the media player, I can’t determine whether the video is playing or is done. I don’t want to swap that view out with another one while the video is playing, but I don’t see a good way to determine that. Any ideas? If there’s a way to get a JavaScript callback, that will work, or if there’s a way to embed YouTube videos using the HTML5 <video> tag, that will work as well (I’ve tried that and not gotten success).
Just add observer for MPAVControllerPlaybackStateChangedNotification.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playbackStateDidChange:)
name:#"MPAVControllerPlaybackStateChangedNotification"
object:nil];
then start listening:
- (void)playbackStateDidChange:(NSNotification *)note
{
NSLog(#"note.name=%# state=%d", note.name, [[note.userInfo objectForKey:#"MPAVControllerNewStateParameter"] intValue]);
int playbackState = [[note.userInfo objectForKey:#"MPAVControllerNewStateParameter"] intValue];
switch (playbackState) {
case 1: //end
;
break;
case 2: //start
;
break;
default:
break;
}
}
Explore other states if you're curious. Additionally everyone interested in bunch of other notifications can register to see all:
CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),
NULL,
noteCallbackFunction,
NULL,
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
then check what's coming on:
void noteCallbackFunction (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
NSLog(#"notification name: %#", name);
NSLog(#"notification info: %#", userInfo);
}
Have fun!
you can inject javascript into a UIWebView (see http://iphoneincubator.com/blog/windows-views/how-to-inject-javascript-functions-into-a-uiwebview)... other interesting stuff about javascript and UIWebView can be found here and here.
try using this together with this experimental youtube API (see http://code.google.com/apis/youtube/iframe_api_reference.html)... this should be able to get you what you want.
Another useful resource for this to make a callback from javascript to your code is here.
For iPhone I used some tricky method. You could get a notification when video modal view controller was dismissed.
-(void) onUIWebViewButtonTouch:(id) sender
{
self.isWatchForNotifications = YES;
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(windowNowVisible:)
name:UIWindowDidBecomeVisibleNotification
object:self.view.window
];
}
- (void)windowNowVisible:(NSNotification *)note
{
if (isWatchForNotifications == YES)
{
//modal viewcontroller was dismissed
}
self.isWatchForNotifications = NO;
}