I am using a camera to record video's and save them into my documents folder. The problem I am facing is that the video's I got from the camera are .avi files and have to be converted to .mp4 (or any other allowed format).
I use the code below:
SOURCE: iOS Convert AVI to MP4 Format programatically
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"MyVideo.mp4"];
NSURL *outputURL = [NSURL fileURLWithPath:filePath];
[self convertVideoToLowQuailtyWithInputURL:localUrl outputURL:outputURL handler:^(AVAssetExportSession *exportSession)
{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
// Video conversation completed
}
}];
- (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:AVAssetExportPresetPassthrough];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeMPEG4;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
handler(exportSession);
}];
}
the exportSession status always fails. But when i try to convert a .mov into a .mp4 is does work.
How come I cannot convert .avi files into .mp4 files ?
Try to print the error message:
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed:
NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Export canceled");
break;
case AVAssetExportSessionStatusCompleted:
NSLog(#"Successfully");
break;
default:
break;
}
}];
}
Related
I recorded a video in 120FPS. It is SLOW_Mo video. IF I export that video in CameraRoll using PHImageManager. Everything is ok like as VIDEO Effect is slow_mo. I can play it using QuickPlayer and AVPlayer and effect is 120FPS.
This is my working code:
PHAsset *oneVideo = [[PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeVideo options:nil] lastObject];
PHVideoRequestOptions *options = [PHVideoRequestOptions new];
options.networkAccessAllowed = YES;
options.version = PHVideoRequestOptionsVersionCurrent;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeHighQualityFormat;
[[PHImageManager defaultManager] requestAVAssetForVideo:oneVideo options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
if(([asset isKindOfClass:[AVComposition class]])){
BOOL bResult = FALSE;
DebugLog(#"\navPlayer.outputFileURL.absoluteString:%#", URl);
bResult = [[NSFileManager defaultManager] removeItemAtURL:URl error:nil];
DebugLog(#"\nremoveItemAtPath:%d", bResult);
//Begin slow mo video export
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL = avPlayer.outputFileURL;
// exporter.outputURL = urlFirstVideoPath;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
NSLog(#"Video test run exported video into file: %#", exporter.outputURL);
NSLog(#"exportSession.status: %ld", (long)exporter.status);
dispatch_async(dispatch_get_main_queue(), ^{
if (exporter.status == AVAssetExportSessionStatusCompleted) {
NSLog(#"exportSession.status: okkkkkkk");
}
});
}];
}
}];
NOW I don't want to save that video in CAMERAROLL. I saved video in Document folder. and get AVAssets. But effect is not slow_mo 120FPS I READ about it and got i should use AVComposition for export slow_mo video. but i am unable to do it. Below is my NOT working code.
AVAsset *assetURL = [AVURLAsset URLAssetWithURL:URl options:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths.firstObject;
NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"mergeSlowMoVideo-%d.mov",arc4random() % 1000]];
NSURL *_filePath = [NSURL fileURLWithPath:myPathDocs];
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:assetURL presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL = _filePath;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{ //start
NSLog(#"Export failed: %#", [[exporter error] localizedDescription]);
NSLog(#"Video test run exported video into file: %#", exporter.outputURL);
NSLog(#"export %ld", (long)exporter.status);
dispatch_async(dispatch_get_main_queue(), ^{
if (exporter.status == AVAssetExportSessionStatusCompleted) {
}
});
}];
Please any expert help me.
UPDATE: this is my actual problem.
This Question has my Actual problem explanation
I have tried to find out regarding this issue but didn't find any exact solution for this.
NSString *strPath = #"video.mp4";
NSURL *URL = [NSURL fileURLWithPath:strPath];
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:URL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetMediumQuality];
exportSession.shouldOptimizeForNetworkUse = YES;
NSString *cachesFolder = [NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithFormat:#"%#", [strPath lastPathComponent]]];
NSURL *fileUrl = [NSURL fileURLWithPath:cachesFolder];
exportSession.outputURL = fileUrl;
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed:
NSLog(#"Export failed");
break;
case AVAssetExportSessionStatusCompleted:
NSLog(#"Export Completed");
break;
default:
break;
}
Log: Export failed
I can not comment :(
I just test your code and everything work fine.
Just check in debug "strPath" is correct (export mov file is in bundle)
I Just want to export .mp4 file to CameraRoll
Here is my code.
self.videoPath=#"/var/mobile/Applications/AE75E729-7F10-478B-9DAF-E730EB4231D1/Documents/Videos/aa.mp4";
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:self.videoPath] options:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough];
//NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
exportSession.outputURL = [NSURL fileURLWithPath:self.videoPath];
NSLog(#"videopath of your mp4 file = %#",self.videoPath); // PATH OF YOUR .mp4 FILE
exportSession.outputFileType = AVFileTypeMPEG4;
// CMTime start = CMTimeMakeWithSeconds(1.0, 600);
// CMTime duration = CMTimeMakeWithSeconds(3.0, 600);
// CMTimeRange range = CMTimeRangeMake(start, duration);
// exportSession.timeRange = range;
// UNCOMMENT ABOVE LINES FOR CROP VIDEO
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed:
NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Export canceled");
break;
default:
break;
}
UISaveVideoAtPathToSavedPhotosAlbum(self.videoPath, self, nil, nil);
[exportSession release];
}];
}
Export failed: Cannot Save;
I am converting the .MOV video i get from UIImagePickerController to the .mp4 format using AVAssetExportSession. Once the conversion is completed I send the data to a server. Everything works fine, except the status bar become red and pulsing after the transmission is completed. If I put the app in background and open it again, then the status bar returns to its normal status again.
This is what I think is the piece of code that causes this behavior:
//I took a video
__block NSString *messageType;
__block NSData *messageData;
__block NSString *messageText;
[...]
NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL];
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
NSString *videoPath = nil;
if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality])
{
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough];
videoPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:videoDirectory]stringByAppendingPathComponent:tempVideoFileName];
exportSession.outputURL = [NSURL fileURLWithPath:videoPath];
NSLog(#"videopath of your mp4 file = %#",videoPath); // PATH OF YOUR .mp4 FILE
exportSession.outputFileType = AVFileTypeMPEG4;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed:{
NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
[picker dismissViewControllerAnimated:YES completion:^{
[SVProgressHUD showErrorWithStatus:[[exportSession error] localizedDescription]];
}];
}
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Export canceled");
break;
case AVAssetExportSessionStatusCompleted:{
messageData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoPath]];
messageText = videoPath;
messageType = kMessageTypeVideo;
// This method sends asynchronously the data to the server
[self sendMediaType:messageType MessageData:messageData MessageText:messageText];
[picker dismissViewControllerAnimated:YES completion:NULL];
}
break;
default:
break;
}
}];
}
Is there a way to avoid the appearance of the red status bar or at least the way I should use to make it disappear?
It turns out that in some way the recording session of the UIImagePickerController went in conflict with the AVAssetExportSession.
I resolved this issue by converting the video after having dismissed the UIImagePicker controller:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
if (CFStringCompare ((__bridge_retained CFStringRef) mediaType, kUTTypeImage, 0)
== kCFCompareEqualTo) {
[....]
}
else{
//Took a video
NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL];
[picker dismissViewControllerAnimated:YES completion:^{
[self convertAndSendVideo:url];
}];
}
}
-(void)convertAndSendVideo:(NSURL *)url{
__block NSString *messageType;
__block NSData *messageData;
__block NSString *messageText;
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:avAsset];
NSString *videoPath = nil;
if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality])
{
__block AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:avAsset presetName:AVAssetExportPresetPassthrough];
videoPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:videoDirectory]stringByAppendingPathComponent:tempVideoFileName];
exportSession.outputURL = [NSURL fileURLWithPath:videoPath];
NSLog(#"videopath of your mp4 file = %#",videoPath); // PATH OF YOUR .mp4 FILE
exportSession.outputFileType = AVFileTypeMPEG4;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed:{
NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
[SVProgressHUD showErrorWithStatus:[[exportSession error] localizedDescription]];
}
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Export canceled");
break;
case AVAssetExportSessionStatusCompleted:{
messageData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoPath]];
messageText = videoPath;
messageType = kMessageTypeVideo;
[self sendMediaType:messageType MessageData:messageData MessageText:messageText];
}
break;
default:
break;
}
}];
}
}
I have a video file from the device camera -- stored as /private/var/mobile/Media/DCIM/100APPLE/IMG_0203.MOV, for example, and I need to cut the first 10 seconds of this video. What API or libraries I can use?
I found solution with standard API: AVAssetExportSession
- (void)getTrimmedVideoForFile:(NSString *)filePath withInfo:(NSArray *)info
{
//[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:filePath] options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality];
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSAllDomainsMask, YES);
// NSString *outputURL = paths[0];
NSFileManager *manager = [NSFileManager defaultManager];
// [manager createDirectoryAtPath:outputURL withIntermediateDirectories:YES attributes:nil error:nil];
// outputURL = [outputURL stringByAppendingPathComponent:#"output.mp4"];
NSString *outputURL = [NSString stringWithFormat:#"/tmp/%#.mp4", [info objectAtIndex:2]];
NSLog(#"OUTPUT: %#", outputURL);
// Remove Existing File
// [manager removeItemAtPath:outputURL error:nil];
if (![manager fileExistsAtPath:outputURL]) {
exportSession.outputURL = [NSURL fileURLWithPath:outputURL];
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
CMTime start = kCMTimeZero;
CMTime duration = kCMTimeIndefinite;
if ([[NSString stringWithFormat:#"%#", [info objectAtIndex:3]] floatValue] > 20.0) {
start = CMTimeMakeWithSeconds(1.0, 600);
duration = CMTimeMakeWithSeconds(10.0, 600);
}
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
switch (exportSession.status) {
case AVAssetExportSessionStatusCompleted:
NSLog(#"Export Complete %d %#", exportSession.status, exportSession.error);
[self sendVideoPreview:info];
break;
case AVAssetExportSessionStatusFailed:
NSLog(#"Failed:%#",exportSession.error);
// [self addToDelayed:info withAction:#"add"];
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Canceled:%#",exportSession.error);
// [self addToDelayed:info withAction:#"add"];
break;
default:
break;
}
}];
} else {
[self sendVideoPreview:info];
}