Swift 4中合并两个视频遇问题:代码拼接后黑屏且丢失音频
Fixing Video Merging: Black Screen Gaps & Missing Audio in AVMutableComposition
Hey there! Let's get your video merging working properly—those black screens and missing audio are easy fixes once you spot the issues in your code. Here's what's going wrong and how to fix it:
Key Issues in Your Current Code
- Black Screen Overlap: You're inserting both videos starting at
kCMTimeZero, which means they're playing on top of each other. The black screen happens because the exporter handles this overlap incorrectly, or one video's duration doesn't align with the other. - Missing Audio: You only created a mutable track for video—you never added any audio tracks from your source assets, so the exported video has no sound.
Corrected Code
Here's the updated version with fixes for both problems, plus safety checks to avoid unexpected crashes:
import AVFoundation func mergeVideos(firstVideoURL: URL, secondVideoURL: URL, outputURL: URL) { let composition = AVMutableComposition() // MARK: - Handle Video Tracks guard let videoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { print("Failed to create video track") return } let firstAsset = AVAsset(url: firstVideoURL) let secondAsset = AVAsset(url: secondVideoURL) guard let firstVideoAssetTrack = firstAsset.tracks(withMediaType: .video).first, let secondVideoAssetTrack = secondAsset.tracks(withMediaType: .video).first else { print("Could not retrieve video tracks from assets") return } do { // Insert first video at the start try videoTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: firstAsset.duration), of: firstVideoAssetTrack, at: .zero) // Insert second video RIGHT AFTER the first one ends (fixes black screen overlap) try videoTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: secondAsset.duration), of: secondVideoAssetTrack, at: firstAsset.duration) } catch { print("Error inserting video tracks: \(error.localizedDescription)") return } // MARK: - Handle Audio Tracks (fixes missing audio) guard let audioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { print("Failed to create audio track") return } guard let firstAudioAssetTrack = firstAsset.tracks(withMediaType: .audio).first, let secondAudioAssetTrack = secondAsset.tracks(withMediaType: .audio).first else { print("Could not retrieve audio tracks from assets") return } do { // Insert first audio track try audioTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: firstAsset.duration), of: firstAudioAssetTrack, at: .zero) // Insert second audio track after the first one ends try audioTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: secondAsset.duration), of: secondAudioAssetTrack, at: firstAsset.duration) } catch { print("Error inserting audio tracks: \(error.localizedDescription)") return } // MARK: - Export the Merged Video guard let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else { print("Failed to create export session") return } exporter.outputURL = outputURL exporter.outputFileType = .mp4 exporter.shouldOptimizeForNetworkUse = true exporter.exportAsynchronously { switch exporter.status { case .completed: print("Merge successful! Video saved to \(outputURL)") case .failed: print("Export failed: \(exporter.error?.localizedDescription ?? "Unknown error")") case .cancelled: print("Export cancelled") default: break } } } // Usage example: // let firstURL = URL(fileURLWithPath: "path/to/first.mp4") // let secondURL = URL(fileURLWithPath: "path/to/second.mp4") // let outputURL = URL(fileURLWithPath: "path/to/merged.mp4") // mergeVideos(firstVideoURL: firstURL, secondVideoURL: secondURL, outputURL: outputURL)
What Changed?
- Fixed Video Placement: The second video is now inserted at
firstAsset.durationinstead of.zero, so it plays right after the first video ends—no more overlap or black screens. - Added Audio Track Handling: We created a mutable audio track and inserted both source audio tracks, matching the timing of their respective video tracks.
- Added Safety Checks: We added
guardstatements to handle cases where tracks can't be retrieved or created, preventing unexpected crashes. - Improved Export Status Handling: We now check the exporter's status to report success, failure, or cancellation instead of just printing a vague "done?".
Just make sure your output URL is a valid file path (and that you have write permissions for that location) when you call the function!
内容的提问来源于stack exchange,提问作者Jack Crawford
相关产品推荐
相关产品推荐

