Video file only exports to photos app? - ios

In my application, I allow the user to store a video that has been edited. I save it into the photos application and my document directory for debugging. However, the video only saves into the photos album and not my application and I do not know why. Here is what i'm doing:
- (void) mergeVideos{
//do some neat editing
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *tempPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#_%#_stacked.mov", [[self.firstVideo.videoURL lastPathComponent] stringByDeletingPathExtension], [[self.secondVideo.videoURL lastPathComponent]stringByDeletingPathExtension]]];
NSURL *url = [NSURL fileURLWithPath:tempPath];
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];
exporter.outputURL=url;
[exporter setVideoComposition:MainCompositionInst];
exporter.outputFileType = AVFileTypeQuickTimeMovie;
NSLog(#"EXPORT PATH IS %#",exporter.outputURL);
[exporter exportAsynchronouslyWithCompletionHandler:^
{
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinish:exporter];
});
}];
}
- (void)exportDidFinish:(AVAssetExportSession*)session
{
NSURL *outputURL = session.outputURL;
//NSLog(#"OUTPUT URL: %#",outputURL);
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:outputURL
completionBlock:^(NSURL *assetURL, NSError *error){
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(#"writeVideoToAssetsLibrary failed. Error: %#", error);
}else{
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
Video *video = [NSEntityDescription insertNewObjectForEntityForName:#"Video" inManagedObjectContext:_managedObjectContext];
[video setVideoURL:[NSString stringWithFormat:#"%#",outputURL]];
NSError *error = nil;
if (![_managedObjectContext save:&error]) {
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"ALERT" message:#"SUCCESS" delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
NSLog(#"Successfully written!");
}
});
}];
}
}

Related

IOS How to write and read Metadata to video?

I'm trying to write Metadata information inside a Video recorded inside my app. At the end of video taking i have:
NSMutableArray *metadata = [NSMutableArray array];
AVMutableMetadataItem *mi = [AVMutableMetadataItem metadataItem];
mi.key = AVMetadataCommonKeyTitle;
mi.keySpace = AVMetadataKeySpaceCommon;
mi.value = #"testmetadata";
[metadata addObject:mi];
AVMutableMetadataItem *mi2 = [AVMutableMetadataItem metadataItem];
mi2.key = AVMetadataCommonKeyIdentifier;
mi2.keySpace = AVMetadataKeySpaceCommon;
mi2.value = #"testmetadata";
[metadata addObject:mi2];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:self.outputURL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *outputURL_nuovo = paths[0];
NSFileManager *manager = [NSFileManager defaultManager];
[manager createDirectoryAtPath:outputURL_nuovo withIntermediateDirectories:YES attributes:nil error:nil];
outputURL_nuovo = [outputURL_nuovo stringByAppendingPathComponent:#"output.mp4"];
// Remove Existing File
[manager removeItemAtPath:outputURL_nuovo error:nil];
exportSession.outputURL = [NSURL fileURLWithPath:outputURL_nuovo];
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.metadata=metadata;
CMTime start = CMTimeMakeWithSeconds(1.0, 600);
CMTime duration = CMTimeMakeWithSeconds(3.0, 600);
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void)
{
switch (exportSession.status) {
case AVAssetExportSessionStatusCompleted:
[self writeVideoToPhotoLibrary:[NSURL fileURLWithPath:outputURL_nuovo]];
NSLog(#"Export Complete %d %#", exportSession.status, exportSession.error);
break;
case AVAssetExportSessionStatusFailed:
NSLog(#"Failed:%#",exportSession.error);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Canceled:%#",exportSession.error);
break;
default:
break;
}
}];
If the export end with success, i have this other method:
-(void)writeVideoToPhotoLibrary: (NSURL*)url{
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
[assetsLibrary writeVideoAtPathToSavedPhotosAlbum:url
completionBlock:^(NSURL *assetURL, NSError *error)
{
[assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *assetRep = [asset defaultRepresentation];
NSLog(#"Image filename: %#", [assetRep filename]);
NSDate *date = [asset valueForProperty:ALAssetPropertyDate];
NSLog(#"DATA prima %#",date);
NSLog(#"TIMESTAMP %f",[date timeIntervalSince1970]);
//////////get info
[assetsLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *assetRep = [asset defaultRepresentation];
NSLog(#"Image filename dopp: %#", [assetRep filename]);
NSLog(#"METADATA %#",[assetRep metadata]);
} failureBlock:^(NSError *error) {
NSLog(#"Error: %#", error.localizedDescription);
}];
///////////////get info
} failureBlock:^(NSError *error) {
NSLog(#"Error: %#", error.localizedDescription);
}];
}];
}
With this code i'm trying to save a video with some metadata in it, like a title, and then read the metadata i've just saved. The log returns a null value METADATA (null) , what i'm doing wrong?

How to share Image in Instagram from one application

I am trying to share an image on the Instagram application through my application.
Please check my code below and please let me know where I have gone wrong.
_instagramURL = [NSURL URLWithString:[NSString stringWithFormat: #"instagram://media?id=%#",[SingletoneClass sharedSingleTone].imageId]];
if ([[UIApplication sharedApplication] canOpenURL:_instagramURL]) {
self.dic = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:[SingletoneClass sharedSingleTone].imagePath]];
self.dic.delegate = self;
self.dic.UTI = #"com.instagram.exclusivegram";
self.dic.annotation = [NSDictionary dictionaryWithObject:[SingletoneClass sharedSingleTone].captionStr forKey:#"InstagramCaption"];
[self.dic presentOpenInMenuFromRect: CGRectZero inView:self.view animated:YES ];
}
else {
UIAlertController *alert = [[SingletoneClass sharedSingleTone] setAlertControllerWithTitle:#"" message:#"Instagram is not present in your device" andCallback:^(id actionResponse) {
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[self presentViewController:alert animated:YES completion:nil];
}
If above code is correct, then please let me know, from where I can find the imageId?
Finally, I got the solution. We need to save the image in Document directory. Instagram app can retrieve the image from Document directory.
NSData *imagedata = UIImageJPEGRepresentation(image, 0.5);
NSFileManager *fileManager = [NSFileManager defaultManager];//create instance of NSFileManager
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it
NSString *documentsDirectory = [paths objectAtIndex:0]; //create NSString object, that holds our exact path to the documents directory
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"insta.igo"]]; //add our image to the path
[fileManager createFileAtPath:fullPath contents:imagedata attributes:nil]; //finally save the path (image)
Then by using UIDocumentInteractionController, we can share the image in Instagram app.
Before sharing the image, you need to be sure that Instagram app is present in the device.
- (void) shareImageToInstagram {
_instagramURL = [NSURL URLWithString:[NSString stringWithFormat: #"instagram://app"]];
if ([[UIApplication sharedApplication] canOpenURL:_instagramURL])
{
self.dic = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:[SingletoneClass sharedSingleTone].imagePath]];
self.dic.delegate = self;
self.dic.UTI = #"com.instagram.photo";
self.dic.annotation = [NSDictionary dictionaryWithObjectsAndKeys:[SingletoneClass sharedSingleTone].captionStr,#"InstagramCaption", nil];
[self.dic presentOpenInMenuFromRect: CGRectZero inView:self.view animated:YES ];
}
else
{
UIAlertController *alert = [[SingletoneClass sharedSingleTone] setAlertControllerWithTitle:#"" message:#"Instagram is not present in your device" andCallback:^(id actionResponse) {
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[self presentViewController:alert animated:YES completion:nil];
}
}
You can refer the following links for more information.
https://www.instagram.com/developer/mobile-sharing/iphone-hooks/
and Share photo to Instagram from my iOS App
Check Below code for share image on Instagram , its working fine
import
-(void)shareImageOnInstagram:(UIImage *)image {
if(![[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"instagram://"]]) {
//Your device doesn't have Instagram app.
return;
}
//__weak typeof(self) weakSelf = self;
__block PHFetchResult *photosAsset;
__block PHObjectPlaceholder *placeholder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest* createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
placeholder = [createAssetRequest placeholderForCreatedAsset];
photosAsset = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:#[placeholder.localIdentifier] options:nil];
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
requestOptions.synchronous = YES;
PHFetchOptions *allPhotosOptions = [PHFetchOptions new];
allPhotosOptions.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"creationDate" ascending:YES]];
NSString *identifier = placeholder.localIdentifier;
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *instagramURL = [NSURL URLWithString:[NSString stringWithFormat:#"instagram://library?LocalIdentifier=%#",identifier]];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
[[UIApplication sharedApplication] openURL:instagramURL options:#{} completionHandler:^(BOOL success) {
}];
}
});
}
}];
}

How to save captured image in to the document directory

I captured image using below code
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;
CALayer *viewLayer = self.vImagePreview.layer;
NSLog(#"viewLayer = %#", viewLayer);
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = self.vImagePreview.bounds;
[self.vImagePreview.layer addSublayer:captureVideoPreviewLayer];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
NSLog(#"ERROR: trying to open camera: %#", error);
}
[session addInput:input];
[session startRunning];
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[_stillImageOutput setOutputSettings:outputSettings];
[session addOutput:_stillImageOutput];
when i press the button
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in _stillImageOutput.connections)
{
for (AVCaptureInputPort *port in [connection inputPorts])
{
if ([[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
break;
}
}
if (videoConnection) { break; }
}
NSLog(#"about to request a capture from: %#", _stillImageOutput);
[_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
{
CFDictionaryRef exifAttachments = CMGetAttachment( imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
if (exifAttachments)
{
// Do something with the attachments.
NSLog(#"attachements: %#", exifAttachments);
}
else
NSLog(#"no attachments");
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
self.vImage.image = image;
_vImage.hidden=YES;
UIStoryboard *storybord=[UIStoryboard storyboardWithName:#"Main" bundle:nil];
shareViewController *shareview=[storybord instantiateViewControllerWithIdentifier:#"share"];
[self presentViewController:shareview animated:YES completion:nil];
shareview.shareimageview.image=image;
NSMutableArray *temparray = [NSMutableArray arrayWithObjects:image,nil];
NSMutableArray *newparsetile=[#[#"you"]mutableCopy];
shareview.newtile=newparsetile;
shareview.selectedimgarray=temparray;
[[NSNotificationCenter defaultCenter] postNotificationName:#"Shareimage" object:image];
}];
how to save the output image in to the device document directory,can any body help me out,answer with code is appreciated,since i am new to the ios objective c,the people who want to customize the camera like instagram can use my code it is 100% working
NSData *pngData = UIImagePNGRepresentation(image);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"image_name”]]; //Add the file name
[pngData writeToFile:filePath atomically:YES]; //Write the file
// Saving it to documents direcctory
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [directoryPaths objectAtIndex:0];
NSString* filePath = [documentDirectory stringByAppendingPathComponent:#"FileName.png"];
NSData *imageData = // Some Image data;
NSURL *url = [NSURL fileURLWithPath:filePath];
if ([imageData writeToURL:url atomically:YES]) {
NSLog(#"Success");
}
else{
NSLog(#"Error");
}
You can use above code to save an image to documents directory. Instead of imagedata variable you can pass your variable.

Need to save .MP4 file to Photo Gallery from documents folder but the asset url return nil

I have download the .mp4 file from sever to document directory and called the
writeVideoAtPathToSavedPhotosAlbum method to save to gallery but its nor working.its throwing asset url nil.Can anyone plz help me with this issue
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"test.mp4"];
NSURL *movieURL = [NSURL fileURLWithPath:path];
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
NSLog(#"Moview URL:%#",movieURL);
NSURL *url = [movieURL copy];
[library writeVideoAtPathToSavedPhotosAlbum:url
completionBlock:^(NSURL *assetURL, NSError *error)
{
NSLog(#"Asset Url:%#",assetURL);
if(!error) {
NSLog(#"\t ! Error");
NSLog(#"\t Error: %#", [error localizedDescription]);
NSLog(#"\t Error code %d", [error code]);
}
if(error != nil) {
NSLog(#"\t ERROR != NIL");
NSLog(#"\t Error - Image Failed To Save With Error: %#", [error localizedDescription]);
NSLog(#"\t Error code %d", [error code]);
}
if(error == nil) {
NSLog(#"\t ERROR == NIL");
}
}];
Check this below methods:
-(void)ButtonAction:(id)sender
{
NSURL *video = [NSURL URLWithString:YOURURL];
NSData *data = [NSData dataWithContentsOfURL:video];
NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/myvideo_%#.mp4",docDirPath,CURRENT_TIMESTAMP];
[data writeToFile:filePath atomically:YES];
NSURL *urlPath = [[NSURL alloc] initFileURLWithPath:filePath];
[self saveToCameraRoll:urlPath dict:(NSDictionary *)sender];
}
-(void) saveToCameraRoll:(NSURL *)srcURL dict:(NSDictionary *)dictValues
{
NSLog(#"srcURL: %#", srcURL);
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:srcURL completionBlock:^(NSURL *assetURL, NSError *error)
{
NSURL *savedAssetURL = assetURL;
NSLog(#"asset url %#",assetURL);
if(error)
{
error handling
}
else
{
[library assetForURL:savedAssetURL resultBlock:^(ALAsset * alAsset)
{
NSLog(#"Saved");
}failureBlock:^(NSError *error)
{
NSLog(#"Not Saved");
}];
}
}];
}
Try assetURL.absoluteString in completionBlock

How to merge multiple videos and audio using AVAsset

Hi I am trying to merge videos together using AVMutableComposition .
The problem I am having is that the AVAsset tracksWithMediaTypes method returns an empty array and the app crashed.
Can someone point out what I am doing wrong.
Thanks
Here is what I have so far:
-(void) mergeVideosAndAudio:(AVAsset *)audioAsset{
//Load Video Assets
NSError *error;
NSArray *dirFiles;
if ((dirFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self documentsDirectory] error:&error]) == nil) {
// handle the error
};
// find all the temp files
NSArray *movFiles = [dirFiles filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self BEGINSWITH 'temp'"]];
NSLog(#"The are %i temp files",movFiles.count);
NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:[self documentsDirectory] error:nil];
//Create the composition
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
// 1 - Video track
AVMutableCompositionTrack *firstTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime videoTrackDuration;
for (int j = 0; j < filePathsArray.count; j++) {
NSURL *url = [NSURL fileURLWithPath:filePathsArray[j]];
AVURLAsset *currentAsset = [[AVURLAsset alloc]initWithURL:url options:nil];
videoTrackDuration = CMTimeAdd(videoTrackDuration, currentAsset.duration);
CMTime time;
if (j == 0) {
time = kCMTimeZero;
}else{
NSURL *previousAssetURL = [NSURL fileURLWithPath:filePathsArray[j-1]];
AVURLAsset *previousAsset = [[AVURLAsset alloc]initWithURL:previousAssetURL options:nil];
time = previousAsset.duration;
}
[firstTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, currentAsset.duration) ofTrack:[[currentAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:time error:nil];
}
// 2 - Audio track
if (audioAsset!=nil){
AVMutableCompositionTrack *AudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
[AudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoTrackDuration)
ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];
}
//3 - Get Path for merge
NSString *myPathDocs = [[self documentsDirectory] stringByAppendingPathComponent:
[NSString stringWithFormat:#"mergeVideo-%d.mov",arc4random() % 1000]];
self.fileURL = [NSURL URLWithString: myPathDocs];
// 5 - Create exporter
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=self.fileURL;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinish:exporter];
});
}];
}
-(void)exportDidFinish:(AVAssetExportSession*)session {
if (session.status == AVAssetExportSessionStatusCompleted) {
self.fileURL = session.outputURL;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:self.fileURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:self.fileURL completionBlock:^(NSURL *assetURL, NSError *error){
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Video Saving Failed"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Video Saved" message:#"Saved To Photo Album"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
});
}];
}
}
[self removeTempFilesFromDocuments];
}
Here is a screenshot of the error:
Well, the error is right there "index 0 beyond bounds for empty array".
That means that you have empty array of video assets. Thus, there is something wrong with getting your videoassets via NSFileManager. Go check the array filePathsArray, there is something wrong with it.
First Check video is present at particular path and run proper .
In my case,video is present at path ,but not able to run .
This mostly happen because video not write properly at that path.
Hope it helps.
Please check your files duration that should't be zero.
Not sure if this solves your problem. But I've ran into this issue before when I was trying to load an AVAsset from a url but was getting an asset with no tracks. What fixed it for me was adding "isDirectory:NO" when creating the NSURL:
NSURL *url = [NSURL fileURLWithPath:filePathsArray[j] isDirectory:NO];

Resources