I debugged my code and found out that when I run test audio file does not created, only empty file with name - no tracks in asset, nothing. But my code works and when I run it, audio files successfully created.But not in tests.
func audioTrackReduction() → URL? {
var mergeAudioURL: URL?
let composition = AVMutableComposition()
let fileName = “merged(arc4random_uniform(1000)).m4a”
let assetAudio = AVURLAsset(url: audioUrl)
let assetVideo = AVURLAsset(url: videoUrl)
let trackAudio = assetAudio.tracks(withMediaType: AVMediaType.audio)[0]
let trackVideo = assetVideo.tracks(withMediaType: AVMediaType.video)[0]
let inputAudioDuration = Double(CMTimeGetSeconds(trackAudio.timeRange.duration))
let inputVideoDuration = Double(CMTimeGetSeconds(trackVideo.timeRange.duration))
if inputAudioDuration == inputVideoDuration {
let compositionAudioTrack :AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!
let timeRange = CMTimeRange(start: CMTimeMake(0, 600), duration: trackAudio.timeRange.duration)
try! compositionAudioTrack.insertTimeRange(timeRange, of: trackAudio, at: composition.duration)
} else if inputAudioDuration > inputVideoDuration {
do {
let asset = try assetByTrimming(timeOffStart: inputVideoDuration, track: trackAudio)
let trackAudioTrimmed = asset.tracks(withMediaType: AVMediaType.audio)[0]
let compositionAudioTrack :AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!
let timeRange = CMTimeRange(start: CMTimeMake(0, 600), duration: trackAudioTrimmed.timeRange.duration)
try! compositionAudioTrack.insertTimeRange(timeRange, of: trackAudioTrimmed, at: composition.duration)
} catch let error {
print(error.localizedDescription)
}
} else {
let timeRange = CMTimeRange(start: CMTimeMake(0, 600), duration: trackAudio.timeRange.duration)
for _ in 0..<Int((inputVideoDuration / inputAudioDuration).rounded(.down)) {
let compositionAudioTrack: AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!
try! compositionAudioTrack.insertTimeRange(timeRange, of: trackAudio, at: composition.duration)
}
let trimmedDuration = inputVideoDuration - Double(CMTimeGetSeconds(composition.duration))
do {
let asset = try assetByTrimming(timeOffStart: trimmedDuration, track: trackAudio)
let trackAudioTrimmed = asset.tracks(withMediaType: AVMediaType.audio)[0]
let compositionAudioTrack :AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!
let timeRange = CMTimeRange(start: CMTimeMake(0, 600), duration: trackAudioTrimmed.timeRange.duration)
try! compositionAudioTrack.insertTimeRange(timeRange, of: trackAudioTrimmed, at: composition.duration)
} catch let error {
print(error.localizedDescription)
}
}
let docsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL
mergeAudioURL = docsURL.appendingPathComponent(fileName)! as URL
let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
assetExport?.outputFileType = AVFileType.m4a
assetExport?.outputURL = mergeAudioURL
assetExport?.exportAsynchronously(completionHandler:
{
switch assetExport!.status
{
case AVAssetExportSessionStatus.failed:
print("failed \(String(describing: assetExport?.error))")
case AVAssetExportSessionStatus.cancelled:
print("cancelled \(String(describing: assetExport?.error))")
case AVAssetExportSessionStatus.unknown:
print("unknown\(String(describing: assetExport?.error))")
case AVAssetExportSessionStatus.waiting:
print("waiting\(String(describing: assetExport?.error))")
case AVAssetExportSessionStatus.exporting:
print("exporting\(String(describing: assetExport?.error))")
default:
print("-----Merge audio exportation complete.\(String(describing: mergeAudioURL))")
}
})
guard let url = mergeAudioURL else {
return nil
}
do {
let audioData = try Data(contentsOf: url)
storage.insert(item: Record(audio: audioData,
name: fileName,
urlString: String(describing: url),
duration: Double(CMTimeGetSeconds((AVURLAsset(url: url).duration)))))
} catch {
print(error.localizedDescription)
}
return mergeAudioURL
}
//Test code
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
guard let url = merger.audioTrackReduction() else {return}
mergedUrl = url
}
func testMergerAudioTrackReduction() {
let gottenAsset = AVURLAsset.init(url: mergedUrl)
let expectedAsset = AVURLAsset.init(url:URL(string: “file:/Users/Nechaev/Documents/TestSmashingFlashing/merged377.m4a”)!)
XCTAssertEqual(gottenAsset, expectedAsset)
}
Gotten asset has nothing but url.