Created
January 19, 2017 11:54
-
-
Save jayeshk/6519a47fbd00e61a88eb392f4996579d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "ViewController.h" | |
#import <AVFoundation/AVFoundation.h> | |
#import <AssetsLibrary/AssetsLibrary.h> | |
//typedef (^AudioWriteComplection)(Bool, NSError); | |
@interface AVAsset (AudiExtract) | |
- (void)writeAudioTrack:(NSURL *)url complection:(void (^)(BOOL, NSError *))completion; | |
- (void)extractAudioFromVideo:(NSURL*)videoSrcPath audioFilePath:(NSString*)dstPath complection:(void (^)(BOOL, NSError *))completion; | |
- (NSURL *)documentFileWithExt:(NSString *)ext; | |
@end | |
@interface ViewController () | |
@property (nonatomic, strong) NSURL *storedVideo; | |
@end | |
@implementation ViewController | |
- (void)viewDidLoad { | |
[super viewDidLoad]; | |
NSURL* videoURL = [[NSBundle mainBundle] URLForResource:@"demo" withExtension:@"mp4"];; | |
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; | |
ALAssetsLibraryWriteVideoCompletionBlock completionBlock = | |
^(NSURL *savedURL, NSError *error) { | |
if (error) { | |
NSLog( @"Error while saving video Photo Library: %@", error ); | |
} else { | |
NSLog( @"Successfuly saved video to Photo Library %@", savedURL.absoluteString); | |
self.storedVideo = savedURL; | |
[self processAudio:self.storedVideo]; | |
} | |
}; | |
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:videoURL]) | |
{ | |
[library writeVideoAtPathToSavedPhotosAlbum:videoURL completionBlock:completionBlock]; | |
} | |
} | |
- (void)didReceiveMemoryWarning { | |
[super didReceiveMemoryWarning]; | |
} | |
- (void)processAudio:(NSURL *)url | |
{ | |
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil]; | |
NSURL *outputUrl = [asset documentFileWithExt:@"m4a"]; | |
NSLog(@"Storing at %@", outputUrl.absoluteString); | |
[asset writeAudioTrack:outputUrl complection:^(BOOL success, NSError *error) { | |
if( success) | |
{ | |
NSLog(@"...E.X.P.O.R.T.E.D..."); | |
} | |
else | |
{ | |
NSLog(@"...F.A.I.L..."); | |
} | |
}]; | |
/* | |
[asset extractAudioFromVideo:url audioFilePath:fileName complection:^(BOOL success, NSError *error) { | |
if(success) | |
{ | |
NSLog(@"Second approch...E.X.P.O.R.T.E.D..."); | |
} | |
else | |
{ | |
NSLog(@"Second approch...F.A.I.L..."); | |
} | |
}]; | |
*/ | |
} | |
@end | |
@implementation AVAsset (AudiExtract) | |
- (NSURL *)documentFileWithExt:(NSString *)ext | |
{ | |
NSArray *arr = [[NSFileManager defaultManager] URLsForDirectory: NSDocumentDirectory | |
inDomains: NSUserDomainMask]; | |
NSURL *documentsUrl = [arr firstObject]; | |
NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; | |
formatter.dateFormat = @"YYYYMMddHHmmss"; | |
NSString *fileName = [NSString stringWithFormat:@"output_%@.%@", [formatter stringFromDate:[NSDate new]], ext]; | |
NSURL *outputUrl = [documentsUrl URLByAppendingPathComponent:fileName]; | |
return outputUrl; | |
} | |
- (void)writeAudioTrack:(NSURL *)url complection:(void (^)(BOOL, NSError *))completion; | |
{ | |
AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:self presetName:AVAssetExportPresetAppleM4A]; | |
if(session != nil) | |
{ | |
session.outputFileType = AVFileTypeAppleM4A; | |
session.outputURL = url; | |
session.timeRange = CMTimeRangeMake(kCMTimeZero, [self duration]); | |
[session exportAsynchronouslyWithCompletionHandler:^{ | |
if(session.status == AVAssetExportSessionStatusCompleted) | |
{ | |
NSLog(@"Completed.."); | |
completion(true, nil); | |
} | |
else if (session.status == AVAssetExportSessionStatusExporting) | |
{ | |
NSLog(@"Exporting..."); | |
} | |
else | |
{ | |
NSLog(@"Export Failed status = %ld", (long)session.status); | |
completion(false, nil); | |
} | |
}]; | |
} | |
else | |
{ | |
NSLog(@"Failed to create session"); | |
completion(false, nil); | |
} | |
} | |
- (void)extractAudioFromVideo:(NSURL*)videoSrcPath audioFilePath:(NSString*)dstPath complection:(void (^)(BOOL, NSError *))completion | |
{ | |
AVMutableComposition* newAudioAsset = [AVMutableComposition composition]; | |
AVMutableCompositionTrack* dstCompositionTrack; | |
dstCompositionTrack = [newAudioAsset addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; | |
//NSURL *srcURL=[NSURL fileURLWithPath:videoSrcPath]; | |
NSURL *srcURL=videoSrcPath; | |
AVAsset* srcAsset = [AVURLAsset URLAssetWithURL:srcURL options:nil]; | |
AVAssetTrack* srcTrack = [[srcAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; | |
NSArray *formatDescriptions=srcTrack.formatDescriptions; | |
NSString *fileType = nil; | |
NSString *ex = nil; | |
if ([formatDescriptions count] > 0) | |
{ | |
CMAudioFormatDescriptionRef formatDesc=(__bridge CMFormatDescriptionRef)[formatDescriptions objectAtIndex:0]; | |
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDesc); | |
NSLog(@"mediaSubType>>%u",(unsigned int)mediaSubType); | |
const AudioStreamBasicDescription * asbd=CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc); | |
FourCharCode formatID = asbd->mFormatID; | |
NSLog(@"formatID>>%u",(unsigned int)mediaSubType); | |
switch (formatID) { | |
case kAudioFormatLinearPCM: | |
{ | |
UInt32 flags = asbd->mFormatFlags; | |
if (flags & kAudioFormatFlagIsBigEndian) { | |
fileType = @"public.aiff-audio"; | |
ex = @"aif"; | |
} else { | |
fileType = @"com.microsoft.waveform-audio"; | |
ex = @".wav"; | |
} | |
} | |
break; | |
case kAudioFormatMPEGLayer3: | |
fileType = @"com.apple.quicktime-movie"; | |
ex = @".mp3"; | |
break; | |
case kAudioFormatMPEG4AAC: | |
fileType = @"com.apple.m4a-audio"; | |
ex = @".m4a"; | |
break; | |
case kAudioFormatAppleLossless: | |
fileType = @"com.apple.m4a-audio"; | |
ex = @".m4a"; | |
break; | |
default: | |
break; | |
} | |
} | |
NSURL *outputUrl = [self documentFileWithExt:@"m4a"]; | |
[[NSFileManager defaultManager] removeItemAtURL:outputUrl error:nil]; | |
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 = fileType; | |
exportSesh.outputURL = outputUrl; | |
[exportSesh exportAsynchronouslyWithCompletionHandler:^{ | |
AVAssetExportSessionStatus status = exportSesh.status; | |
NSLog(@"exportAsynchronouslyWithCompletionHandler: %li\n", (long)status); | |
if(AVAssetExportSessionStatusFailed == status) { | |
dispatch_async(dispatch_get_main_queue(), ^(void){ | |
completion(false,nil); | |
}); | |
NSLog(@"FAILURE: %@\n", exportSesh.error); | |
} else if(AVAssetExportSessionStatusCompleted == status) { | |
dispatch_async(dispatch_get_main_queue(), ^(void){ | |
completion(true,nil); | |
}); | |
} | |
}]; | |
} | |
@end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
nice