I want to trim video so i am using UIVideoEditorController but when i check can edit file then it return false for all the files, mp4,mov,m4v. So any one will please guide me what is the problem.
Will you please give me the link of any tutorial of using UIVIdeoEditorcontroller
UIVideoEditorController does not work on simulator so it always returns false, it will work fine on device.
You can find editing of video by path through UIVideoEditorController.
UIVideoEditorController* videoEditor = [[UIVideoEditorController alloc] init];
videoEditor.delegate=self;
NSString* videoPath = [[NSBundle mainBundle] pathForResource:#"video" ofType:#"MOV"];
if ( [UIVideoEditorController canEditVideoAtPath:videoPath] )
{
videoEditor.videoPath = videoPath;
videoEditor.videoMaximumDuration = 10.0;
//[self.customAvPlayerView addSubview:videoEditor.view];
[self presentViewController:videoEditor animated:YES completion:nil];
}
else
{
NSLog( #"can't edit video at %#", videoPath );
}
http://www.raywenderlich.com/forums/viewtopic.php?t=11571&p=60182
Related
Even though it looks like a simple procedure, it's by now 3 hours I'm trying without success. I am probably missing something really stupid.
So, I have this app downloading videos from the Internet. The videos are correctly stored locally because I can play them providing the local url. But, I can't succeed in copying the videos to the camera roll. Here is what I do:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryWriteVideoCompletionBlock videoWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image with metadata to Photo Library %#", newURL.absoluteString);
}
};
NSLog(#"file %#", localPath);
NSURL *url = [NSURL fileURLWithPath:localPath isDirectory:NO];
[library writeVideoAtPathToSavedPhotosAlbum:url
completionBlock:videoWriteCompletionBlock];
But the output I get is:
2013-07-24 00:13:32.094 App[1716:907] file /var/mobile/Applications/70C18C4E-9F97-4A6A-B63E-1BD19961F010/Documents/downloaded_video.mp4
2013-07-24 00:13:32.374 App[1716:907] Wrote image with metadata to Photo Library (null)
And of course the file is not saved in the camera roll. It's a simple mp4, compatible with the device I'm using (i.e. it should be possible to save it).
I honestly have no idea what to do. Any hint will be highly appreciated. Thanks
I may have found a workaround for you. Have you tried an AVAssetExportSession?
In the sample below, I built a simple app that has two buttons on the screen. One calls onSaveBtn:, which simply grabs the URL of a video I have in my app's resource bundle and saves it to the user's saved photos album. (Though, in my case my videos do return YES from videoAtPathIsCompatibleWithSavedPhotosAlbum:. I didn't have any videos that don't return otherwise.)
The second button is wired to onExportBtn:, which takes the video we want to save, creates an AVAssetExportSession, exports the video to a temp directory, and then copies the exported video to the saved photos album. Due to the export time, this method does take longer than a simple copy, but maybe this could be an alternate path - check the results of videoAtPathIsCompatibleWithSavedPhotosAlbum:, and if YES, copy directly to the album. Otherwise, export the video, then copy.
Without having a video file that doesn't return NO to the compatibility call, I'm not 100% sure this would work for you, but it's worth a shot.
You may also want to check out this question, which explores what video formats are compatible on the device you may be using.
#import <AVFoundation/AVFoundation.h>
#import <AssetsLibrary/AssetsLibrary.h>
- (IBAction)onSaveBtn:(id)sender
{
NSURL *srcURL = [[NSBundle mainBundle] URLForResource:#"WP_20121214_001" withExtension:#"mp4"];
[self saveToCameraRoll:srcURL];
}
- (IBAction)onExportBtn:(id)sender
{
NSURL *srcURL = [[NSBundle mainBundle] URLForResource:#"WP_20121214_001" withExtension:#"mp4"];
AVAsset *srcAsset = [AVAsset assetWithURL:srcURL];
// create an export session
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:srcAsset presetName:AVAssetExportPresetHighestQuality];
// Export the file to a tmp dir
NSString *fileName = [srcURL lastPathComponent];
NSString *tmpDir = NSTemporaryDirectory();
NSURL *tmpURL = [NSURL fileURLWithPath:[tmpDir stringByAppendingPathComponent:fileName]];
exportSession.outputURL = tmpURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
// now copy the tmp file to the camera roll
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed:
NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Export canceled");
break;
case AVAssetExportSessionStatusCompleted:
NSLog(#"Export successful");
[self saveToCameraRoll:exportSession.outputURL];
break;
default:
break;
}
}];
}
- (void) saveToCameraRoll:(NSURL *)srcURL
{
NSLog(#"srcURL: %#", srcURL);
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryWriteVideoCompletionBlock videoWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image with metadata to Photo Library %#", newURL.absoluteString);
}
};
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:srcURL])
{
[library writeVideoAtPathToSavedPhotosAlbum:srcURL
completionBlock:videoWriteCompletionBlock];
}
}
Where are you providing the URL to the block.
I think you need to do this way..
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:videoURL completionBlock:^(NSURL *assetURL, NSError *error){
/*notify of completion*/
NSLog(#"AssetURL: %#",assetURL);
NSLog(#"Error: %#",error);
if (!error) {
//video saved
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:error.domain delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
}];
You can change the url here, I have used for the imagePickerController..
See if its helps you..
Here's a shorter answer.
In my case, I've used AFNetworking to download a video from a URL and in the downloadCompletedBlock of the download operation, responseObject returns the download file. Logging responseObject returns me the full file path of the downloaded video.
If you are using another method to download videos, simply replace responseObject with the full file path of your video, probably with the usual NSSearchPathForDirectoriesInDomains method.
Here's the snippet I use to export videos in the application's local file directory to the Camera Roll:
NSURL *responseObjectPath = [NSURL URLWithString:responseObject];
// If video is compatible with Camera Roll
if ([[ALAssetsLibrary new] videoAtPathIsCompatibleWithSavedPhotosAlbum:responseObjectPath])
{
// Export to Camera Roll
[[ALAssetsLibrary new] writeVideoAtPathToSavedPhotosAlbum:responseObjectPath completionBlock:nil];
}
else
{
NSLog(#"Incompatible File Type");
}
Cheers!
In my application I am combining two audio files using AVAssetExportSession and it works fine in earlier ios versions.But in ios5 device its not working. What i am getting is an error
AVAssetExportSessionStatusFailed: Error Domain=AVFoundationErrorDomain Code=-11820 "Cannot Complete Export" UserInfo=0x1df1c0 {NSLocalizedRecoverySuggestion=Try exporting again., NSLocalizedDescription=Cannot Complete Export}
The code that I use for exporting is given below
Did anyone experience the same issue? Please provide your valuable suggestions.
I am in an urgent need to fix this issue..
//Export function to export the combined audios as one.
-(void)exportAudioFile:(AVComposition*)combinedComposition
{
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:combinedComposition
presetName:AVAssetExportPresetPassthrough];
NSArray *presets =[AVAssetExportSession exportPresetsCompatibleWithAsset:combinedComposition];
NSLog(#"presets======%#",presets);
NSLog (#"can export: %#", exportSession.supportedFileTypes);
NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
exportPath = [documentsDirectoryPath stringByAppendingPathComponent:#"CombinedNew.m4a"];
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
exportURL = [NSURL fileURLWithPath:exportPath];
exportSession.outputURL = exportURL;
exportSession.outputFileType = #"com.apple.m4a-audio";
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
NSLog (#"i is in your block, exportin. status is %d",
exportSession.status);
switch (exportSession.status)
{
case AVAssetExportSessionStatusFailed:
{
// log error to text view
NSError *exportError = exportSession.error;
DEBUG_LOG(#"AVAssetExportSessionStatusFailed: %#", exportError);
[self enableUI];
break;
}
case AVAssetExportSessionStatusCompleted:
{
DEBUG_LOG(#"AVAssetExportSessionStatusCompleted");
DEBUG_LOG(#"Completed export");
exportSuccess = YES;
if (recorderFilePath)
{
NSError *finalurlError;
[[NSFileManager defaultManager]removeItemAtPath:recorderFilePath error:&finalurlError];
finalurlError = nil;
[[NSFileManager defaultManager]copyItemAtPath:[exportURL path] toPath:recorderFilePath error:&finalurlError];
}
isExported = YES;
fileUrl = [NSURL fileURLWithPath:recorderFilePath];
[self performSelectorInBackground:#selector(updatePlayerForUrl:) withObject:fileUrl];
break;
}
case AVAssetExportSessionStatusUnknown:
{
DEBUG_LOG(#"AVAssetExportSessionStatusUnknown");
break;
}
case AVAssetExportSessionStatusExporting:
{
DEBUG_LOG(#"AVAssetExportSessionStatusExporting");
break;
}
case AVAssetExportSessionStatusCancelled:
{
DEBUG_LOG(#"AVAssetExportSessionStatusCancelled");
break;
}
case AVAssetExportSessionStatusWaiting:
{
DEBUG_LOG(#"AVAssetExportSessionStatusWaiting");
break;
}
default:
{
DEBUG_LOG(#"didn't get export status");
break;
}
};
}];
[exportSession release];
}
I sorted out the answer for myself and would like to share it with others who experience the same problem.
The problem is that for some reason the AVAssetExportPresetPassthrough is not working properly in ios5. Substituting it with AVAssetExportPresetAppleM4A solved the issue.
But it takes longer to export now.
Perhaps a way around it is to use AVAssetWriter directly and not use AVAssetExportSession. Please please please, file a bug at http://bugreport.apple.com so that maybe it gets fixed in the next rev of iOS5. (I filed one of my own, but the more the merrier.)
As a workaround, I found that using .mov as the file extension, then renaming it back to mp3 seems to work. I dont need to do this for m4a files.
I'm try to create thumbnail image from video url.
I use AV Foundation Programming Guide.
My project have a button and an imageview. When button pressed so thumbnail image will load on uiimageview.
my code can't work,it's:
- (IBAction) btnClick : (id)sender
{
NSURL *url = [NSURL URLWithString:#"http://www.youtube.com/watch?v=bgN62D70VLk"];
AVURLAsset *myAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:myAsset];
Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]);
CMTime midpoint = CMTimeMakeWithSeconds(durationSeconds/2.0, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef halfWayImage = [imageGenerator copyCGImageAtTime:midpoint actualTime:&actualTime error:&error];
if (halfWayImage != NULL) {
NSString *actualTimeString = (NSString *)CMTimeCopyDescription(NULL, actualTime);
NSString *requestedTimeString = (NSString *)CMTimeCopyDescription(NULL, midpoint);
NSLog(#"got halfWayImage: Asked for %#, got %#", requestedTimeString, actualTimeString);
[actualTimeString release];
[requestedTimeString release];
// Do something interesting with the image.
CGImageRelease(halfWayImage);
}
UIImage *image = [UIImage imageWithCGImage:halfWayImage];
[imageView setImage:image];
[imageGenerator release];
}
Help me for this problem,please!
Thanks!
MPMoviePlayerController has some method to handle this -
thumbnailImageAtTime:timeOption:
requestThumbnailImagesAtTimes: timeOption:
cancelAllThumbnailImageRequests:
I see a few problems in your code:
http://www.youtube.com/watch?v=bgN62D70VLk is the URL of a web page, but AVAssets must be video or audio files. Note: YouTube does not advertise the URLs of its video files.
Your call to [myAsset duration] will block. You should instead use the AVAsynchronousKeyValueLoading protocol (see loadValuesAsynchronouslyForKeys).
You are using halfwayImage after releasing it.
I would recommend watching the AVFoundation sessions from WWDC 2010, and looking at the session sample code.
This is very late but it will help some other who comes to this question.
Look into this answer for the same problem, Hope will help to other guys.
I'm very new to core audio and I just would like some help in coding up a little volume meter for whatever's being outputted through headphones or built-in speaker, like a dB meter. I have the following code, and have been trying to go through the apple source project "SpeakHere", but it's a nightmare trying to go through all that, without knowing how it works first... Could anyone shed some light?
Here's the code I have so far...
(void)displayWaveForm
{
while (musicIsPlaying == YES {
NSLog(#"%f",sizeof(AudioQueueLevelMeterState));
}
}
(IBAction)playMusic
{
if (musicIsPlaying == NO) {
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/track7.wav",[[NSBundle mainBundle] resourcePath]]];
NSError *error;
music = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
music.numberOfLoops = -1;
music.volume = 0.5;
[music play];
musicIsPlaying = YES;
[self displayWaveForm];
}
else {
[music pause];
musicIsPlaying = NO;
}
}
you can use metering with the AVAudioPlayer class, first enable it then get the average power to use as your meter data avTouch has a working example
I am working on an iPhone application that uses a MediaPlayer to play a couple different videos. It works great for the first video but when I try to play another the screen stays black and only the audio plays. Does anyone have any idea why this might be happening?
Here is my code:
-(NSURL *)movieURL
{
NSBundle *bundle = [NSBundle mainBundle];
if (bundle)
{
NSString *moviePath = [bundle pathForResource:vidName ofType:#"mov"];
if (moviePath)
mMovieURL = [NSURL fileURLWithPath:moviePath];
if (vidName == #"Vid01")
vidName = #"Vid02";
else if (vidName == #"Vid02")
vidName = #"Vid03";
}
return mMovieURL;
}
- (void)onHitButton1 {
mMoviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[self movieURL]];
mMoviePlayer.movieControlMode = MPMovieControlModeHidden;
[mMoviePlayer play];
}
I figured it out. I needed to release the MediaPlayer before calling the second video.
Code example:
- (void)onHitButton1 {
[mMoviePlayer release];
mMoviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[self movieURL]];
mMoviePlayer.movieControlMode = MPMovieControlModeHidden;
[mMoviePlayer play];
}
You should also note that the playback issues may only occur in the simulator, not on the phone (such as subsequent playback 'flashing' or not displaying an image).
Are you really going to other videos?
I've noticed a bug in 3.0 that if you try to play a video twice from the same file you get some weird playback artifacts. The code you have above looks like it would only ever have a URL pointing to a single file.
The workaround I had was to rename my file, but that means you have to copy it to the documents directory in order to change the name... perhaps you could see if the iPhone file system would support a symbolic or hard link back to the original file in the resource directory so you could feed the movie player different names.
I filed a RADAR on this issue, you should too. Just put together a super simple example showing what is not working.
Shouldn't vidname be changing before the resource path instead of after?
Either way, it would be better to write it to accept an NSString which you could pass the filename to. You know like
-(NSURL *)movieURLForVideo: (NSString) videoFileName
?
Also I didn't like your lack of {}'s. This makes it much easier to read/debug for me. It's a good habit to have in general. Taking the extra time to write things as neat as you can will save you headaches later.
-(NSURL *)movieURL
{
NSBundle *bundle = [NSBundle mainBundle];
if (bundle)
{
if (vidName == #"Vid01")
{
vidName = #"Vid02";
}
else if (vidName == #"Vid02")
{
vidName = #"Vid03";
}
else if (vidName == #"Vid03")
{
vidName = #"Vid01";
}
NSString *moviePath = [bundle pathForResource:vidName ofType:#"mov"];
if (moviePath)
{
mMovieURL = [NSURL fileURLWithPath:moviePath];
}
}
return mMovieURL;
}
Is vidName being set to Vid01 somewhere? I didn't see it so I have to ask. This is just confusing in general. I've been writing for OS X, so I'm not sure if there are any differences, but I use this when I'm loading maps in my current project:
NSString* mapPath = [[NSBundle mainBundle] pathForResource:mapFileName ofType:mapFileType];
NSURL* mapURL = [NSURL fileURLWithPath: mapPath];
currentMap_ = [[Map alloc] initWithContentsOfURL: mapURL];
Just seems like you're writing way more than you need to be.