MPMoviePlayerViewController hanging at loading screen - ios

I have code that records the screen in my app, and then I want to be able to play it back. I have gotten so far as to get to the black loading screen with the rewind, play and fast forward buttons, but it hangs at loading without playing anything.
This code plays the clip:
-(IBAction)playMovie:(id)sender
{
MPMoviePlayerViewController *movieViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:locationOfVideoURL];
movieViewController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[self presentMoviePlayerViewControllerAnimated:movieViewController];
}
I believe the problem has something to do with the locationOfVideoURL variable. I am able to print it and it seems like it SHOULD work.
Here it is printed out:
file://localhost/Users/myusername/Library/Application%20Support/iPhone%20Simulator/5.1/Applications/[left out, personal info]/Documents/Videoclip.mp4
Any ideas? Any help would be greatly appreciated! thank you
EDIT: Location of video clip:
NSString *outputPath = [[NSString alloc] initWithFormat:#"%#/%#", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0], #"Videoclip.mp4"];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
NSLog(#"Completed recording, file is stored at: %#", outputURL);

Related

Recorded video sometimes displaying, sometimes not

I have a view controller which records a (front-facing) video of the user. The following code is used:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = [paths objectAtIndex:0];
NSString *outputPath = [[NSString alloc] initWithFormat:#"%#", [basePath stringByAppendingPathComponent:#"output.mp4"]];
if ([[NSFileManager defaultManager] isDeletableFileAtPath:outputPath])
[[NSFileManager defaultManager] removeItemAtPath:outputPath error:NULL];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
self.outputURL = outputURL;
Where movieFileOutput is a AVCaptureMovieFileOutput object. I can show you the camera configuration/setup code (this is not an image picker controller or any Apple UI; this films the user in the background while they interact with a completely different screen) but in general, I know it works.
Afterwards, [movieFileOutput stopRecording]; is called and the user is navigated to a new screen where the recording that just occured is played. I pass on the outputURL object to this newly initialized view controller, where the VC plays it using the following code:
self.player = [[MPMoviePlayerController alloc] initWithContentURL:self.outputURL];
self.player.view.frame = CGRectMake(0, 0, self.view.frame.size.width, 320);
self.player.movieSourceType = MPMovieSourceTypeFile;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlaybackComplete:) name:MPMoviePlayerPlaybackDidFinishNotification object:self.player];
self.player.controlStyle = MPMovieControlStyleNone;
self.player.shouldAutoplay = YES;
[self.player setFullscreen:YES animated:NO];
[self.player prepareToPlay];
[self.view addSubview:[self.player view]];
[self.player play];
So, the first time, everything works. The app records the video, then the next screen is displayed, and the video is shown. But then, if you click the "Discard" button, which segues all the way back to the start of the app, and do the entire process again, it does not work and instead the player shows a black screen. With that being said, I print out the data length at the path and it is always a large number (hence something exists at that path).
Oddly enough, I decided to just print the NSData object itself like so:
NSLog(#"%#", [NSData dataWithContentsOfURL:self.outputURL]);
And indeed a very large string of characters (perhaps the bytes? not sure) is printed. Yet, for some reason, now everything works fine... when I add this NSLog(), the bug no longer occurs. When I remove it, it occurs again! I have tested this rigorously.
But still there are some odd times with the inclusion of this NSLog() when after three times the black screen is played. I am very confused as to why this bug may occur and how on Earth the inclusion of an NSLog() could change any behavior.
Any ideas?
My guess is that you need to wait for the file to have been saved.
The documentation of AVCaptureFileOutput says:
When recording is stopped either by calling this method, by changing
files using startRecordingToOutputFileURL:recordingDelegate:, or
because of an error, the remaining data that needs to be included to
the file will be written in the background. Therefore, before using
the file, you must wait until the delegate that was specified in
startRecordingToOutputFileURL:recordingDelegate: is notified when all
data has been written to the file using the
captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error:
method.

iOS CocoaHttpServer File Download Extremely Slow

I am currently building an http server in iPhone that allows wifi speakers to download music from it. This is so far what I have done:
This is the part that initializes the http server:
- (void)startHttpServer
{
[DDLog addLogger:[DDTTYLogger sharedInstance]];
_httpServer = [[HTTPServer alloc] init];
[_httpServer setType:#"_http._tcp."];
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[_httpServer setDocumentRoot:documentPath];
[_httpServer setPort:9088];
[_httpServer setName:#"Music Server"];
[self startServer]; }
This is the part that gets the asset URL of the music file:
if (currentGroupIndex < currentGroupPlayList.count)
{
[self.savedIndexInfo setObject:[NSNumber numberWithInteger:currentGroupIndex] forKey:groupIDNum];
//makes sure that there is no existing duplicated url;
NSURL *oneURL = [self.savedURLInfo objectForKey:groupIDNum];
[[NSFileManager defaultManager] removeItemAtURL:oneURL error:nil];
MPMediaItem *music = [currentGroupPlayList objectAtIndex:currentGroupIndex];
NSURL *assetURL = [music valueForProperty:MPMediaItemPropertyAssetURL];
[self exportAssetAtURL:assetURL
withTitle:[NSString stringWithFormat:#"song_%lld_%ld", groupID, (long)currentGroupIndex]
groupAdress:groupIP
groupID:groupID
songDuration:[[music valueForProperty:MPMediaItemPropertyPlaybackDuration]intValue]];
}
This is the part that imports the music file and exports the output url:
- (void)exportAssetAtURL:(NSURL*)assetURL withTitle:(NSString*)title groupAdress:(NSString *)groupAdress groupID:(UInt64)groupID songDuration:(NSInteger)duration
{
NSString *ext = [TSLibraryImport extensionForAssetURL:assetURL];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSURL *outURL = [[NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:title]] URLByAppendingPathExtension:ext];
// we're responsible for making sure the destination url doesn't already exist
[[NSFileManager defaultManager] removeItemAtURL:outURL error:nil];
// create the import object
TSLibraryImport* import = [[TSLibraryImport alloc] init];
[import importAsset:assetURL toURL:outURL completionBlock:^(TSLibraryImport* import)
{
if (import.status == AVAssetExportSessionStatusCompleted)
{
NSString *musicURL = [NSString stringWithFormat:#"http://%#:9088/%#.%#", [self currentIPAddress], title, ext];
NSLog(#"URL: %#", musicURL);
cntl_http_pb_pkt pb;
pb.header.packet_type = CONTROL_PACKET;
pb.header.op = CNTL_PB_HTTP_PLAY;
pb.header.body_len = sizeof(pb.body);
const char *adressChar = [groupAdress cStringUsingEncoding:NSASCIIStringEncoding];
pb.body.group_addr = inet_addr(adressChar);
pb.body.group_port = htons(INIT_GROUP_PORT);
pb.body.seq = [NSDate timeIntervalSinceReferenceDate];
self.playSeq = pb.body.seq;
const char *urlChar = [musicURL cStringUsingEncoding:NSASCIIStringEncoding];
memcpy(pb.body.url, urlChar, 200);
NSData *data = [NSData dataWithBytes:&pb length:sizeof(pb)];
[self.savedURLInfo setObject:outURL forKey:[NSNumber numberWithUnsignedLongLong:groupID]];
[self.savedPlayData setObject:musicURL forKey:[NSNumber numberWithUnsignedLongLong:groupID]];
[self performSelectorOnMainThread:#selector(sendUdpData:) withObject:data waitUntilDone:YES];
_acting = NO;
}
else
{
_acting = NO;
NSLog(#"Error importing: %#", import.error);
}
import = nil;
}];
}
My Problem:
50% of the time, its either the music file cannot be downloaded from the server, or the download speed is extremely slow (less than 10kb/s). My problem is I don't know what are the possible causes of this problem, how am I able to solve this.
Different Instances:
Sometimes at the beginning, the download speed is ok(download speed is at 200+kb/s) and then without doing anything at all, the speed would suddenly drop, making the speakers totally impossible to fetch the file from the server. Take note, there are no other devices connected to the router, only speakers and the phone.
Sometimes at the beginning, the song was not playing, and then after a couple of secs the playing would begin.
There is one time I tried connecting 8 speakers to one router, the playing was smooth and fine. But then after an hour or less, Problems would occur, like a lot of stops would occur.
Solutions I have tried:
Tried connecting all speakers under different types of routers
(TP-LINK, Tenda, Netgear, mi, etc...). above instances still occurs.
When the song stops playing or when the data received is incredibly slow, I tried relaunching the app, restarting and phone, and even restarting the router, but then speed is still very slow at the beginning.
Tried disconnecting the router from modem.
Tried connecting only four devices and one phone only.
5.Tried turning off all other wifi devices that are not even under the same network.
Tried changing the port of the http server.
When the problem occurs, I tried checking whether the connection is gone, or the http server is down. But both are ok.
Take Note:
I tried accessing the url by using a browser, the download speed was as slow as the time the speaker was not playing the song smoothly. So I guess the problem is not on the speaker.
There are no error messages returned at all when the problem occurs
No connection terminated when checked on NSLog.
My Request:
So please, if you guys have an idea of what might cause this problem please tell me, or the better, if you know the solution to this. Its really hard to determine what the problem is. Because no error messages are reflected, and I tried removing a lot things that could become possible cause to this problem, but still no good result.
Any help would be highly appreciated.

AVAudioPlayer suddenly no longer plays entire audio source

I am using an AVAudioPlayer to play audio in my app, and it worked for a while. Suddenly, it just stopped working and I cannot figure out why. I created the AVAudioPlayer at the class level in the .h file. This is the code I use to init the player
-(void)initAudio
{
NSURL *song = [[NSBundle mainBundle] URLForResource:#"Prelude" withExtension:#"m4a"];
NSError *error = nil;
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:song error:&error];
[_audioPlayer prepareToPlay];
}
I call this method in the initWithSize function. error is nil, and I have verified that the player object contains the actual audio file. The audio file plays back fine in my OS environment and I have tried adding it to the build phase compile sources just to be safe, even though beforehand it worked fine without it explicitly there. When I trigger the play event, it will play the first snippet of the audio and then nothing. I log the current time of the player and it is 0. Everything else about the app is continuing on and functions without issue. I do not interfere with the avaudioplayer object in any way except to play/pause/preparetoplay.
I am completely stumped as it worked fine and then suddenly no longer works. I have tried to clean the project, I have even dumped the derivedData.
Any ideas?
I think your player has an error when you try to play the song.
You need to check the error first.
In my opinion, it seems like OSStatus error -43.
When you update an app, file path can be changed.
For example,
old path : /var/mobile/Applications/F28E0C2C-4AE2-4C9D-906F-414AE1669D90/Documents/AAA.mp3
new path: var/mobile/Applications/6086783B-A410-42C3-9BAE-7BA755D0E528/Documents/AAA.mp3
Try this code instead:
NSError *error;
NSURL *song = [[NSBundle mainBundle] URLForResource:#"Prelude" withExtension:#"m4a"];
_audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:song error:&error];
if(error){
NSLog(#"[error localizedDescription] %#", [error localizedDescription]);
NSString *fileName = [[song absoluteString] lastPathComponent]; //this code is just example. get your fileName like "AAA.m4a"
NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", docDirPath , fileName];
_audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL URLWithString:filePath] error:&error];
}
_audioPlayer.delegate = self;
[_audioPlayer prepareToPlay];
[_audioPlayer play];
}
I hope this will help you.
Cheers

Play audio after a Time Interval IOS7

Hi in my application, audio is playing when user press the button but now I have two audio buttons like audio1 and audio2, now I want to play second audio after a time interval once the audio1 is completed by clicking the same button.
- (IBAction)btn1:(id)sender {
NSString *audioPath = [[NSBundle mainBundle] pathForResource:#"audio" ofType:#"mp3" ];
NSURL *audioURL = [NSURL fileURLWithPath:audioPath];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
[self.audioPlayer play];
}
The above code I have used for play one audio now I want to play second audio once the first audio completed please tell me how to make it.
Thanks.
Try this:
You have to add a bool variable with the name 'firstAudioPlayed' on start the variable should be NO or FALSE.
- (IBAction)btn1:(id)sender {
if (![self.audioPlayer isPlaying]) {
NSString *audioPath;
if (self.firstAudioPlayed) {
audioPath = [[NSBundle mainBundle] pathForResource:#"audio2" ofType:#"mp3" ];
} else {
audioPath = [[NSBundle mainBundle] pathForResource:#"audio1" ofType:#"mp3" ];
}
NSURL *audioURL = [NSURL fileURLWithPath:audioPath];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
[self.audioPlayer play];
self.firstAudioPlayed = !self.firstAudioPlayed;
}
}
I'm not sure if it's working like this, else just ask with a comment...
Explication of the code:
First you check if the player is already playing a song, if he isn't, you check if the first audio already has played (self.firstAudioPlayed) with this you can give the correct path to load the audio file. Now you play this audio file.
(Sorry for my grammar and my english, corrections are welcome)
You probably should use player's delegate. Set audioPlayer.delegate=self; and implement audioPlayerDidFinishPlaying:successfully: method to see when a player finished playing.
Then you can do whatever you want in there, for example start the second audio.

MPMoviePlayerController video not playing

I used MPMoviePlayerController in my application.
I got the right URL but MPMoviePlayer does not play video it shows only black screen.
My code is as below:
[video setImage:[UIImage imageNamed:#"video_active.png"] forState:UIControlStateNormal];
NSString *filename=[NSString stringWithFormat:#"%#.mp4",[appdel.TempVideoUrl valueForKey:tag]];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:filename];
NSURL *movieURL = [NSURL fileURLWithPath:filePath] ;
theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.view.frame = CGRectMake(106, 18, 216, 235);
[uploadview addSubview:theMovie.view];
// Play the movie.
[theMovie pause];
I got the URL like this:
file://localhost/var/mobile/Applications/6E1D4CB7-A08D-438B-9FE7-E2FD9B7B5EEC/Documents/136_1355227629.mp4
Add [theMovie prepareToPlay]; before calling [theMovie play];.
prepareToPlay
Prepares a movie player for playback. (required)
- (void)prepareToPlay
Discussion
If a movie player is not already prepared to play when you call the
play method, that method automatically calls this method. However, to
minimize playback delay, call this method before you call play.
Calling this method may interrupt the movie player’s audio session.
For information on interruptions and how to resond to them, see Audio
Session Programming Guide. Availability
Available in iOS 3.2 and later.
Declared In MPMediaPlayback.h
Also you can use isPreparedToPlay for checking whether a movie player is ready to play.
Please refer this link for more.

Resources