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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:39:37