iOS: trimming audio files with Swift

Swift Language

iOS: trimming audio files

I’ve written about how to record audio on iOS using Swift.
But, how do you trim the recording?

Introduction

Table of Contents

One way to trim an audio file is to use AVFoundation’s AVAssetExportSession. You create an export session instance, set its parameters, and then tell it to export the asset (your audio file) according to those parameters.

In the recorder project, I saved the URL of the recording in the soundFileURL instance variable. To use AVAssetExportSession we need to create an AVAsset from it. Here is a simple action that creates the asset and then call the export function I will discuss next.

Now to define the export func.

You create the exporter from your asset and desired file format. Here I’m using the Apple lossless format.
Then I set the exporter’s outputURL property to a file URL in the documents directory. This will be the location of the trimmed audio file.

I create a core media time range using CMTimeRangeFromTimeToTime that specifies the time offsets for the beginning and ending for the trimmed file. Here I just hard code the values, but of course you’d use a slider or a waveform view to choose the time boundaries.

While you’re there, you can also specify an AVMutableAudioMix for the volume. You can even specify a volume ramp.

Once the exporter’s properties are set, you call exportAsynchronouslyWithCompletionHandler to do the actual work. You can check the status of the export in the completion handler.

Or using Swift 4 syntax:

Groovy, huh?

Summary

Table of Contents

To trim an audio (or video) file, use AVFoundation’s AVAssetExportSession.

Resources

Table of Contents

Share These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Facebook
  • Twitter
  • LinkedIn
  • email
  • DZone
  • Slashdot
  • Reddit
  • Google Bookmarks
  • Digg
  • StumbleUpon
  • del.icio.us
This entry was posted in AVFoundation, Computer Music, Core Audio, Swift and tagged , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

13 Comments

  1. Dai Bui
    Posted July 5, 2015 at 5:03 am | Permalink

    Thanks for good example.

    In the next post, could you make an example about Streaming music with Swift ?

    I’m start to learn swift and build up my first app about Streaming Music Online. Then i get stuck in the process to get the duration of mp3 file from URL, still looking for the solution for it.

    Regards,

    • Alexey Savchenko
      Posted April 2, 2017 at 2:32 am | Permalink

      You should play your streaming audio with AVPlayer. Instantiate AVPlayer with new player item, call play() func and when AVPlayer actually starts playing (isPlating == true) you can grab duration of your mp3 file.
      Below is an extension to AVPlayer.

      extension AVPlayer {

      var isPlaying: Bool {
      return rate != 0 && error == nil
      }

      }

  2. Farzam Hady
    Posted January 10, 2016 at 5:16 am | Permalink

    Hi. You mentioned that we can use slider or a waveform view to choose the time boundaries. I have been searching for a tutorial about that for a week and i couldn’t find anything. Could you please explain that too? i would really appreciate it.

    • Gene De Lisa
      Posted January 12, 2016 at 9:08 am | Permalink

      UISliders are pretty well documented. I think a “range” slider would be better. NMRangeSlider is one open source example.

      SCWaveformView is an open source waveform view.

      • Farzam Hadi
        Posted January 15, 2016 at 3:37 pm | Permalink

        Thank you very much!

  3. Martin
    Posted June 24, 2016 at 9:35 am | Permalink

    Is it possible to change the pitch and rate in the method “exportAsset” ? If it is possible how should i do this?

  4. Linkon
    Posted November 3, 2016 at 6:44 am | Permalink

    Your code works fine. But could you tell why audio quality degrades?? Thanks.

    • Posted August 12, 2017 at 12:57 am | Permalink

      i m trying to trim an mp3 file that is locally saved.

      The code runs correctly as per my use case, let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)

      exportSession?.outputFileType = AVFileTypeQuickTimeMovie

      I exported as the above formats.

      But i keep getting the exported outfile duration as zero
      Below is the code

  5. Posted August 12, 2017 at 12:57 am | Permalink

    i m trying to trim an mp3 file that is locally saved.

    The code runs correctly as per my use case, let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)

    exportSession?.outputFileType = AVFileTypeQuickTimeMovie

    I exported as the above formats.

    But i keep getting the exported outfile duration as zero
    Below is the code

    func exportAsset(asset:AVAsset, fileName:String) {

    // var audioUrl : URL = URL.init(string: “ipod-library://item/item.mp3?id=2928197610297287611”)!
    // var avAsset: AVAsset = AVAsset(url: audioUrl)

    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let trimmedSoundFileURL = documentsDirectory.appendingPathComponent(fileName)

    print(“saving to \(trimmedSoundFileURL.absoluteString)”)

    let filemanager = FileManager.default
    if filemanager.fileExists(atPath: trimmedSoundFileURL.absoluteString) {
    print(“sound exists”)
    }

    let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)
    exportSession?.outputFileType = AVFileTypeQuickTimeMovie
    exportSession?.outputURL = trimmedSoundFileURL

    let duration = CMTimeGetSeconds(asset.duration)
    if (duration Void in
    if exportSession?.status == .completed {
    print(“AVAssetExportSessionStatusCompleted”)
    print(exportSession?.asset)
    // play trimmed song

    }
    else if exportSession?.status == .failed {
    // a failure may happen because of an event out of your control
    // for example, an interruption like a phone call comming in
    // make sure and handle this case appropriately
    print(“AVAssetExportSessionStatusFailed”)
    }
    else {
    print(“Export Session Status: \(exportSession?.status)”)
    }

    })
    }

    func playTrimmedSong() {
    let url: URL = URL.init(string: “file:///var/mobile/Containers/Data/Application/B57F6319-9412-4238-900F-85CE0A4EB343/Documents/trimmed4.m4a”)!

    let avAsset: AVAsset = AVAsset(url: url)

    print(avAsset.duration.seconds)

    }
    </code

  6. Souad
    Posted December 2, 2017 at 7:41 pm | Permalink

    Hello,
    I have an important voice memo recorded in 20171108 on my iphone. Unfortunally i didn’t save in Itunes or in iCloud
    Today 20171202 i trimmed this voice memo
    Trimmed version (20171202) look like overwrite original version (20171108)
    I used application ibrowse to find voice memo file, but in the folder Recording i just have trimmed version not original version.

    I try to use assetmanifest.plist but i’m not confortable with code and function you exposed.
    Could you please help to fix my issue?

    • Gene De Lisa
      Posted December 3, 2017 at 10:03 am | Permalink

      Look at the first example:

      As you see, I’m specifying a new filename for the trimmed sound file.

  7. Souad
    Posted December 3, 2017 at 2:15 pm | Permalink

    Hello,
    Thank you for quick reply.
    I’m a novice in code so i need your help.
    I need a procedure with step by step, could you help me please?
    Where i put this code? In which file?
    This code will be execute?

    Below is what i understood:
    1- In the forlder Recording add new file with this code:
    @IBAction
    func trim() {
    if let asset = AVAsset.assetWithURL(self.soundFileURL) as? AVAsset {
    exportAsset(asset, fileName: “20171108 195140.m4a”)
    }
    }
    2- 20171108 195140.m4a it’s a trimmed filename
    3- If i rename “20171108 195140.m4a” to “20171203_NewFileName.m4a” how i do the link between trimmed file and new file

    Can i share my files with you please?

    Thank you in advance

  8. Souad
    Posted December 5, 2017 at 4:13 pm | Permalink

    Hello Gene,

    Could you please help me ?

Post a Comment

Your email is never published nor shared.

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">