1

병합을위한 아래의 방법을 만들었습니다 (조인, 합집합, 어느 것이 맞는지 확실하지 않음, 2 개 이상에서 1 개의 오디오를 만들고 싶습니다.) 서로 후에 하나씩이 아니라 한 번에 각각을 재생하는 것). 입력으로 나는 .wav 형식의 오디오 파일을 여러 개 가지고 있으며 출력시 1 .wav 형식을 원합니다.iOS 병합 (믹스) wav 형식으로 두 개 이상의 오디오 파일

func merge(audioUrls: [NSURL], resultName : String = "result") { 

    let resultNameWithExtension = resultName + ".wav" 

    //Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack. 
    let composition = AVMutableComposition() 


    //create new file to receive data 
    //let documentDirectoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! 
    let outputFilePath = NSTemporaryDirectory().stringByAppendingPathComponent(resultNameWithExtension) 
    let fileDestinationUrl = NSURL(fileURLWithPath: outputFilePath) 
    print(fileDestinationUrl) 

    StorageManager.sharedInstance.deleteFileAtPath(NSTemporaryDirectory().stringByAppendingPathComponent(resultNameWithExtension)) 

    var avAssets: [AVURLAsset] = [] 
    var assetTracks: [AVAssetTrack] = [] 
    var timeRanges: [CMTimeRange] = [] 

    for audioUrl in audioUrls { 
     let compositionAudioTrack:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID:kCMPersistentTrackID_Invalid) 

     let avAsset = AVURLAsset(URL: audioUrl, options: nil) 
     avAssets.append(avAsset) 

     let assetTrack = avAsset.tracksWithMediaType(AVMediaTypeAudio)[0] 
     assetTracks.append(assetTrack) 

     let duration = assetTrack.timeRange.duration 
     let timeRange = CMTimeRangeMake(kCMTimeZero, duration) 
     timeRanges.append(timeRange) 

     do { 
     try compositionAudioTrack.insertTimeRange(timeRange, ofTrack: assetTrack, atTime: kCMTimeZero) 
     } catch let error as NSError { 
     print("compositionAudioTrack insert error: \(error)") 
     } 
    } 

    let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough)! 
    assetExport.outputFileType = AVFileTypeWAVE 
    assetExport.outputURL = fileDestinationUrl 
    assetExport.exportAsynchronouslyWithCompletionHandler({ 
     self.delegate?.assetExportSessionDidFinishExport(assetExport, outputFilePath: outputFilePath) 
    }) 
    } 

제 문제는 제대로 작동하지 않으며 그 이유를 모르겠습니다. 이 오류는 내가 얻을 :

오류 도메인 = AVFoundationErrorDomain 코드 = -11838이 사용자 정보가 = "작업 중지")

{NSLocalizedDescription = 조작 가 NSLocalizedFailureReason이 작업이 미디어 지원되지 않습니다 =, 중지됨.}

미리 설정 및 출력 유형을 .m4a로 변경하면 작동하지만 .wav가 필요합니다. 동일한 형식의 입력이있을 때 .wav로 작업해야합니다. 어떤 도움을 주셔서 감사합니다

+0

혼합 또는 합산 음악 세계에서 오디오를 병합하는 정확한 용어이다. –

+0

정보 주셔서 감사합니다. 그래서 오디오 파일을 혼합해야합니다. –

+0

나는 과거에 많은 테스트를했으며 AVAssetExportSession이 M4A 파일 이외의 다른 것을 내보낼 수 없었습니다. 귀하의 작업에 대해 AVAssetExportSession과 다른 API를 사용해야 할 수도 있습니다. – Moritz

답변

0

참조 : this question 이것은 iOS 7부터 현저한 버그였습니다. DTS에서 버그를 제기하는 조언은 여전히 ​​불행히도 현재 적용 가능합니다.

코드 줄에 따라 AVAssetWriter로 내보내려는 시도가있는 것은 Converting CAF to WAV입니다.

+0

유용한 코드도 여기에 있습니다. https://developer.apple.com/library/ios/samplecode/ReaderWriter/Listings/Swift_AVReaderWriter_CyanifyOperation_swift.html – matt

