I need to write an application where there are different short video loops in the background of a View. These loops should typically have a length of 10-30 seconds. I was wondering what would be better in terms of performance and memory economics (the loops should be bundled with the app when downloaded from the appstore)
a) Use a UIWebview as Background where an animated .gif of the video is looped
b) Use some VideoPlayerView (AVPlayer) as Background with an m4v-like file
c) Some alternative that I haven't considered yet
There will also be audio, however audio is not linked to the video
- (void)playIntroVideo
{
// NSBundle *bundle = [NSBundle mainBundle];
// // NSString *moviePath = iPadDevice ? [bundle pathForResource:#"IntroVideo" ofType:#"mp4"] : [bundle pathForResource:#"IntroVideo_iPhone" ofType:#"mp4"];
// NSString *moviePath = [bundle pathForResource:#"IntroVideo" ofType:#"mp4"];
// NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
CGRect frame = self.movieView.frame;
frame.origin.x=-200;
frame.size.width+=200;
AVAsset *avAsset = [AVAsset assetWithURL:movieURL];
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:avAsset];
gen.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMakeWithSeconds(0.0, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
UIImage *selectedImage = [[UIImage alloc] initWithCGImage:image];
CGImageRelease(image);
UIImageView *img = [[UIImageView alloc] initWithImage:selectedImage];
img.frame = frame;
[self.movieView addSubview:img];
AVPlayerItem *avPlayerItem =[[AVPlayerItem alloc]initWithAsset:avAsset];
self.avplayer = [[AVPlayer alloc]initWithPlayerItem:avPlayerItem];
avPlayerLayer =[AVPlayerLayer playerLayerWithPlayer:self.avplayer];
[avPlayerLayer setVideoGravity:AVLayerVideoGravityResize];
if (iPhoneDevice)
[avPlayerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[avPlayerLayer setFrame:frame];
[self.movieView.layer addSublayer:avPlayerLayer];
[self.avplayer seekToTime:kCMTimeZero];
// Not affecting background music playing
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&sessionError];
[[AVAudioSession sharedInstance] setActive:YES error:&sessionError];
// [self.avplayer setVolume:0.0f];
[self.avplayer setActionAtItemEnd:AVPlayerActionAtItemEndNone];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self playIntroVideo];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.avplayer play];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.avplayer pause];
// self.avplayer = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:[self.avplayer currentItem]];
}
- (void)playerItemDidReachEnd:(NSNotification *)notification
{
AVPlayerItem *p = [notification object];
[p seekToTime:kCMTimeZero];
}
Related
I have a UIView which contains an AVQueuePlayer to show a videos. UIViewAnimationOptionTransitionCrossDissolve not working in this avqueue player
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url1 = [NSURL URLWithString:#"http:fff.mov"];
first = [AVPlayerItem playerItemWithURL: url1];
NSURL *url2 = [NSURL URLWithString:#"http:hgh.mov"];
second = [AVPlayerItem playerItemWithURL: url2];
NSURL *url3 = [NSURL URLWithString:#"http:jhk.mov"];
third = [AVPlayerItem playerItemWithURL: url3];
NSURL *url4 = [NSURL URLWithString:#"http:dsdfd.mov"];
fourth = [AVPlayerItem playerItemWithURL: url4];
player = [AVQueuePlayer queuePlayerWithItems:[NSArrayarrayWithObjects:first,second,third,fourth,nil]];
lists = [NSMutableArray arrayWithObjects:first,second,third,fourth, nil];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:playerLayer];
_displayview = [[UIView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_displayview];
[player play];
for (int m;m<lists.count;m++)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:lists[m]];
}
}
-(void)itemDidFinishPlaying:(NSNotification *) notification
{
End=YES;
//
NSLog(#"view will Appear");
[UIView transitionWithView:_displayview
duration:3.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^(void)
{
NSLog(#"IT REACHED THE END");
}
completion:nil];
}
If anyone can help, I'd really appreciate any advice.
Thanks guys.
I am trying to replace AVPlayer with MPMoviePlayerController as I want to be able to add an animation with transparent background to a view. The problem is the animation is not displaying with MPMoviePlayerController.
Please find my lines below. The first portion is with AVPlayer and it's work. The second is with MPMoviePlayerController and doesn't.
What the code does is it plays an animation and when this is done it is launching an action.
Code with AVPlayer (that works):
NSString *filepath = [[NSBundle mainBundle] pathForResource:theAnimationFileName ofType:theString;
//NSURL *fileURL = [NSURL fileURLWithPath:filepath];
// First create an AVPlayerItem
AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:fileURL];
// Subscribe to the AVPlayerItem's DidPlayToEndTime notification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(itemDidFinishPlaying) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
// Pass the AVPlayerItem to a new player
controlledPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem];
AVPlayerLayer *animatedLayer = [AVPlayerLayer playerLayerWithPlayer:controlledPlayer];
[animatedLayer setFrame:CGRectMake(0, 0, 1024, 1024)];
[thisReplacementView.layer addSublayer: animatedLayer];
// Begin playback
[controlledPlayer play];
Code with MPMoviePlayerController (does not display anything):
NSString *moviePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:theString];
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:moviePath]];
moviePlayer.controlStyle = MPMovieControlModeDefault;
moviePlayer.view.frame = CGRectMake(0, 0, 1024, 1024);
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(itemDidFinishPlaying) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];
[thisReplacementView addSubview:moviePlayer.view];
[moviePlayer play];
NSURL *url = [NSURL URLWithString:#"http://iOS.mp4"];
self.moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
NSError *_error = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &_error];
[self presentMoviePlayerViewControllerAnimated:self.moviePlayer];
-(void)playbackFinishedCallback:(NSNotification *)notification{
self.moviePlayer = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
}
- (void)moviePlaybackComplete:(NSNotification *)notification
{
self.moviePlayer = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
[self.moviePlayer.view removeFromSuperview];
}
would you please help me with this code, I'm trying to play video but I'm having error Exc_bad_Access code = 1 and some times code = 2:
-(IBAction)BtnPressed:(id)sender{
self.videoview.hidden = false;
NSString *btnTag = [NSString stringWithFormat:#"%d",[sender tag]];
NSString *videofilename = [NSString stringWithFormat:#"%#%#_%#", selectedGender, btnTag, selectedVowel];
//Playing video
NSString *filepath = [[NSBundle mainBundle] pathForResource:videofilename ofType:#"mp4"];
NSLog(#"file name is %#",filepath);
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
//NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:btnTag ofType:#"mp4"]];
MPMoviePlayerViewController *playercontroller = [[MPMoviePlayerViewController alloc] initWithContentURL:fileURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:playercontroller];
//[self presentMoviePlayerViewControllerAnimated:playercontroller];
playercontroller.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
//playercontroller.moviePlayer.scalingMode = MPMovieScalingModeNone;
playercontroller.moviePlayer.controlStyle = MPMovieControlStyleNone;
[playercontroller.view setFrame:CGRectMake(30, 50, 150, 200)];
[self.videoview addSubview:playercontroller.view];
[playercontroller.moviePlayer prepareToPlay];
[playercontroller.moviePlayer play];
//playercontroller = nil;
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
if ([player respondsToSelector:#selector(setFullscreen:animated:)])
{
[player.view removeFromSuperview];
}
}
Waiting for your advice
It looks like your MPMoviePlayerViewController isn't retained, so it is probably getting deleted.
I am using GPUImage library to record a video to a file on filesystem. I save it as m4v file. This is the code I'm using:
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:recordingDestination];
unlink([pathToMovie UTF8String]);
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(1280.0, 720.0)];
[videoCameraFilter addTarget:movieWriter];
movieWriter.shouldPassthroughAudio = YES;
movieFile.audioEncodingTarget = movieWriter;
[movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
[movieWriter startRecording];
[movieFile startProcessing];
[movieWriter setCompletionBlock:^{
[videoCameraFilter removeTarget:movieWriter];
[movieWriter finishRecording];
}];
This records a m4v video. I then try to play it with MPMoviePlayerController:
NSString *videoPath = [NSString stringWithFormat:#"%#/%#", [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"], [libraryFiles objectAtIndex:selectedCell]];
NSLog(videoPath);
NSURL *url=[[NSURL alloc] initWithString:videoPath];
MPMoviePlayerController *moviePlayer=[[MPMoviePlayerController alloc] initWithContentURL:url];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDidFinish) name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackDonePressed) name:MPMoviePlayerDidExitFullscreenNotification object:moviePlayer];
moviePlayer.controlStyle=MPMovieControlStyleDefault;
[moviePlayer play];
[self.view addSubview:moviePlayer.view];
[moviePlayer setFullscreen:YES animated:YES];
However, the player just starts buffering and nothing happens. The video doesn't start playing. The player is just buffering forever. The app doesn't crash and there are no warnings in the console, so I don't know what is the problem.
I see at a couple of things that don't look right.
First off you're writing directly to NSHomeDirectory which returns the application directory that is however not writeable (see reference).
Either write to the Documents folder or the Library/Caches folder instead.
Secondly I don't see how videoCameraFilter is defined. You need to make sure to add it as a target of movieFile
GPUImageMovie *movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pathToMovie = [documentsDirectory stringByAppendingPathComponent:#"filtered-movie.m4v"];
unlink([pathToMovie UTF8String]);
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
GPUImageMovieWriter *movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(1920.0, 1080.0)];
GPUImageBoxBlurFilter * videoCameraFilter = [[GPUImageBoxBlurFilter alloc] init]; // just a random filter...
videoCameraFilter.blurSize = 2.0;
[movieFile addTarget:videoCameraFilter];
[videoCameraFilter addTarget:movieWriter];
movieWriter.shouldPassthroughAudio = YES;
movieFile.audioEncodingTarget = movieWriter;
[movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
[movieWriter startRecording];
[movieFile startProcessing];
__weak GPUImageMovieWriter *weakMoviewWriter = movieWriter;
[movieWriter setCompletionBlock:^{
[movieFile removeTarget:weakMoviewWriter];
[weakMoviewWriter finishRecording];
}];
* EDIT:
Did you try yo making moviePlayer a property/ivar as #SAMIR RATHOD suggested? The fact that the moviePlayer stays there buffering endlessly is most probably caused because it's not being retained.
add a property to your viewController's interface:
#property (nonatomic, strong) MPMoviePlayerController *moviePlayer;
and instantiate your MPMoviewPlayerController:
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
Try this :
First Check videoPath it display proper path or not?
.h File
MPMoviePlayerController* player
.m
#synthesize player;
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:videoPath]];
player.scalingMode = MPMovieScalingModeFill;
player.movieSourceType = MPMovieSourceTypeFile;
player.view.frame = CGRectMake(0, 45, 320, 400);
player.shouldAutoplay = YES;
[player prepareToPlay];
[self.view addSubview:player.view];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinishedCallback:) name:MPMoviePlayerPlaybackDidFinishNotification object:player];
[player play];
}
#pragma mark MoviPlayer Method
- (void) movieFinishedCallback:(NSNotification*) aNotification {
MPMoviePlayerController *player1 = [aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player1];
[player stop];
[player1.view removeFromSuperview];
player1 = nil;
[self.navigationController popViewControllerAnimated:YES];
}
-(void) dealloc {
[player release];
[super dealloc];
}
sorry for my question but i´ve implemented a intro- video and despite of the hardware silent-switch of my iPad, the audio is playing.
I´m also using the AVAudioplayer within my app just for playing short sound samples. Within this class, its the only region where i´ve set up the "AVAudioSessionCategory".
But for all audio playback only, there´s nothing hearable. Its just for my intro-video.
Any help how to fix that "audio-bug" so the movie player is silent?
Thanks you
Here´s my Audio-class:
- (id)initWithSoundfileName:(NSString*) file
{
if ((self = [super init]))
{
NSString* filename = [file stringByDeletingPathExtension];
NSString* fileextension = [file pathExtension];
// get file path from bundle
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: filename ofType: fileextension];
NSLog(#"AudioPlayer init: %#", soundFilePath);
NSURL* fileurl = [[NSURL alloc] initFileURLWithPath:soundFilePath];
NSError* error = nil;
AVAudioPlayer* audioplayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileurl error:&error ];
if (error) { NSLog(#"Error creating AVAudioPlayer %#", [error description]);}
// set audio policy
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:NULL];
self.player = audioplayer;
[self.player prepareToPlay];
[self.player setDelegate:self];
}
return self;
}
-(void) play{
[self.player play];
}
And here´s my video-playback method:
- (void)playIntroVideo
{
NSString *movpath = [[NSBundle mainBundle] pathForResource:#"mymovie" ofType:#"mp4"];
NSURL *fileURL = [NSURL fileURLWithPath:movpath];
self.moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
self.moviePlayerController.fullscreen = YES;
self.moviePlayerController.scalingMode = MPMovieScalingModeAspectFit;
self.moviePlayerController.controlStyle = MPMovieControlStyleNone;
self.moviePlayerController.movieSourceType = MPMovieSourceTypeFile;
self.moviePlayerController.useApplicationAudioSession = NO;
[self.moviePlayerController.view setFrame: self.view.bounds];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayBackComplete:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayerController];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlaybackStateChanged:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:self.moviePlayerController];
[self.view addSubview:self.moviePlayerController.view];
[self.moviePlayerController prepareToPlay];
[self.moviePlayerController play];
}
Like #Till mentioned:
When I change the MoviePlayerController property to useApplicationAudioSession=TRUE, it fixes my problem. Audio Playback is silent.