Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Audio Trimming

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...

  1. Record Audio and Save Clip (Checked, I did this using AVAudioRecorder)
  2. Change the pitch (Checked, Did this using Dirac)
  3. 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.

like image 914
Muhammad Usama Avatar asked Mar 14 '12 09:03

Muhammad Usama


People also ask

Can I trim music on iPhone?

You can use GarageBand on your iPhone to add effects to and trim songs from your music library, as well as other AIFF, WAV, CAF, Apple Loops, AAC, MP3, and MIDI files saved to your phone.


3 Answers

// 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

like image 89
Him bhatt Avatar answered Sep 21 '22 19:09

Him bhatt


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.

like image 31
kyleobrien Avatar answered Oct 16 '22 20:10

kyleobrien


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);
           }
       }];

}
like image 3
Sumit Srivastava Avatar answered Oct 16 '22 21:10

Sumit Srivastava