Invalid File Output AVAssetExport

Tags: ios audio swift
Question!

When i run my app and click the save button to save the two files mixed together my app crashes saying invalid file output. I dont see why this error shows up because the two files being mixed are mp3 and output file is mp3.

Code:

 @IBAction func mixButton (sender:AnyObject!) {
        let oldAsset = self.player.currentItem.asset

        let type = AVMediaTypeAudio
        let audioFile = NSBundle.mainBundle().URLForResource("file1", withExtension: "mp3")
        let asset1 = AVURLAsset(URL: audioFile, options: nil)
        let arr2 = asset1.tracksWithMediaType(type)
        let track2 = arr2.last as AVAssetTrack

        let duration : CMTime = track2.timeRange.duration

        let comp = AVMutableComposition()
        let comptrack = comp.addMutableTrackWithMediaType(type,
            preferredTrackID: Int32(kCMPersistentTrackID_Invalid))

        comptrack.insertTimeRange(CMTimeRangeMake(CMTimeMakeWithSeconds(0,600), CMTimeMakeWithSeconds(5,600)), ofTrack:track2, atTime:CMTimeMakeWithSeconds(0,600), error:nil)
        comptrack.insertTimeRange(CMTimeRangeMake(CMTimeSubtract(duration, CMTimeMakeWithSeconds(5,600)), CMTimeMakeWithSeconds(5,600)), ofTrack:track2, atTime:CMTimeMakeWithSeconds(5,600), error:nil)



        let type3 = AVMediaTypeAudio
        let s = NSBundle.mainBundle().URLForResource("file2", withExtension:"mp3")
        let asset = AVURLAsset(URL:s, options:nil)
        let arr3 = asset.tracksWithMediaType(type3)
        let track3 = arr3.last as AVAssetTrack

        let comptrack3 = comp.addMutableTrackWithMediaType(type3, preferredTrackID:Int32(kCMPersistentTrackID_Invalid))
        comptrack3.insertTimeRange(CMTimeRangeMake(CMTimeMakeWithSeconds(0,600), CMTimeMakeWithSeconds(10,600)), ofTrack:track3, atTime:CMTimeMakeWithSeconds(0,600), error:nil)



        let params = AVMutableAudioMixInputParameters(track:comptrack3)
        params.setVolume(1, atTime:CMTimeMakeWithSeconds(0,600))
        params.setVolumeRampFromStartVolume(1, toEndVolume:0, timeRange:CMTimeRangeMake(CMTimeMakeWithSeconds(7,600), CMTimeMakeWithSeconds(3,600)))
        let mix = AVMutableAudioMix()
        mix.inputParameters = [params]

        let item = AVPlayerItem(asset:comp)
        item.audioMix = mix
        mixedFile = comp //global variable for mixed file

} }

@IBAction func saveButton(sender: AnyObject) {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
    let savedFileTest = documentsPath + "/myfile.mp3"
    if (NSFileManager.defaultManager().fileExistsAtPath(savedFileTest)) {
        NSFileManager.defaultManager().removeItemAtPath(savedFileTest, error: nil)
    }

    let url = NSURL.fileURLWithPath(savedFileTest)

    let exporter = AVAssetExportSession(asset: mixedFile, presetName: AVAssetExportPresetHighestQuality)
    exporter.outputURL = url
    exporter.outputFileType = AVFileTypeMPEGLayer3

    exporter.exportAsynchronouslyWithCompletionHandler({
        switch exporter.status{
        case  AVAssetExportSessionStatus.Failed:
            println("failed \(exporter.error)")
        case AVAssetExportSessionStatus.Cancelled:
            println("cancelled \(exporter.error)")
        default:
            println("complete")
        }


Answers

You can export it to "AVFileTypeQuickTimeMovie" and rename it to *.mp3.

Init export, here you must set "presentName" argument to "AVAssetExportPresetPassthrough". If not, you will can't export mp3 correct.

AVAssetExportSession *export = [[AVAssetExportSession alloc] initWithAsset:sset presetName:AVAssetExportPresetPassthrough];

Set the ouput type:

exportSession.outputFileType = AVFileTypeQuickTimeMovie;  
exportSession.shouldOptimizeForNetworkUse = true;

Export it and set the file name extension to "mp3".

By : liaogang


The output file is not mp3. You can say mp3 but that doesn't make it one. I don't think Apple framework code can save as mp3. It can read it, but due to various licensing issues it can't write it.

Do it as an m4a, like this (I have starred the lines I changed from your original code):

let savedFileTest = documentsPath   "/myfile.m4a" // *
if (NSFileManager.defaultManager().fileExistsAtPath(savedFileTest)) {
    NSFileManager.defaultManager().removeItemAtPath(savedFileTest, error: nil)
}
let url = NSURL.fileURLWithPath(savedFileTest)
let exporter = AVAssetExportSession(
    asset: mixedFile, presetName: AVAssetExportPresetAppleM4A) // *
exporter.outputURL = url
exporter.outputFileType = AVFileTypeAppleM4A // *

By the way, you're saving the wrong thing (the unmixed comp rather than the mixed item).

By : matt


This video can help you solving your question :)
By: admin