I'm using the following code:
- (AVAssetExportSession *)testRecording
{
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
NSURL *url = [[NSBundle mainBundle] URLForResource:kTestSongName withExtension:#"mp3"];
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
CMTimeRange range = CMTimeRangeMake(CMTimeMake(0, 600), asset.duration);
NSError *editError;
BOOL result = [composition insertTimeRange:range ofAsset:asset atTime:kCMTimeZero error:&editError];
if (!result) {
NSLog(#"Error inserting timerange");
}
AVAssetExportSession *exportSession = [AVAssetExportSession
exportSessionWithAsset:composition
presetName:AVAssetExportPresetAppleM4A];
return exportSession;
}
This does what it's supposed to on iOS8 but on iOS7 exportSession is always nil at the end of the method. I tried using assets with different formats (mp3, caf) but the result was the same.
If I play the composition instead of exporting it the sound is fine:
AVPlayerItem * item = [[AVPlayerItem alloc] initWithAsset:composition];
AVPlayer * player = [AVPlayer playerWithPlayerItem:item];
[player play];
Any idea about what might be wrong?
exportSession = [[AVAssetExportSession alloc]
initWithAsset:songAsset
presetName:AVAssetExportPresetAppleM4A];
exportSession.outputFileType = #"com.apple.m4a-audio";
filePath = [[docDir stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:#"m4a.mov"]
exportSession.outputURL = [NSURL fileURLWithPath:filePath];
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
NSString *newPath = [NSString stringWithFormat:#"%#/%#", documentDirectory, [[[filePath lastPathComponent] substringToIndex:[[filePath lastPathComponent] length]-5] stringByAppendingString:#"a"]];
[[NSFileManager defaultManager] removeItemAtPath:newPath error:nil];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:filePath toPath:newPath error:&error];
}
if (exportSession.status == AVAssetExportSessionStatusCancelled) {
}
if (exportSession.status == AVAssetExportSessionStatusExporting) {
}
if (exportSession.status == AVAssetExportSessionStatusFailed) {
NSLog(#"erros:%#",exportSession.error);
}
if (exportSession.status == AVAssetExportSessionStatusUnknown) {
}
if (exportSession.status == AVAssetExportSessionStatusWaiting) {
}
}];
If you want to save in mp3 format, use ffmpeg.
Related
I have implemented the scenario of converting audio from video but it is taking about 10 to 15 second, I want it to b much quicker than this as it is not user friendly in my app.
Please suggest me a solution
-(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 = outputMainUrl;
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];
urlOrigionalAudio = dstURL;
//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(status == AVAssetExportSessionStatusCompleted){
urlOrigionalAudio = exportSession.outputURL;
[SVProgressHUD dismiss];
}
else if (status == AVAssetExportSessionStatusFailed){
[SVProgressHUD showErrorWithStatus:#"Failled!"];
NSLog(#"Export status not yet completed");
}
}];
}
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
I have one audio file and want to change its album cover artwork. So, is it possible? And, how can i set the artwork in album cover for audio file in iOS programming?
Actually, i merged two audio file and want to add artwork for album cover which will show in iTune.
Code is given below:
- (BOOL) combineVoices1
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryCachesDirectory = [paths objectAtIndex:0];
libraryCachesDirectory = [libraryCachesDirectory stringByAppendingPathComponent:#"Caches"];
NSString *OutputFilePath = [libraryCachesDirectory stringByAppendingFormat:#"/%#.m4a",textFieldMixFile.text];
NSURL *audioFileOutput = [NSURL fileURLWithPath:OutputFilePath];
NSURL *audioFileInput1= audioFileURL1;//<Path of orignal audio file>
NSURL *audioFileInput2= audioFileURL2;//<Path of orignal audio file>
if (!audioFileInput1 || !audioFileInput2 || !audioFileOutput)
{
return NO;
}
[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
//CMTime nextClipStartTime = kCMTimeZero;
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime nextClipStartTimeMix1;
if (playbackDelayAfterTimeMix1 > 0) {
nextClipStartTimeMix1 = CMTimeMake(playbackDelayAfterTimeMix1, 1);
}else{
nextClipStartTimeMix1 = kCMTimeZero;
}
CMTime startTimeMix1;
if (playbackDelayMix1 > 0) {
startTimeMix1 = CMTimeMake(playbackDelayMix1, 1);
}else{
startTimeMix1 = kCMTimeZero;
}
[compositionAudioTrack setPreferredVolume:[NSTSharedData instance].volumeOfMIX1];
NSURL *url = audioFileURL1; //[NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack;
if (tracks.count > 0) {
clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
}else{
return NO;
}
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(startTimeMix1, avAsset.duration) ofTrack:clipAudioTrack atTime:nextClipStartTimeMix1 error:nil];
//avAsset.commonMetadata
AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime nextClipStartTimeMix2;
if (playbackDelayAfterTimeMix2 > 0) {
nextClipStartTimeMix2 = CMTimeMake(playbackDelayAfterTimeMix2, 1);
}else{
nextClipStartTimeMix2 = kCMTimeZero;
}
CMTime startTimeMix2;
if (playbackDelayMix2 > 0) {
startTimeMix2 = CMTimeMake(playbackDelayMix2, 1);
}else{
startTimeMix2 = kCMTimeZero;
}
[compositionAudioTrack1 setPreferredVolume:[NSTSharedData instance].volumeOfMIX2];
//NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:#"test" ofType:#"caf"];
NSURL *url1 = audioFileURL2; //[NSURL fileURLWithPath:soundOne1];
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack1;
if (tracks1.count > 0) {
clipAudioTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
}else{
return NO;
}
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(startTimeMix2, avAsset1.duration) ofTrack:clipAudioTrack1 atTime:nextClipStartTimeMix2 error:nil];
AVAssetExportSession *exportSession = [AVAssetExportSession
exportSessionWithAsset:composition
presetName:AVAssetExportPresetAppleM4A];
if (nil == exportSession) return NO;
exportSession.outputURL = audioFileOutput;
exportSession.outputFileType = AVFileTypeAppleM4A;
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
[self performSelectorOnMainThread:#selector(performAction) withObject:nil waitUntilDone:NO];
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
[self performSelectorOnMainThread:#selector(hideSpinningWheel) withObject:nil waitUntilDone:NO];
[[NSTSharedData instance] showAlertForTitle:#"Error!" andMessage:[NSString stringWithFormat:#"%#",[[exportSession error] localizedDescription]]];
//NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
}
}];
return YES;
}
I solved my problem and now it working fine, i added code near "AVAssetExportSession" in above code. And finally method is:
- (BOOL) combineVoices1
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryCachesDirectory = [paths objectAtIndex:0];
libraryCachesDirectory = [libraryCachesDirectory stringByAppendingPathComponent:#"Caches"];
NSString *OutputFilePath = [libraryCachesDirectory stringByAppendingFormat:#"/%#.m4a",textFieldMixFile.text];
NSURL *audioFileOutput = [NSURL fileURLWithPath:OutputFilePath];
NSURL *audioFileInput1= audioFileURL1;//<Path of orignal audio file>
NSURL *audioFileInput2= audioFileURL2;//<Path of orignal audio file>
if (!audioFileInput1 || !audioFileInput2 || !audioFileOutput)
{
return NO;
}
[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
//CMTime nextClipStartTime = kCMTimeZero;
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime nextClipStartTimeMix1;
if (playbackDelayAfterTimeMix1 > 0) {
nextClipStartTimeMix1 = CMTimeMake(playbackDelayAfterTimeMix1, 1);
}else{
nextClipStartTimeMix1 = kCMTimeZero;
}
CMTime startTimeMix1;
if (playbackDelayMix1 > 0) {
startTimeMix1 = CMTimeMake(playbackDelayMix1, 1);
}else{
startTimeMix1 = kCMTimeZero;
}
[compositionAudioTrack setPreferredVolume:[NSTSharedData instance].volumeOfMIX1];
NSURL *url = audioFileURL1; //[NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack;
if (tracks.count > 0) {
clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
}else{
return NO;
}
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(startTimeMix1, avAsset.duration) ofTrack:clipAudioTrack atTime:nextClipStartTimeMix1 error:nil];
//avAsset.commonMetadata
AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime nextClipStartTimeMix2;
if (playbackDelayAfterTimeMix2 > 0) {
nextClipStartTimeMix2 = CMTimeMake(playbackDelayAfterTimeMix2, 1);
}else{
nextClipStartTimeMix2 = kCMTimeZero;
}
CMTime startTimeMix2;
if (playbackDelayMix2 > 0) {
startTimeMix2 = CMTimeMake(playbackDelayMix2, 1);
}else{
startTimeMix2 = kCMTimeZero;
}
[compositionAudioTrack1 setPreferredVolume:[NSTSharedData instance].volumeOfMIX2];
//NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:#"test" ofType:#"caf"];
NSURL *url1 = audioFileURL2; //[NSURL fileURLWithPath:soundOne1];
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *clipAudioTrack1;
if (tracks1.count > 0) {
clipAudioTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
}else{
return NO;
}
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(startTimeMix2, avAsset1.duration) ofTrack:clipAudioTrack1 atTime:nextClipStartTimeMix2 error:nil];
/**
added MetadataItem
**/
AVMutableMetadataItem *artistMetadata = [[AVMutableMetadataItem alloc] init];
artistMetadata.key = AVMetadataiTunesMetadataKeyArtist;
artistMetadata.keySpace = AVMetadataKeySpaceiTunes;
artistMetadata.locale = [NSLocale currentLocale];
artistMetadata.value = uTakeTheMicArtist;
AVMutableMetadataItem *albumMetadata = [[AVMutableMetadataItem alloc] init];
albumMetadata.key = AVMetadataiTunesMetadataKeyAlbum;
albumMetadata.keySpace = AVMetadataKeySpaceiTunes;
albumMetadata.locale = [NSLocale currentLocale];
albumMetadata.value = uTakeTheMicAlbum;
AVMutableMetadataItem *songMetadata = [[AVMutableMetadataItem alloc] init];
songMetadata.key = AVMetadataiTunesMetadataKeySongName;
songMetadata.keySpace = AVMetadataKeySpaceiTunes;
songMetadata.locale = [NSLocale currentLocale];
songMetadata.value = textFieldMixFile.text;
AVMutableMetadataItem *imageMetadata = [[AVMutableMetadataItem alloc] init];
imageMetadata.key = AVMetadataiTunesMetadataKeyCoverArt;
imageMetadata.keySpace = AVMetadataKeySpaceiTunes;
imageMetadata.locale = [NSLocale currentLocale];
imageMetadata.value = imageData; //imageData is NSData of UIImage.
NSArray *metadata = [NSArray arrayWithObjects:artistMetadata, albumMetadata, songMetadata, imageMetadata, nil];
AVAssetExportSession *exportSession = [AVAssetExportSession
exportSessionWithAsset:composition
presetName:AVAssetExportPresetAppleM4A];
if (nil == exportSession) return NO;
exportSession.metadata = metadata;
exportSession.outputURL = audioFileOutput;
exportSession.outputFileType = AVFileTypeAppleM4A;
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
[self performSelectorOnMainThread:#selector(performAction) withObject:nil waitUntilDone:NO];
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
[self performSelectorOnMainThread:#selector(hideSpinningWheel) withObject:nil waitUntilDone:NO];
[[NSTSharedData instance] showAlertForTitle:#"Error!" andMessage:[NSString stringWithFormat:#"%#.",[[exportSession error] localizedDescription]]];
//NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
}
}];
return YES;
}
float vocalStartMarker = 1.0;
float vocalEndMarker = 3.0;
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSURL *audioFileInput =[NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/idea_honey_bunny.mp3", [[NSBundle mainBundle] resourcePath]]];
NSURL *audioFileOutput =[NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/idea_honey_bunny.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
if (!audioFileInput || !audioFileOutput)
{
return NO;
}
[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
AVAsset *asset = [AVAsset assetWithURL:audioFileInput];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset
presetName:AVAssetExportPresetAppleM4A];
if (exportSession == nil)
{
return NO;
}
CMTime startTime = CMTimeMake((int)(floor(vocalStartMarker * 1)), 1);
CMTime stopTime = CMTimeMake((int)(ceil(vocalEndMarker * 1)), 1);
CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);
exportSession.outputURL = audioFileOutput;
exportSession.outputFileType = AVFileTypeAppleM4A;
exportSession.timeRange = exportTimeRange;
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
NSLog(#"It worked!");
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
// It failed...
}
}];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileOutput error:&error];
// audioPlayer.numberOfLoops = -1;
if (audioPlayer == nil)
NSLog(#"%#",error);
else
[audioPlayer play];
return YES;
}
i want to try trimming audio file but compiler not entered in this if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
NSLog(#"It worked!");
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
// It failed...
}
}]; bloock and file not trim
You have given same path for audioFileOutput and audioFileInput...So it is going into fail case.And also make sure that file is existed at input path...please change the OutputFile path and check..
exportAsynchronouslyWithCompletionHandler method takes some time to export new asset. So you create your audio player with asset, which not ready.
Try to change your code like this
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
NSLog(#"It worked!");
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileOutput error:&error];
if (audioPlayer == nil) {
NSLog(#"%#",error);
}
else {
[audioPlayer play];
}
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
// It failed...
}
}];
Also, as Murali said above, change path for output file
I searched a lot and couldn't find anything relevant... I am working on iOS audio files and here is what I want to do...
Record Audio and Save Clip (Checked, I did this using AVAudioRecorder)
Change the pitch (Checked, Did this using Dirac)
Trimming :(
I have two markers i.e. starting & ending offset and using this info I want to trim recorded file and want to save it back. I don't want to use "seek" because later on I want to play all recorded files in sync (just like flash movie clips in timeline) and then finally I want to export as one audio file.
Here's the code that I've used to trim audio from a pre-existing file. You'll need to change the M4A related constants if you've saved or are saving to another format.
- (BOOL)trimAudio
{
float vocalStartMarker = <starting time>;
float vocalEndMarker = <ending time>;
NSURL *audioFileInput = <your pre-existing file>;
NSURL *audioFileOutput = <the file you want to create>;
if (!audioFileInput || !audioFileOutput)
{
return NO;
}
[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
AVAsset *asset = [AVAsset assetWithURL:audioFileInput];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset
presetName:AVAssetExportPresetAppleM4A];
if (exportSession == nil)
{
return NO;
}
CMTime startTime = CMTimeMake((int)(floor(vocalStartMarker * 100)), 100);
CMTime stopTime = CMTimeMake((int)(ceil(vocalEndMarker * 100)), 100);
CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);
exportSession.outputURL = audioFileOutput;
exportSession.outputFileType = AVFileTypeAppleM4A;
exportSession.timeRange = exportTimeRange;
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
// It worked!
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
// It failed...
}
}];
return YES;
}
There's also Technical Q&A 1730, which gives a slightly more detailed approach.
import following two libraries in .m
#import "BJRangeSliderWithProgress.h"
#import < AVFoundation/AVFoundation.h >
and after that paste following code you will be able to trim an audio file with the help of two thumbs.
- (void) viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
mySlider = [[BJRangeSliderWithProgress alloc] initWithFrame:CGRectMake(20, 100, 300, 50)];
[mySlider setDisplayMode:BJRSWPAudioSetTrimMode];
[mySlider addTarget:self action:#selector(valueChanged) forControlEvents:UIControlEventValueChanged];
[mySlider setMinValue:0.0];
NSString *strInputFilePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"saewill.mp3"];
NSURL *audioFileInput = [NSURL fileURLWithPath:strInputFilePath];
audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:audioFileInput error:nil];
[mySlider setMaxValue:audioPlayer.duration];
[self.view addSubview:mySlider];
}
-(void)valueChanged {
NSLog(#"%f %f", mySlider.leftValue, mySlider.rightValue);
}
-(IBAction)playTheSong
{
// Path of your source audio file
NSString *strInputFilePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"saewill.mp3"];
NSURL *audioFileInput = [NSURL fileURLWithPath:strInputFilePath];
// Path of your destination save audio file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryCachesDirectory = [paths objectAtIndex:0];
//libraryCachesDirectory = [libraryCachesDirectory stringByAppendingPathComponent:#"Caches"];
NSString *strOutputFilePath = [libraryCachesDirectory stringByAppendingPathComponent:#"output.mov"];
NSString *requiredOutputPath = [libraryCachesDirectory stringByAppendingPathComponent:#"output.m4a"];
NSURL *audioFileOutput = [NSURL fileURLWithPath:requiredOutputPath];
[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
AVAsset *asset = [AVAsset assetWithURL:audioFileInput];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset
presetName:AVAssetExportPresetAppleM4A];
float startTrimTime = mySlider.leftValue;
float endTrimTime = mySlider.rightValue;
CMTime startTime = CMTimeMake((int)(floor(startTrimTime * 100)), 100);
CMTime stopTime = CMTimeMake((int)(ceil(endTrimTime * 100)), 100);
CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);
exportSession.outputURL = audioFileOutput;
exportSession.outputFileType = AVFileTypeAppleM4A;
exportSession.timeRange = exportTimeRange;
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
NSLog(#"Success!");
NSLog(#" OUtput path is \n %#", requiredOutputPath);
NSFileManager * fm = [[NSFileManager alloc] init];
[fm moveItemAtPath:strOutputFilePath toPath:requiredOutputPath error:nil];
//[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
NSURL *url=[NSURL fileURLWithPath:requiredOutputPath];
NSError *error;
audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops=0;
[audioPlayer play];
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
NSLog(#"failed with error: %#", exportSession.error.localizedDescription);
}
}];
}
// Swift 4.2
If anybody is still looking for answer in swift here it is.
//Audio Trimming
func trimAudio(asset: AVAsset, startTime: Double, stopTime: Double, finished:#escaping (URL) -> ())
{
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith:asset)
if compatiblePresets.contains(AVAssetExportPresetMediumQuality) {
guard let exportSession = AVAssetExportSession(asset: asset,
presetName: AVAssetExportPresetAppleM4A) else{return}
// Creating new output File url and removing it if already exists.
let furl = createUrlInAppDD("trimmedAudio.m4a") //Custom Function
removeFileIfExists(fileURL: furl) //Custom Function
exportSession.outputURL = furl
exportSession.outputFileType = AVFileType.m4a
let start: CMTime = CMTimeMakeWithSeconds(startTime, preferredTimescale: asset.duration.timescale)
let stop: CMTime = CMTimeMakeWithSeconds(stopTime, preferredTimescale: asset.duration.timescale)
let range: CMTimeRange = CMTimeRangeFromTimeToTime(start: start, end: stop)
exportSession.timeRange = range
exportSession.exportAsynchronously(completionHandler: {
switch exportSession.status {
case .failed:
print("Export failed: \(exportSession.error!.localizedDescription)")
case .cancelled:
print("Export canceled")
default:
print("Successfully trimmed audio")
DispatchQueue.main.async(execute: {
finished(furl)
})
}
})
}
}
You can use it for video trimming as well. For Video trimming replace the value of export session as bellow:
guard let exportSession = AVAssetExportSession(asset: asset,
presetName: AVAssetExportPresetPassthrough) else{return}
and filetype to mp4
exportSession.outputFileType = AVFileType.mp4
Here is a sample code which trim audio file from starting & ending offset and save it back.
Please check this iOS Audio Trimming.
// Path of your source audio file
NSString *strInputFilePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"abc.mp3"];
NSURL *audioFileInput = [NSURL fileURLWithPath:strInputFilePath];
// Path of your destination save audio file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryCachesDirectory = [paths objectAtIndex:0];
libraryCachesDirectory = [libraryCachesDirectory stringByAppendingPathComponent:#"Caches"];
NSString *strOutputFilePath = [NSString stringWithFormat:#"%#%#",libraryCachesDirectory,#"/abc.mp4"];
NSURL *audioFileOutput = [NSURL fileURLWithPath:strOutputFilePath];
if (!audioFileInput || !audioFileOutput)
{
return NO;
}
[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
AVAsset *asset = [AVAsset assetWithURL:audioFileInput];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetAppleM4A];
if (exportSession == nil)
{
return NO;
}
float startTrimTime = 0;
float endTrimTime = 5;
CMTime startTime = CMTimeMake((int)(floor(startTrimTime * 100)), 100);
CMTime stopTime = CMTimeMake((int)(ceil(endTrimTime * 100)), 100);
CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);
exportSession.outputURL = audioFileOutput;
exportSession.outputFileType = AVFileTypeAppleM4A;
exportSession.timeRange = exportTimeRange;
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
if (AVAssetExportSessionStatusCompleted == exportSession.status)
{
NSLog(#"Success!");
}
else if (AVAssetExportSessionStatusFailed == exportSession.status)
{
NSLog(#"failed");
}
}];