You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AVMutableComposition合并AKAudioFile仅导出首轨问题求助

Troubleshooting AVMutableComposition + AudioKit: Only First File Plays in Combined Output

Hey there! Let's dig into why your combined AKAudioFile only plays the first track when using AVMutableComposition with AudioKit. This is a common gotcha, and the issue is almost always tied to how you're building the composition or exporting it to an AKAudioFile—let's break down the most likely culprits and fixes:

1. Most Common Issue: Incorrect Time Offsets in AVMutableComposition

If you're inserting all audio tracks at CMTime.zero, you're overwriting each subsequent file instead of appending them. You need to track the cumulative duration of the composition and insert each new file at the end of the last one.

Fix Your Track Insertion Logic

Here's how to adjust your loop to properly append files:

private func createCombinedRecordingFrom(_ files: [AKAudioFile], completion: @escaping (AKAudioFile?) -> ()) {
    let composition = AVMutableComposition()
    var currentEndTime = CMTime.zero // Track where the last file ends

    for audioFile in files {
        guard let asset = AVURLAsset(url: audioFile.url) else {
            print("Skipping invalid audio file URL")
            continue
        }
        guard let audioAssetTrack = asset.tracks(withMediaType: .audio).first else {
            print("No audio track found in file")
            continue
        }
        guard let compositionTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) else {
            print("Failed to add track to composition")
            continue
        }

        let trackTimeRange = CMTimeRange(start: .zero, duration: asset.duration)
        do {
            // Insert the new track at the END of the composition, not at zero
            try compositionTrack.insertTimeRange(trackTimeRange, of: audioAssetTrack, at: currentEndTime)
            // Update the end time for the next track
            currentEndTime = CMTimeAdd(currentEndTime, asset.duration)
        } catch {
            print("Error inserting track: \(error.localizedDescription)")
        }
    }

    // Now export the composition to an AKAudioFile
    exportComposition(composition, completion: completion)
}

// Helper to export composition to AKAudioFile
private func exportComposition(_ composition: AVMutableComposition, completion: @escaping (AKAudioFile?) -> ()) {
    guard let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) else {
        completion(nil)
        return
    }

    let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent("combined_recording.m4a")
    // Clean up any existing file at the temp URL
    try? FileManager.default.removeItem(at: tempURL)

    exportSession.outputURL = tempURL
    exportSession.outputFileType = .m4a
    exportSession.shouldOptimizeForNetworkUse = true

    exportSession.exportAsynchronously {
        DispatchQueue.main.async {
            switch exportSession.status {
            case .completed:
                guard let url = exportSession.outputURL else {
                    completion(nil)
                    return
                }
                do {
                    let combinedFile = try AKAudioFile(forReading: url)
                    completion(combinedFile)
                } catch {
                    print("Failed to create AKAudioFile: \(error)")
                    completion(nil)
                }
            case .failed, .cancelled:
                print("Export failed: \(exportSession.error?.localizedDescription ?? "Unknown error")")
                completion(nil)
            default:
                completion(nil)
            }
        }
    }
}

2. Possible AudioKit Export Misstep: Skipping Proper Composition Rendering

If you're trying to directly copy AKAudioFile data (like appending raw PCM buffers) instead of using AVAssetExportSession to render the composition, you'll run into issues with audio headers and format mismatches. The AVMutableComposition needs to be rendered into a proper audio file first before loading it into AKAudioFile.

3. Edge Case: Mismatched Audio Formats

If your input AKAudioFiles have different sample rates, channel counts, or bit depths, AVMutableComposition might fail to properly mix/append them, resulting in only the first track being playable.

Check File Formats

Add a quick check to verify consistency:

for (index, file) in files.enumerated() {
    let sampleRate = file.settings[AVSampleRateKey] as? Double ?? 0
    let channels = file.settings[AVNumberOfChannelsKey] as? Int ?? 0
    print("File \(index): Sample rate = \(sampleRate), Channels = \(channels)")
}

If formats differ, you can use AudioKit's AKConverter to normalize them before adding to the composition, or let AVMutableComposition handle conversion (it usually does this automatically, but explicit conversion avoids surprises).

Final Notes

The most probable fix is adjusting your track insertion time offsets—double-check that you're not inserting every track at CMTime.zero. If that doesn't solve it, confirm you're using AVAssetExportSession to render the full composition before loading into AKAudioFile.

内容的提问来源于stack exchange,提问作者Grant Emerson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:20:44