Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract Audio from Video AVFoundation

func extractAudioFromVideo(videoUrl:NSURL, audioPath:String){
    //2
    var asset = AVURLAsset(URL: videoUrl, options: nil)
    asset.loadValuesAsynchronouslyForKeys(NSArray(object: "tracks") as [AnyObject], completionHandler: { () -> Void in
        var audioTrack = asset.tracksWithMediaType(AVMediaTypeAudio)[0] as! AVAssetTrack

        var audioComposition = AVMutableComposition()

        var audioCompositionTrack:AVMutableCompositionTrack!

        audioCompositionTrack = audioComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())
        audioCompositionTrack.insertTimeRange(audioTrack.timeRange, ofTrack: audioTrack, atTime: CMTimeMake(0, 1), error: nil)

        var exportSession = AVAssetExportSession(asset: audioComposition, presetName: AVAssetExportPresetAppleM4A)
        var toFileUrl = NSURL(fileURLWithPath: audioPath)

        exportSession.outputURL = toFileUrl
        exportSession.outputFileType = "com.apple.m4a-audio"

        exportSession.exportAsynchronouslyWithCompletionHandler({ () -> Void in
            if exportSession.status == AVAssetExportSessionStatus.Completed {
                println("Succes")
            }else{
                println("not working")
            }
        })

    })

}

I am using above code to get audio from video, but it is printing "not working"

my audioPath is:

var outStr = NSBundle.mainBundle().pathForResource("cheeseburger", ofType: "m4a")

Please help me with this

Thanks

like image 603
Muhammad Raza Avatar asked Aug 07 '15 13:08

Muhammad Raza


1 Answers

I have re-written the answer for Swift 4.0 since several API changes broke the previous one.

import AVFoundation

extension AVAsset {
    // Provide a URL for where you wish to write
    // the audio file if successful
    func writeAudioTrack(to url: URL,
                         success: @escaping () -> (),
                         failure: @escaping (Error) -> ()) {
        do {
            let asset = try audioAsset()
            asset.write(to: url, success: success, failure: failure)
        } catch {
            failure(error)
        }
    }

    private func write(to url: URL,
                       success: @escaping () -> (),
                       failure: @escaping (Error) -> ()) {
        // Create an export session that will output an
        // audio track (M4A file)
        guard let exportSession = AVAssetExportSession(asset: self,
                                                       presetName: AVAssetExportPresetAppleM4A) else {
                                                        // This is just a generic error
                                                        let error = NSError(domain: "domain",
                                                                            code: 0,
                                                                            userInfo: nil)
                                                        failure(error)

                                                        return
        }

        exportSession.outputFileType = .m4a
        exportSession.outputURL = url

        exportSession.exportAsynchronously {
            switch exportSession.status {
            case .completed:
                success()
            case .unknown, .waiting, .exporting, .failed, .cancelled:
                let error = NSError(domain: "domain", code: 0, userInfo: nil)
                failure(error)
            }
        }
    }

    private func audioAsset() throws -> AVAsset {
        // Create a new container to hold the audio track
        let composition = AVMutableComposition()
        // Create an array of audio tracks in the given asset
        // Typically, there is only one
        let audioTracks = tracks(withMediaType: .audio)

        // Iterate through the audio tracks while
        // Adding them to a new AVAsset
        for track in audioTracks {
            let compositionTrack = composition.addMutableTrack(withMediaType: .audio,
                                                               preferredTrackID: kCMPersistentTrackID_Invalid)
            do {
                // Add the current audio track at the beginning of
                // the asset for the duration of the source AVAsset
                try compositionTrack?.insertTimeRange(track.timeRange,
                                                      of: track,
                                                      at: track.timeRange.start)
            } catch {
                throw error
            }
        }

        return composition
    }
}

Then, you call the extension, and rely on the different closures to process successes and failures. The error handling in this example is extremely primitive, so you will want to improve that when implementing it.

asset.writeAudioTrack(to: url, success: {
    print("Success")
}) { (error) in
    print(error.localizedDescription)
}
like image 198
CodeBender Avatar answered Sep 20 '22 23:09

CodeBender