我有两个音轨,我就这样相互结合:
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:1.0];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:originalContentURL options:nil];
AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack1 setPreferredVolume:0.01];
NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:@"jingle1" ofType:@"m4a"];
NSURL *url1 = [NSURL fileURLWithPath:soundOne1];
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
AVAssetTrack *clipAudioTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack1 atTime:kCMTimeZero error:nil];
正如您所看到的,第一个AVAsset
是第二个音轨的基本长度,这意味着如果我有一个很长的第二个音轨,它将被剪切,这正是我想要的方式。
但是,我需要能够循环第二个曲目,这样如果第一个一个太长,第二个曲目会一直亮着。我后来不得不将最终的曲目保存在光盘上,这也是一个重要的因素。
经过一项研究,我发现我发现没有方便的方法在iOS中实际循环播放曲目。其中一种方法是在AVMutableComposition
多次反复插入第二首曲目,但这对我来说听起来很奇怪。任何基于该主题的想法都非常有用。
答案 0 :(得分:7)
我认为它应该有效:
CMTime videoDuration = avAsset.duration;
if(CMTimeCompare(videoDuration, audioAsset.duration) == -1){
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack1 atTime:kCMTimeZero error:nil];
}else if(CMTimeCompare(videoDuration, audioAsset.duration) == 1){
CMTime currentTime = kCMTimeZero;
while(YES){
CMTime audioDuration = audioAsset.duration;
CMTime totalDuration = CMTimeAdd(currentTime,audioDuration);
if(CMTimeCompare(totalDuration, videoDuration)==1){
audioDuration = CMTimeSubtract(totalDuration,videoDuration);
}
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioDuration) ofTrack:clipAudioTrack1 atTime:currentTime error:nil];
currentTime = CMTimeAdd(currentTime, audioDuration);
if(CMTimeCompare(currentTime, videoDuration) == 1 || CMTimeCompare(currentTime, videoDuration) == 0){
break;
}
}
}
答案 1 :(得分:6)
关于Gaurav的回应你应该改变这一行:
audioDuration = CMTimeSubtract(totalDuration,videoDuration);
于:
audioDuration = CMTimeSubtract(videoDuration,currentTime);
否则录音带会比视频长(只是黑色)
答案 2 :(得分:1)
通过repeat whiel
循环快速浏览。
修复视频长度问题
let audioLength = CMTime(value: 100, timescale: 1)
let videoLength = CMTime(value: 220, timescale: 1)
func getAudioRepeatInfo(audioLength:CMTime, videoLength:CMTime) -> [(at:CMTime, duration:CMTime)] {
var at = [(at:CMTime, duration:CMTime)](), start = CMTime.zero
repeat {
let info = (at:start, duration: min(CMTimeSubtract(videoLength, start), audioLength) )
at.append(info)
start = CMTimeAdd(start, info.duration)
} while start < videoLength
return at
}
var ranges = getAudioRepeatInfo(audioLength: audioLength, videoLength: videoLength)
游乐场输出:
[(at: __C.CMTime(value: 0, timescale: 1, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0), duration: __C.CMTime(value: 100, timescale: 1, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0)),
(at: __C.CMTime(value: 100, timescale: 1, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0), duration: __C.CMTime(value: 100, timescale: 1, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0)),
(at: __C.CMTime(value: 200, timescale: 1, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0), duration: __C.CMTime(value: 20, timescale: 1, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0))]
使用:
for info in repeatInfo {
try compositionAudioTrack1?.insertTimeRange(.init(start: .zero, duration: info.duration), of: assetTrack, at: info.at)
}