Xamarin中使用CMTime设置AVUrlAsset的CMTimeRange.Start参数
解决自定义音频从指定位置开始与视频合并的问题
嘿,我刚好碰到过类似的需求,这就给你捋清楚怎么用CMTime设置音频的起始播放位置!
核心思路
你的需求本质是:视频的起始帧要对应音频已经播放了N秒的位置,所以我们需要先记录下用户点击录制时音频已经播放的时长,再把这个时长转换成AVFoundation用的CMTime,最后在合并时指定音频的播放范围。
具体步骤
1. 记录音频已播放时长
当用户点击录制按钮时,先获取当前音频的播放进度(比如用AVAudioPlayer的currentTime),然后把这个秒数转换成CMTime:
// 假设你用AVAudioPlayer播放背景音乐 let audioPlayer: AVAudioPlayer = ... // 你的音频播放器实例 // 将已播放的秒数转为CMTime,timescale用600是AVFoundation常用的精度值,兼容性好 let elapsedAudioTime = CMTimeMakeWithSeconds(audioPlayer.currentTime, preferredTimescale: 600)
2. 定义音频的播放范围
接下来要确定音频需要截取的范围:起始点是刚才的elapsedAudioTime,时长则和你的视频时长一致(这样音频和视频同步结束)。
// 先获取视频的时长(假设你已经拿到了视频的AVAsset) let videoAsset: AVAsset = ... // 你的视频资源 let videoDuration = videoAsset.duration // 创建音频的时间范围:从已播放位置开始,时长等于视频时长 let audioPlayRange = CMTimeRange(start: elapsedAudioTime, duration: videoDuration)
⚠️ 这里要注意:如果音频剩余时长(音频总时长 - 已播放时长)小于视频时长,音频会提前结束,视频后半段会没有声音。你可以根据需求处理这种情况——比如循环音频、截断视频,或者提示用户音频不够长。
3. 用AVMutableComposition合并视频和音频
最后用AVMutableComposition把视频和音频轨道组合起来,重点是给音频轨道指定我们刚才创建的audioPlayRange:
let composition = AVMutableComposition() // 添加视频轨道 guard let videoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid) else { print("无法创建视频轨道") return } do { let sourceVideoTrack = videoAsset.tracks(withMediaType: .video).first! try videoTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoDuration), of: sourceVideoTrack, at: .zero) } catch { print("插入视频轨道失败:\(error)") return } // 添加音频轨道并指定起始位置 guard let audioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) else { print("无法创建音频轨道") return } let audioAsset: AVAsset = ... // 你的背景音乐资源 do { let sourceAudioTrack = audioAsset.tracks(withMediaType: .audio).first! // 关键:插入音频时指定我们定义的播放范围 try audioTrack.insertTimeRange(audioPlayRange, of: sourceAudioTrack, at: .zero) } catch { print("插入音频轨道失败:\(error)") return }
这样处理后,视频播放时,音频就会从用户点击录制时的进度点开始同步播放啦!
内容的提问来源于stack exchange,提问作者jaysonragasa
相关产品推荐
相关产品推荐

