AVAssetExportSession outputfile - iphone

How should the AVAssetExportSession output file look like? I'm trying to compress a video from an ALAsset item and it doesn't work. I'm guessing the output file has something to do with it.
Here's the code i'm using:
NSString *destinationPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Movie"];
[self convertVideoToLowQualityWithInputURL:asset.defaultRepresentation.url outputURL:[NSURL URLWithString:destinationPath]];
- (void)convertVideoToLowQualityWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL {
if([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithContentsOfURL:outputURL encoding: 0 error:Nil]]) [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *assetAV = [AVURLAsset URLAssetWithURL:inputURL options:nil];
NSLog(#"url string from asset: %#", assetAV.URL);
NSLog(#"output url: %#", [outputURL absoluteString]);
[[NSFileManager defaultManager] createFileAtPath:[outputURL path] contents:nil attributes:nil];
NSLog(#"duration: %lld", assetAV.duration.value); //it logs a valid value, so it's all good so far
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:assetAV presetName:AVAssetExportPresetLowQuality];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSLog(#"success");
} else {
NSLog(#"error: %#", [exportSession error]);
//error: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x2023b720 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x2023bb70 "The operation couldn’t be completed. (OSStatus error -12780.)", NSLocalizedFailureReason=An unknown error occurred (-12780)}
}
}];
}
Can someone please help me?
UPDATE:
Found the solution. As I thought the problem was the output file so here is the code for generating a valid one:
NSUInteger count = 0;
NSString *filePath = nil;
do {
NSString *extension = ( NSString *)UTTypeCopyPreferredTagWithClass(( CFStringRef)AVFileTypeQuickTimeMovie, kUTTagClassFilenameExtension);
NSString *fileNameNoExtension = [[asset.defaultRepresentation.url URLByDeletingPathExtension] lastPathComponent];
NSString *fileName = [NSString stringWithFormat:#"%#-%#-%u",fileNameNoExtension , AVAssetExportPresetLowQuality, count];
filePath = NSTemporaryDirectory();
filePath = [filePath stringByAppendingPathComponent:fileName];
filePath = [filePath stringByAppendingPathExtension:extension];
count++;
} while ([[NSFileManager defaultManager] fileExistsAtPath:filePath]);
NSURL *outputURL = [NSURL fileURLWithPath:filePath];

Your issue is [NSURL URLWithString:destinationPath] and only that. You need to use [NSURL fileURLWithPath:xxx] like you did in your solution. Posting this just to clarify that that is the only problem.

Related

How to get file size of file from iPhone documents folder

I have in which i save video file in documents folder it works fine,but i want to get the file size of the saved file,I have searched but did not get result using NSfileManager,here is the code which i use for saving video.I want to get the file size and show it on UILabel.
thanks
NSURL*videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSLog(#"found a video");
videoData = [[NSData dataWithContentsOfURL:videoURL] retain];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSDateFormatter *dateFormat = [[[NSDateFormatter alloc] init] autorelease];
[dateFormat setDateFormat:#"dd-MM-yyyy_HH:mm:SS"];
NSDate *now = [[[NSDate alloc] init] autorelease];
NSDate* theDate = [dateFormat stringFromDate:now];
NSString*myDate=[dateFormat stringFromDate:theDate];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"Default Album"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:nil];
NSString*test=#"test";
NSString*testUser=[test stringByReplacingOccurrencesOfString:#" " withString:#""];
videopath= [[[NSString alloc] initWithString:[NSString stringWithFormat:#"%#/%#.mp4",documentsDirectory,testUser]] autorelease];
BOOL success = [videoData writeToFile:videopath atomically:NO];
NSLog(#"Successs:::: %#", success ? #"YES" : #"NO");
NSLog(#"video path --> %#",videopath);
NSURL *movieURL = [NSURL fileURLWithPath:videopath];
AVURLAsset *avUrl = [AVURLAsset assetWithURL:movieURL];
CMTime time1 = [avUrl duration];
int seconds = ceil(time1.value/time1.timescale);
// durationTime=[NSString stringWithFormat:#"%d",seconds];
// insertTime=[NSString stringWithFormat:#"%d",seconds];
NSString*messageA=[NSString stringWithFormat:#"You have recorded video of duration of %d seconds ",seconds];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert" message:messageA
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
AVAsset *asset = [AVAsset assetWithURL:movieURL];// url= give your url video here
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
CMTime time = CMTimeMake(1, 5);//it will create the thumbnail after the 5 sec of video
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
thumbnailImageView.image=thumbnail;
Note: Above Method is deprecated so, use below method
Objective-C:
NSError* error;
NSDictionary *fileDictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:mediaURL error: &error];
NSNumber *size = [fileDictionary objectForKey:NSFileSize];
Swift:
do
{
let fileDictionary = try FileManager.default.attributesOfItem(atPath: urlString)
let fileSize = fileDictionary[FileAttributeKey.size]
print ("\(fileSize)")
}
catch{}
** this file size in bytes
Try this its help you
NSDictionary *fileDictionary = [[NSFileManager defaultManager] fileAttributesAtPath:videopath traverseLink:YES];
fileSize = [fileDictionary fileSize];
Use NSFileManager attributesOfItemAtPath:error
https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/Reference/Reference.html#//apple_ref/occ/instm/NSFileManager/attributesOfItemAtPath:error:
It returns an NSDictionary of file attributes and one key it contains is NSFileSize, the size of the file.
try this way.
// Get file size
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [documentsDirectory stringByAppendingString:[directoryContent objectAtIndex:indexPath.row]];
NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:filePath traverseLink:YES];
if(fileAttributes != nil)
{
NSString *fileSize = [fileAttributes objectForKey:NSFileSize];
[[cell detailTextLabel] setText:[NSString stringWithFormat:#"%# kb", fileSize]];
NSLog(#"File size: %# kb", fileSize);
}
Before few days I was also searching for something very similar. I was needed to upload the local file to the dropbox and here is something that worked for me: Check the below link:
https://stackoverflow.com/a/1694928/2098401

Convert ImagePath in DocumentDirectory to NSURL Iphone

I am using following code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSURL *myUrl = [[NSURL alloc] initWithString:self.selectedRing.ringThumbNailImagePath];
[Utilities responseDataFromURL:myUrl completionBlock:^(NSData *fileData, NSError *err)
{
if (err != nil)
{
[self.indicator stopAnimating];
[Utilities errorDisplay:#""];
}
else
{
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"Test.igo"];
NSLog(#"FilePath: %#", filePath);
if ([fileData writeToFile:filePath atomically:YES])
{
CGRect rect = CGRectMake(0 ,0 , 0, 0);
NSURL *igImageHookFile = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:#"file://%#", filePath]];
NSLog(#"JPG path %#", filePath);
filePath is
Users/umar/Library/Application Support/iPhone Simulator/6.1/Applications/B45223CF-B437-4617-A02D-DCA91C965A5A/Documents/Test.igo
however i get Nil igImageHookFile NSURL. What is wrong?
Use fileURLWithPath for converting your Path of Document Directory to NSURL like this in piece of code:
NSURL *myImagePath = [NSURL fileURLWithPath:filePath]; //here filePath is your document directory full path with extantionm
For Example:
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"Test.igo"];
NSLog(#"FilePath: %#", filePath);
if ([fileData writeToFile:filePath atomically:YES])
{
CGRect rect = CGRectMake(0 ,0 , 0, 0);
NSURL *igImageHookFile = [NSURL fileURLWithPath:filePath];
NSLog(#"URL from path %#", igImageHookFile);
OUTPUT of path URL something like this:-
file://localhost/Users/umar/Library/Application Support/iPhone Simulator/6.1/Applications/B45223CF-B437-4617-A02D-DCA91C965A5A/Documents/Test.igo
Try this:
NSURL *url = [NSURL URLWithString:[Request stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
Hope it Helps!!

Warning in iCloud integration

I am trying to integrating iCloud.
Everything works fine but when I try to read a file from iCloud I get a warning Like:
Foundation called mkdir("/var/mobile/Library/Mobile Documents/.ubd/peer-E8A60A8F-FB9D-8721-F47C-hdffgdfg-v23/ftr/(A Document Being Saved By XYZ)"), it didn't return 0, and errno was set to 1.
My Code to fetch Data:
for (NSMetadataItem *item in results)
{
NSString *filename = [item valueForAttribute:NSMetadataItemDisplayNameKey];
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
MyDocument *doc = [[MyDocument alloc] initWithFileURL:url];
[doc openWithCompletionHandler:^(BOOL success) {
if (success) {
NSData *file = [NSData dataWithContentsOfURL:url];
NSString *docDir = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"Import/iCloud"];
if (![[NSFileManager defaultManager] fileExistsAtPath:docDir])
[[NSFileManager defaultManager] createDirectoryAtPath:docDir withIntermediateDirectories:YES attributes:nil error:nil];
NSString *pdfFile = [docDir stringByAppendingPathComponent:filename];
if(![[NSFileManager defaultManager] fileExistsAtPath:pdfFile])
[[NSFileManager defaultManager] createFileAtPath:pdfFile contents:file attributes:nil];
NSLog(#"Successfully loaded data from cloud file name %#", filename);
}
else
{
NSLog(#"Failed to load data");
}
}];
}
}
It looks like you have a partially written file in iCloud (based on the A Document Being Saved By XYZ in the error), and your meta data query has returned that to you since it also matches the filename. I ran into a similar situation a few weeks ago and solved it by using the exact path to the file, as in:
NSString *filepath = [containerURL.path stringByAppendingPathComponent:#"MyFileName"];
NSPredicate *pred = [NSPredicate predicateWithFormat: #"%K == %#", NSMetadataItemPathKey, filepath];
[query setPredicate:pred];

UIImagepickercontroller: converting to low quality video error

I am getting inputurl [info objectForKey:UIImagePickerControllerMediaURL] from UIImagepickercontroller's didFinishPickingMediaWithInfo's method.
NSURL *inputURL = [NSURL URLWithString:inputurlstring];
I am giving outputurl from this code
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *videoPath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"capturedvideo.MOV"];
NSURL *outputURL = [NSURL fileURLWithPath:videoPath];
I used the following code to get low quality video
- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL
outputURL:(NSURL*)outputURL
handler:(void (^)(AVAssetExportSession*))handler
{
[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void)
{
if (exportSession.status == AVAssetExportSessionStatusCompleted)
{
printf("completed\n");
}
else
{
printf("error\n");
NSLog(#"error is %#",exportSession.error);
}
}];
}
I am getting following error when I use large files only. Because when I use small size video file I did not get any error.
Error Domain=NSURLErrorDomain Code=-1 "unknown error" UserInfo=0x616d890
{NSErrorFailingURLStringKey=/private/var/mobile/Applications/EE1E6701-EED0-4830-BD1D-7366680713C0/tmp//trim.7mL7VS.MOV, NSErrorFailingURLKey=/private/var/mobile/Applications/EE1E6701-EED0-4830-BD1D-7366680713C0/tmp//trim.7mL7VS.MOV, NSLocalizedDescription=unknown error, NSUnderlyingError=0x2d1460 "The operation couldn’t be completed. (OSStatus error -12935.)", NSURL=/private/var/mobile/Applications/EE1E6701-EED0-4830-BD1D-7366680713C0/tmp//trim.7mL7VS.MOV}
the above code is perfectly works. the only change is inputURL.
after I changed the inputURL to fileURLWithPath:
NSURL *inputURL = [NSURL fileURLWithPath:inputurlstring];
Now its perfectly works.
Instead of this
[info objectForKey:UIImagePickerControllerMediaURL];
use
NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
AVAssetLibrary can access your video through its reference url only.

Not getting resulted movie in PhotoLibrary iPad

i am creating a movie with an array of images and a audio file and saving that created movie to photo library, in simulator i am getting correct movie with my array of image and audio file but while running in device i am not getting my resulted movie instead i am getting the video what i added(OutPut.mov i used in my code) to write my output file (mixed audio and array of images file).
here is my code to save my mixed audio and array of images file to photo lib:
AVMutableComposition* mixComposition = [AVMutableComposition composition];
NSString* audio_inputFilePath = [[NSBundle mainBundle] pathForResource:#"Ruler" ofType:#"caf"];
NSURL* audio_inputFileUrl = [NSURL fileURLWithPath:audio_inputFilePath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *video_inputFilePath = [documentsDirectory stringByAppendingPathComponent:#"videoOutput1234videoOutput1234.mp4"];
NSLog(#"output url %#",video_inputFilePath);
NSURL* video_inputFileUrl = [NSURL fileURLWithPath:video_inputFilePath];
NSString* outputFilePath = [[NSBundle mainBundle] pathForResource:#"OutPut" ofType:#"mov"];
NSURL* outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
[[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];
if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
[[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];
CMTime nextClipStartTime = kCMTimeZero;
AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:video_inputFileUrl options:nil];
CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:nextClipStartTime error:nil];
AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:audio_inputFileUrl options:nil];
CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration);
AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:nextClipStartTime error:nil];
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
_assetExport.outputFileType = #"com.apple.quicktime-movie";
_assetExport.outputURL = outputFileUrl;
[_assetExport exportAsynchronouslyWithCompletionHandler:^(void ) {[self saveVideoToAlbum:outputFilePath]; } ];
You have to write the video file into the photolibrary path like..
- (void)writeVideoToPhotoLibrary:(NSURL *)url
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
NSLog(#"Video could not be saved");
}
}];
[library release];
}
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
// Let's see what happened
NSLog(#"finished");
NSLog(#":error : %#", error);
}