I tried running my working 3.1.x application on 3.2 and realized that
the MPPlayerController framework had changed.
After doing some research the common method should be to add the
MPMoviePlayerViewController's view as a subview.
Somehow this does not work for me ...
I have TTTableViewController with items such as :
[TTTableSubtitleItem itemWithText:#"Text" subtitle:#"subtitle" imageURL:#"bundle://1.jpg" defaultImage:nil URL:#"tt://videos/0" accessoryURL:nil],
This is then mapped:
[map from:#"tt://videos/(playMovieAtIndex:)" toViewController: [VideoViewController class]];
and the VideoViewController finally plays the movie:
MPMoviePlayerViewController* controller =
[[MPMoviePlayerViewController alloc] initWithContentURL:theURL];
if (controller)
{
self.mp = controller;
self.mp.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
self.mp.moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
self.mp.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[controller release];
[self presentMoviePlayerViewControllerAnimated:self.mp];
[self.mp.moviePlayer play];
}
But only audio is played, and the MoviePlayer view is not actually
shown.
What am I doing wrong ?
I had the same problem. My quick work-around was to not use:
[self presentMoviePlayerViewControllerAnimated:self.mp];
But instead, add the subview to the parent controller manually:
[self.view addSubview:self.mp.view];
Related
I want to play two videos next to each other.
When building Mac apps I did this by using a AVPlayer object.
It is a view that you could place inside of your ViewController.
But when I tried to find the AVPlayer object in the object library in an IOS project it didn't show up. Only the AVKit Player View Controller did.
But the AVKit Player View Controller always plays videos full screen in a separate ViewController. I have searched the internet to find a way to display two videos next to each other but so far, I have not found anything useful.
So my question is: Is there any way that I can display two videos next to each other in an IOS application?
// ViewController.h
#import AVFoundation;
#import AVKit;
#property(nonatomic, readonly) AVPlayerItem *currentItem;
// ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
i=0;
[self videoPlay:[_passdataArr valueForKey:#"videoUrl"]];
}
-(void)videoPlay:(NSArray*)links
{
NSLog(#"1");
//create an AVPlayer
_detailView.hidden=YES;
// NSMutableArray *videolinksArr=[[NSMutableArray alloc] init];
// videolinksArr=_videoLinkArr;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#",links]];
// create a player view controller
player = [AVPlayer playerWithURL:url];
AVPlayerViewController *controller = [[AVPlayerViewController alloc] init];
[self addChildViewController:controller];
[self.view addSubview:controller.view];
controller.view.frame = self.bgimg.frame;
controller.player = player;
controller.showsPlaybackControls = YES;
player.closedCaptionDisplayEnabled = NO;
[player pause];
[player play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(AllVideoPlay:) name:AVPlayerItemDidPlayToEndTimeNotification object:_currentItem];
}
-(void)AllVideoPlay:(NSNotification*)aNotification
{
NSLog(#"2");
NSArray *temp = _videoLinkArr[i];
[self videoPlay:temp];
i++;
}
But the AVKit Player View Controller always plays videos full screen in a separate ViewController
That's false. If you want the movie view to appear as a subview, make the AVPlayerViewController a child view controller. Start with the Container View Controller in the storyboard and make an Embed segue to an AVPlayerViewController.
Or, you could use AVPlayer without an AVPlayerViewController (in code).
AVPlayer has been available on iOS since iOS 4. AVPlayer is a controller object that manages the playback of media assets with no UI elements directly tied to it, which is why it is not located in the IB object library. Rather you can build your own UI using AVPlayerLayer our use Apple's standard AVPlayerViewController, which includes default controls and standard playback behavior. The fastest way to get two videos playing side-by-side is to embed two instances of AVPlayerViewController inside another view controller. If you are using storyboards your code could be as short as:
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[AVPlayerViewController class]] && [segue.identifier isEqualToString:#"First Player"])
{
AVPlayerViewController *avPlayerViewController = (AVPlayerViewController *)segue.destinationViewController;
avPlayerViewController.player = [AVPlayer playerWithURL: [NSURL URLWithString:#"http://devstreaming.apple.com/videos/wwdc/2016/703rx8zlfedjfom6l93/703/hls_vod_mvp.m3u8"]];
[avPlayerViewController.player play];
} else if ([segue.destinationViewController isKindOfClass:[AVPlayerViewController class]] && [segue.identifier isEqualToString:#"Second Player"])
{
AVPlayerViewController *avPlayerViewController = (AVPlayerViewController *)segue.destinationViewController;
avPlayerViewController.player = [AVPlayer playerWithURL: [NSURL URLWithString:#"http://devstreaming.apple.com/videos/wwdc/2016/703rx8zlfedjfom6l93/704/hls_vod_mvp.m3u8"]];
[avPlayerViewController.player play];
}
}
#end
Or something similar. Where most of the work is done by two container views and embed segues to two AVPlayerViewControllers If you are looking to have custom video UI, you can look at Apple's PIP sample code where they show how you can use key value observing to a video player with custom UI.
When I click on a picture, I show a pop-up with a video in it. In that pop up, a video is launching automatically. The problem is that I don't have interactivity with the video (play, pause, etc...). So for now, I found the way to loop it with the AVPlayerItemDidPlayToEndTimeNotification but I would like the user has the capability to play/pause.
Here is my code :
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:player];
NSURL *url = [NSURL fileURLWithPath:mediaPath];
player = [[AVPlayer alloc] initWithURL: url];
controller = [[AVPlayerViewController alloc] init];
controller.player = player;
controller.delegate = self;
controller.showsPlaybackControls = YES;
UIImageView *popView = [[[[[[NSBundle mainBundle] loadNibNamed:mediaType owner:self options:nil] objectAtIndex:0] viewLoadedFromXib] subviews] objectAtIndex:0];
[controller.view setFrame:CGRectMake(0, 0, 850, 600)];
[popView addSubview:controller.view];
[player play];
I precise that when I click on the video, the bar with the pause video appears below, but when I click on the button, nothing happens.
1ST EDIT: It seems that there is a AVTouchIgnoringView that has been added automatically by the AVPlayerViewController. It seems that there is a link with UserInteraction... But I try to put it to YES without success. May be I don't do it for the good view. Any ideas ?
2ND EDIT : this is the setFrame that adds the AVTouchIgnoringView. So do you know how can I change the size of the frame without it adding automatically that AVTouchIgnoringView ?
First, I think that the UIImageView is not correct as you put a video in it, so I advise you to change in UIView.
UIView *popView = [[[[[[NSBundle mainBundle] loadNibNamed:mediaType owner:self options:nil] objectAtIndex:0] viewLoadedFromXib] subviews]
Second, I think that you may have user interactivity with the video. Try a bigger size to display the bottom bar with controls.
//video resize
controller.view.frame = CGRectMake(0, 0, 900, 600);//for example
In my case touch on the AVPlayerViewController view was ignored because of the gesture recognizer on one of its superviews. Mentioned recognizer was returning NO from the method: canBePreventedByGestureRecognizer:.
Adding an exception for the recognizer owned by AVPlayerViewController fixed the issue and the UI is usable again.
Essentially I'm working with 3 view controllers.
Main view which starts a download. (Webview based which passes the download).
Modal download controller. (Tab based).
Downloader (HCDownload).
In the main view my download gets passed like so:
//Fire download
[activeDL downloadURL:fileURL userInfo:nil];
[self presentViewController:vc animated:YES completion:nil];
activeDL is initialized in viewDidLoad:
activeDL = [[HCDownloadViewController alloc] init];
If I removed the presentViewController, it still downloads, which is fine. Then i tap my Downloads button, it brings up the controller which defines the tabs like so:
center = [[CenterViewController alloc] init];
activeDL = [[HCDownloadViewController alloc] init];
completedDL = [[DownloadsViewController alloc] init];
activeDL.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Active Downloads"
image:nil //[UIImage imageNamed:#"view1"]
tag:1];
completedDL.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Completed Downloads"
image:nil //[UIImage imageNamed:#"view3"]
tag:2];
[self setViewControllers:[NSArray arrayWithObjects:activeDL, completedDL, nil]];
However, it is not passing the current active download. I don't know if it's a initialization problem, or my tab issue of showing the current download.
From his github, he suggests to get the current number of downloads is to call: dlvc.numberOfDownloads which for me would be
[activeDL numberOfDownloads].
I call this in the the Downloader viewWillAppear but nothing shows.
Does anybody has any suggestions or have worked with this controller?
Any help would be appreciated.
When you call:
activeDL = [[HCDownloadViewController alloc] init];
You are creating a new download controller, which has its own internal downloads array. This library, as written, has no way to pass this information from one HCDownloadViewController object to another.
Tying downloads to VC's like this will cause problems -- I recommend you rewrite this code to split that apart.
To hack around it, try to create just one HCDownloadViewController object and pass it around.
Ok so with the last comment of the other answer, "Make activeDL a member variable instead of a local variable.", got me Googling and with some tinkering and bug fixing along the way I managed to get it all up and running perfect.
I declared it all in my AppDelegate.
AppDelegate.h
#interface SharedDownloader : HCDownloadViewController <HCDownloadViewControllerDelegate>
+ (id)downloadingView;
#end
AppDelegate.m
static HCDownloadViewController *active;
#implementation SharedDownloader
+ (id)downloadingView {
if (active == nil)
active = [[HCDownloadViewController alloc] init];
return active;
}
#end
Calling to the class for downloading in my main view controller:
-(id)init{
activeDL = [SharedDownloader downloadingView];
return self;
}
//Spot where I fire the download
if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
//More code here
[activeDL downloadURL:fileURL userInfo:nil];
}
Lastly in my tab bar controller:
-(id)init {
activeDL = [SharedDownloader downloadingView];
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
activeDL.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Active Downloads" image:nil] tag:2];
}
I believe that's all of it. In any case, thanks to Lou Franco for pointing me in the right direction.
I have a UIViewController subclass called videoPlayerViewController.
In storyboard I dragged out a UIViewController. I set the class correctly in Storyboard.
I put a button on the screen. When I click the button, it executes the method playVideo:.
- (IBAction)playVideo:(id)sender
{
NSURL *movieURL = [NSURL URLWithString:#"http://www.ebookfrenzy.com/ios_book/movie/movie.mov"];
MPMoviePlayerController *player =
[[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[player prepareToPlay];
[player.view setFrame: self.view.bounds]; // player's frame must match parent's
[self.view addSubview: player.view];
[player play];
}
I get a black screen that does nothing.
This is the simplest version of the code I've had in this method over the last 6 hours.
I've tried every StackOverflow answer out there.
I just want to play a video that I stream from the internet.
If I set:
player.movieSourceType = MPMovieSourceTypeStreaming;
the screen reads "loading" for a second, and then crashes.
What exactly am I doing wrong?
I understand there are so many MPMoviePlayerController questions out there, and to just ask a general "How does it work" question seems ludicrous. I've been at this almost 6 hours now and no Google/Stack Overflow/Apple Documentation search has made this work.
I used your provided code but created a MoviePlayerController property named mcp in the header file that I assigned to player to after creating it. That worked for me. The movie loaded and played just fine.
In the .h file:
#property (strong, nonatomic) MPMoviePlayerController *mcp;
In the .m file:
- (IBAction)playVideo:(id)sender
{
NSURL *movieURL = [NSURL URLWithString:#"http://www.ebookfrenzy.com/ios_book/movie/movie.mov"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[player prepareToPlay];
[player.view setFrame: self.view.bounds]; // player's frame must match parent's
_mcp = player;
[self.view addSubview: _mcp.view];
[_mcp play];
}
Using the code at the bottom of this post I can successfully display a movie. However I need to now use moviePlayer as a property rather than a local variable. So by adding the following in the header file:
#property (retain, nonatomic) MPMoviePlayerController *mPlayer;
...and synthesizing it as:
#synthesize mPlayer = _mPlayer
Here's the original code. This works fine. All I change is the initialisation line where instead of using a local variable I use the property. A
MPMoviePlayerController * mPlayer = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL] autorelease];
mPlayer.shouldAutoplay=YES;
[self.welcomeImage setUserInteractionEnabled:YES];
[mPlayer.view setFrame: self.welcomeImage.bounds]; // player's frame must match parent's
[self.welcomeImage addSubview:mPlayer.view];
mPlayer.scalingMode = MPMovieScalingModeAspectFit;
mPlayer.controlStyle = MPMovieControlStyleEmbedded;
[mPlayer prepareToPlay];
[mPlayer play];
I just get a black box, no controls or video. What am I doing wrong?
Your not using your synthesized property. Change mPlayer to _mPlayer.
_mPlayer = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL] autorelease];
_mPlayer.shouldAutoplay=YES;
[self.welcomeImage setUserInteractionEnabled:YES];
[_mPlayer.view setFrame: self.welcomeImage.bounds]; // player's frame must match parent's
[self.welcomeImage addSubview:_mPlayer.view];
_mPlayer.scalingMode = MPMovieScalingModeAspectFit;
_mPlayer.controlStyle = MPMovieControlStyleEmbedded;
[_mPlayer prepareToPlay];
[mPlayer play];
This should work as long your videoURL is valid.