0

하나의 오디오 파일을 다른 오디오 파일과 섞거나 오버랩하려면이 코드를 작성해야하지만 .wav 파일이 아닌 .m4a 파일 만 생성 할 수 있습니다. 나는 .mp3 파일을 입력 파일로 사용하고 있습니다. swift3에서

:

예 :

func playmerge(audio1: NSURL, audio2: NSURL) 
{ 
    let composition = AVMutableComposition() 
    let compositionAudioTrack1:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID()) 
    let compositionAudioTrack2:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID()) 

    let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL 
    self.fileDestinationUrl = documentDirectoryURL.appendingPathComponent("resultmerge.m4a")! as URL 

    let filemanager = FileManager.default 
    if (!filemanager.fileExists(atPath: self.fileDestinationUrl.path)) 
    { 
     do 
     { 
      try filemanager.removeItem(at: self.fileDestinationUrl) 
     } 
     catch let error as NSError 
     { 
      NSLog("Error: \(error)") 
     } 

     if (theError == nil) 
     { 
      print("The music files has been Removed.") 
     } 
     else 
     { 
      print("Error") 
     } 
    } 
    else 
    { 
     do 
     { 
      try filemanager.removeItem(at: self.fileDestinationUrl) 
     } 
     catch let error as NSError 
     { 
      NSLog("Error: \(error)") 
     } 

     if (theError == nil) 
     { 
      print("The music files has been Removed.") 
     } 
     else 
     { 
      print("Error") 
     } 
    } 

    let url1 = audio1 
    let url2 = audio2 

    let avAsset1 = AVURLAsset(url: url1 as URL, options: nil) 
    let avAsset2 = AVURLAsset(url: url2 as URL, options: nil) 

    var tracks1 = avAsset1.tracks(withMediaType: AVMediaTypeAudio) 
    var tracks2 = avAsset2.tracks(withMediaType: AVMediaTypeAudio) 

    let assetTrack1:AVAssetTrack = tracks1[0] 
    let assetTrack2:AVAssetTrack = tracks2[0] 

    let duration1: CMTime = assetTrack1.timeRange.duration 
    let duration2: CMTime = assetTrack2.timeRange.duration 

    let timeRange1 = CMTimeRangeMake(kCMTimeZero, duration1) 
    let timeRange2 = CMTimeRangeMake(kCMTimeZero, duration2) 
    do 
    { 
     try compositionAudioTrack1.insertTimeRange(timeRange1, of: assetTrack1, at: kCMTimeZero) 
     try compositionAudioTrack2.insertTimeRange(timeRange2, of: assetTrack2, at: kCMTimeZero) 
    } 
    catch 
    { 
     print(error) 
    } 

    let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) 
    assetExport?.outputFileType = AVFileTypeAppleM4A 
    assetExport?.outputURL = fileDestinationUrl 
    assetExport?.exportAsynchronously(completionHandler: 
     { 
     switch assetExport!.status 
     { 
     case AVAssetExportSessionStatus.failed: 
      print("failed \(assetExport?.error)") 
     case AVAssetExportSessionStatus.cancelled: 
      print("cancelled \(assetExport?.error)") 
     case AVAssetExportSessionStatus.unknown: 
      print("unknown\(assetExport?.error)") 
     case AVAssetExportSessionStatus.waiting: 
      print("waiting\(assetExport?.error)") 
     case AVAssetExportSessionStatus.exporting: 
      print("exporting\(assetExport?.error)") 
     default: 
      print("complete") 
     } 

     do 
     { 
      self.player = try AVAudioPlayer(contentsOf: self.fileDestinationUrl) 
      self.player?.numberOfLoops = 0 
      self.player?.prepareToPlay() 
      self.player?.volume = 1.0 
      self.player?.play() 
      self.player?.delegate=self 
     } 
     catch let error as NSError 
     { 
      print(error) 
     } 
    }) 
} 
+1

코드를 붙여 넣기만으로는 충분하지 않습니다. 올바르게 설명해야합니다. – commando24