思路1:使用AVAssertReader+AVAsserWriter读取Buffer,在采集视频的时候,一帧帧处理图像,以时间点对音视频做变速处理。
问题:因为如果使用时间点写入Buffer的话,是要创建AVAssetWriterInputPixelBufferAdaptor对象,但是这个对象只能对视频处理,暂时没有找到能以音频的时间点写入视频中,所以放弃了。
核心代码:
//通过这个方法写入数据
- (BOOL)encodeFrame:(CMSampleBufferRef) sampleBuffer isVideo:(BOOL)isVideo {
if (sampleBuffer == NULL)
{
NSLog(@"empty sampleBuffer");
return NO;
}
@autoreleasepool
{
if (CMSampleBufferDataIsReady(sampleBuffer)){
if (_writer.status == AVAssetWriterStatusUnknown && isVideo){
startTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
//开始写入
[self.writer startWriting];
[self.writer startSessionAtSourceTime:kCMTimeZero];
}
//写入视频数据
if (isVideo)
{
if (self.videoInput.readyForMoreMediaData)
{
CMTime pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
pts = CMTimeSubtract(pts, startTime);
pts = CMTimeMultiplyByFloat64(pts, 1);
CVImageBufferRef CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
[self.videoAdaptor appendPixelBuffer:CVPixelBuffer withPresentationTime:pts];
NSLog(@"==%f",CMTimeGetSeconds(pts));
}
}else{
//写入音频数据
if (self.audioInput.readyForMoreMediaData)
{
// BOOL success = [self.audioInput appendSampleBuffer:sampleBuffer];
// if (!success)
// {
// return NO;
// }
}
}
}
}
return YES;
}
思路2:AVFoundation中的AVMutableCompositionTrack对象,这个对象可以控制资源轨道插入时间点和时长,所以我认为这种方式应该能做变速处理,研究了下,最终找到一个方法scaleTimeRange...toDuration...,这种方式是对视频文件处理,但是抖音的功能是在采集完成后,能直接播放变速好的视频,所以可以在采集完成后,利用AVPlayer变速播放,后续再对视频文件做变速处理。
核心代码:
//视频轨道容器
AVMutableCompositionTrack* videoCompositionTrack = [mix addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack* audioCompositionTrack = [mix addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,asset.duration) ofTrack:videoTrack atTime:atTime error:nil];
[audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:audioTrack atTime:atTime error:nil];
//视频变速
[videoCompositionTrack scaleTimeRange:CMTimeRangeMake(kCMTimeZero,asset.duration) toDuration:CMTimeMake(asset.duration.value * rate , asset.duration.timescale)];
//音频变速
[audioCompositionTrack scaleTimeRange:CMTimeRangeMake(kCMTimeZero,asset.duration) toDuration:CMTimeMake(asset.duration.value * rate , asset.duration.timescale)];
AVPLayer播放变速:
https://github.com/qw9685/rateVideo