AVAssetExport fails for some files - ios

I have tried to export audio file from the iPod-Library. My objective is to create new file in app Document folder with this iPod-Library file .Its fails to create files for some items only . Below is my code snippet.
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: url options:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
initWithAsset: songAsset
presetName: AVAssetExportPresetAppleM4A];
exporter.outputFileType = #"com.apple.m4a-audio";
NSString *songName = [filename stringByAppendingString:#".m4a"];
NSString *musicfilepath = [documentsDirectory stringByAppendingPathComponent:#"musics/"];
[[NSFileManager defaultManager] createDirectoryAtPath:musicfilepath withIntermediateDirectories:YES attributes:nil error:nil];
NSString *exportFile = [musicfilepath stringByAppendingPathComponent:songName];
NSError *error1;
if([[NSFileManager defaultManager] fileExistsAtPath:exportFile])
{
[[NSFileManager defaultManager] removeItemAtPath:exportFile error:&error1];
}
NSURL* exportURL = [[NSURL fileURLWithPath:exportFile] retain];
exporter.outputURL = exportURL;
Am getting Error as shown below when tried with the error handler block :
[exporter exportAsynchronouslyWithCompletionHandler:^{
int exportStatus = exporter.status;
switch (exportStatus) {
case AVAssetExportSessionStatusFailed: {
NSError *exportError = exporter.error;
NSLog (#"AVAssetExportSessionStatusFailed: %#", exportError);
break;
}
}
}];
AVAssetExportSessionStatusFailed: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x214f20 {NSLocalizedFailureReason=An unknown error occurred (-12124), NSUnderlyingError=0x218270 "The operation couldn’t be completed. (OSStatus error -12124.)", NSLocalizedDescription=The operation could not be completed}

Having played a lot with this myself, some of the answers may be relevant and correct. One other thing to watch out for is that I often used to get similar AVFoundation errors if trying to combine videos that had different frame-rates. Check the source files frame rate and check your CMTime's too. You may have to pre-process some files before adding them into a AVMutableComposition.

If you have iTunes match on and the file is not downloaded to the device, this can happen. Can you check to see if that is the case for you? If so I can give code to detect it.
+ (BOOL)isDownloadedFromiCloud:(MPMediaItem *)item {
if ([item valueForProperty:MPMediaItemPropertyAssetURL] != nil) {
AVURLAsset *asset = [AVURLAsset assetWithURL:[item valueForProperty:MPMediaItemPropertyAssetURL]];
if (asset.exportable)
return YES;
}
return NO;
}

I've experienced this too. Are you using iTunes match? It may be that the file is not on the actual device. You can check this on the AVAsset by checking the properties such as hasProtectedContent or ensuring exportable is YES.
Also, I notice you are using the AVExportSession preset AVAssetExportPresetAppleM4A'. This will re-encode the file you are exporting. It may be easier (and much faster) to just pass-though instead usingAVAssetExportPresetPassthrough`. This assumes you are happy with the existing file format, which maybe .m4a, .mp3, .wav etc...

The the music file path your are using might be wrong. Try this
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
documentsDirectory = [documentsDirectory stringByAppendingPathComponent:#"Music"];
NSError* error;
if (![[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory])
[[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectory withIntermediateDirectories:NO attributes:nil error:&error];
NSString *exportFile = [documentsDirectory stringByAppendingPathComponent:songName];
if([[NSFileManager defaultManager] fileExistsAtPath:exportFile])
{
[[NSFileManager defaultManager] removeItemAtPath:exportFile error:&error1];
}
if (error != nil) {
NSURL* exportURL = [[NSURL fileURLWithPath:exportFile] retain];
exporter.outputURL = exportURL;
[exporter exportAsynchronouslyWithCompletionHandler:^{
int exportStatus = exporter.status;
switch (exportStatus) {
case AVAssetExportSessionStatusFailed: {
NSError *exportError = exporter.error;
NSLog (#"AVAssetExportSessionStatusFailed: %#", exportError);
break;
}
}
}
];
}

Related

iPhone copy file

I create two file paths with this code:
NSString *fileName = [[self genRandStringLength:15] stringByAppendingString:#".mp4"];
NSString *finalFilePath = [self.videoFiles stringByAppendingString:fileName];
NSString *tmpFile = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"temp.mp4"]];
[[NSFileManager defaultManager] removeItemAtPath:tmpFile error:NULL];
Then i have some code to create video file and the i want to save it in the Document Folder:
[[NSFileManager defaultManager] copyItemAtPath:tmpFile toPath:finalFilePath error:&err];
And i get this error:
Error Domain=NSCocoaErrorDomain Code=4 "The file “temp.mp4” doesn’t exist."
UserInfo={NSSourceFilePathErrorKey=/private/var/mobile/Containers/Data/Application/E5B7BBCB-311F-41A3-949D-8A309F535C95/tmp/temp.mp4, NSUserStringVariant=(
Copy
), NSDestinationFilePath=/var/mobile/Containers/Data/Application/E5B7BBCB-311F-41A3-949D-8A309F535C95/Documents/VideoFiles/0iWDmhLvbbzM6SE.mp4, NSFilePath=/private/var/mobile/Containers/Data/Application/E5B7BBCB-311F-41A3-949D-8A309F535C95/tmp/temp.mp4, NSUnderlyingError=0x12f0099b0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
Any idea what can be the problem?
Just for some checking i try to copy the video to the iPhone Photo library with :
UISaveVideoAtPathToSavedPhotosAlbum(tmpFile, self, nil, nil);
And it's work fine, so the file is exist.
Use this code
NSString *fileName = [[self genRandStringLength:15] stringByAppendingString:#".mp4"];
NSString *finalFilePath = [self.videoFiles stringByAppendingString:fileName];
NSString *tmpFile = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"temp.mp4"]];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath:tmpFile];
if (success)
{
[[NSFileManager defaultManager] copyItemAtPath:tmpFile toPath:finalFilePath error:&err];
[[NSFileManager defaultManager] removeItemAtPath:tmpFile error:NULL];
}

Xcode: How to convert MP4-File to Audio-File

I want to convert a MP4-file from the apps Document folder into an Audio-file (mp3 or m4a).
I already tried, but i can not play the converted MP3-file with AVPlayer.
Here is my code:
-(void)convertMP4toMP3withFile:(NSString*)dstPath
{
NSURL *dstURL = [NSURL fileURLWithPath:dstPath];
AVMutableComposition* newAudioAsset = [AVMutableComposition composition];
AVMutableCompositionTrack* dstCompositionTrack;
dstCompositionTrack = [newAudioAsset addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVAsset* srcAsset = [AVURLAsset URLAssetWithURL:dstURL options:nil];
AVAssetTrack* srcTrack = [[srcAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
CMTimeRange timeRange = srcTrack.timeRange;
NSError* error;
if(NO == [dstCompositionTrack insertTimeRange:timeRange ofTrack:srcTrack atTime:kCMTimeZero error:&error]) {
NSLog(#"track insert failed: %#\n", error);
return;
}
AVAssetExportSession* exportSesh = [[AVAssetExportSession alloc] initWithAsset:newAudioAsset presetName:AVAssetExportPresetPassthrough];
exportSesh.outputFileType = AVFileTypeAppleM4A;
exportSesh.outputURL = dstURL;
[[NSFileManager defaultManager] removeItemAtURL:dstURL error:nil];
[exportSesh exportAsynchronouslyWithCompletionHandler:^{
AVAssetExportSessionStatus status = exportSesh.status;
NSLog(#"exportAsynchronouslyWithCompletionHandler: %i\n", status);
if(AVAssetExportSessionStatusFailed == status) {
NSLog(#"FAILURE: %#\n", exportSesh.error);
} else if(AVAssetExportSessionStatusCompleted == status) {
NSLog(#"SUCCESS!\n");
NSError *error;
//append the name of the file in jpg form
//check if the file exists (completely unnecessary).
NSString *onlyPath = [dstPath stringByDeletingLastPathComponent];
NSString *toPathString = [NSString stringWithFormat:#"%#/testfile.m4a", onlyPath];
[[NSFileManager defaultManager] moveItemAtPath:dstPath toPath:toPathString error:&error];
[self loadFiles];
}
}];
}
Has anyone a solution for my problem or can improve my code?
replace this line:
exportSesh.outputFileType = AVFileTypeAppleM4A;
with:
exportSesh.outputFileType = AVFileTypeCoreAudioFormat;
& this:
NSString *toPathString = [NSString stringWithFormat:#"%#/testfile.m4a", onlyPath];
with:
NSString *toPathString = [NSString stringWithFormat:#"%#/testfile.mp3", onlyPath];
Worked for me :)
The code does work on converting mp4 to m4a. Maybe your play audio file code is wrong. Following questions may be helpful to you.
No sound coming from AVPlayer
iOS Extracting Audio from .mov file

Convert a you tube downloaded video to MOV format in iOS

I'm developing an iOS app, which needs to convert a video downloaded using you tube APIs into .mov format. I've tried using AVExportSession output file type set to .mov.`
NSURL * mediaURL = [NSURL fileURLWithPath:outputURL];
AVAsset *video = [AVAsset assetWithURL:mediaURL];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPreset1920x1080];
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
documentsPath=[documentsPath stringByAppendingString:#"/Youtube"];
BOOL isDir;
if (![[NSFileManager defaultManager] fileExistsAtPath:documentsPath isDirectory:&isDir]) {
NSError *createDirError;
if (![[NSFileManager defaultManager] createDirectoryAtPath:documentsPath withIntermediateDirectories:YES attributes:nil error:&createDirError]) {
if (createDirError) {
NSLog(#"eror while creating dir == %#", createDirError);
}
}
}
documentsPath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.mov",arc4random()%10000]];
exportSession.outputURL = [NSURL fileURLWithPath:documentsPath];
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch (exportSession.status) {
case AVAssetExportSessionStatusCompleted:
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:outputURL] completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(#"error>%#",error.description);
}
else{
if([[NSFileManager defaultManager] fileExistsAtPath:outputURL])
{
[[NSFileManager defaultManager]removeItemAtPath:outputURL error:nil];
}
NSLog(#"asseturl>%#",assetURL);
[[NSFileManager defaultManager] removeItemAtPath:outputURL error:nil];
[self addAssetURL:assetURL toAlbum:#"Fame" withCompletionBlock:^(NSError *error) {
if(error)
{
NSLog(#"Error in saving to Fame album : %#",error.description);
return;
}
}];
}
}];
}
break;
case AVAssetExportSessionStatusFailed:
NSLog(#"Error : %#",exportSession.error.description);
default:
break;
}
NSLog(#"done processing video!");
}];
`
This code saves the video to gallery, but when I fetch the video using asset library, I get mp4 in the url.

Error in extracting audio from .m4v video file

I am trying to extract the audio file from .m4v video. It shows the error like,
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x15e350d0 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x15d1c6b0 "The operation couldn’t be completed. (OSStatus error -12124.)", NSLocalizedFailureReason=An unknown error occurred (-12124)}
This is my code:
-(void)extractAudioFromVideo{
//Create a audia composition and add audio track
AVMutableComposition *newAudioAsset = [AVMutableComposition composition];
AVMutableCompositionTrack *dstCompositionTrack = [newAudioAsset addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
//Get video asset from which the audio should be extracted
NSURL *url = [[NSBundle mainBundle] URLForResource:#"sample_iPod" withExtension:#"m4v"];
AVAsset *srcAsset = [AVAsset assetWithURL:url];
NSArray *trackArray = [srcAsset tracksWithMediaType:AVMediaTypeAudio];
if(!trackArray.count){
NSLog(#"Track returns empty array for mediatype AVMediaTypeAudio");
return;
}
AVAssetTrack *srcAssetTrack = [trackArray objectAtIndex:0];
//Extract time range
CMTimeRange timeRange = srcAssetTrack.timeRange;
//Insert audio from the video to mutable avcomposition track
NSError *err = nil;
if(NO == [dstCompositionTrack insertTimeRange:timeRange ofTrack:srcAssetTrack atTime:kCMTimeZero error:&err]){
NSLog(#"Failed to insert audio from the video to mutable avcomposition track");
return;
}
//Export the avcompostion track to destination path
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
NSString *dstPath = [documentsDirectory stringByAppendingString:#"sample_audio.mp4"];
NSURL *dstURL = [NSURL fileURLWithPath:dstPath];
//Remove if any file already exists
[[NSFileManager defaultManager] removeItemAtURL:dstURL error:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]initWithAsset:newAudioAsset presetName:AVAssetExportPresetPassthrough];
NSLog(#"support file types= %#", [exportSession supportedFileTypes]);
exportSession.outputFileType = #"public.mpeg-4";
exportSession.outputURL = dstURL;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
AVAssetExportSessionStatus status = exportSession.status;
if(AVAssetExportSessionStatusCompleted != status){
NSLog(#"Export status not yet completed. Error: %#", exportSession.error.description);
}
}];
}
How can I resolve this error?
I've tested your code in simulator. It's working fine in simulator(IOS7). But When I run on iPodTouch-5, it shows error as like what you've mention. Spend more than 15 mins, found and silly mistake.
Getting path as below(Documentssample_audio.mp4) when I run in Device..
#"file:///var/mobile/Applications/A1E1D85F-0198-4A0C-80F8-222F0DA1C31A/Documentssample_audio.mp4"
so I've modified path as..
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
NSString *dstPath = [documentsDirectory stringByAppendingString:#"/sample_audio.mp4"];
Now I'm getting path as below(/Documents/sample_audio.mp4) and working fine. But I don't know, How it is happened
#"file:///var/mobile/Applications/A1E1D85F-0198-4A0C-80F8-222F0DA1C31A/Documents/sample_audio.mp4"

Error using zlib on ios

This is the code I use to read from a compressed resource file and write the decompressed data to a file in the documents directory:
- (void)setupPFile
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* passwordsFile = [documentsPath stringByAppendingPathComponent:#"p.txt"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:passwordsFile];
if (!fileExists) {
NSString *resourceDictPass = DICTIONARY_FILE;
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:resourceDictPass ofType:#"gz"];
NSData *fileCompressedData= [NSData dataWithContentsOfFile:resourcePath];
NSError *error = nil;
[fileCompressedData writeInflatedToFile:passwordsFile error:&error];
if (error) {
NSLog(#"error uncompressing passwords file");
return;
}
}
});
}
This is the error I get:
Printing description of error:
Error Domain=se.bitba.ZlibErrorDomain Code=2 "The operation couldn’t be completed. (se.bitba.ZlibErrorDomain error 2.)"
I am using a NSData+zlib category I found recommended around here.
How to debug this?

Resources