- (void)merge{
// 視頻源路徑
_videoPath = @"/Users/liter/Desktop/IMG_2546.m4v";
// 新視頻路徑
_path = @"/Users/liter/Desktop/123.m4v";
// 讀
[self setupAssetReader];
// 寫
[self setupAssetWriter];
// 讀其他視頻 的音頻
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:@"/Users/liter/Desktop/IMG_2545.m4v"] options:nil];
AVAssetReader *readerTwo = [[AVAssetReader alloc] initWithAsset:asset error:nil];
AVAssetTrack *audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject];
NSDictionary *dic = @{AVFormatIDKey :@(kAudioFormatLinearPCM),
AVLinearPCMIsBigEndianKey:@NO,
AVLinearPCMIsFloatKey:@NO,
AVLinearPCMBitDepthKey :@(16)
};
AVAssetReaderTrackOutput *trackOutputTwo = [[AVAssetReaderTrackOutput alloc]initWithTrack:audioTrack outputSettings:dic];
[readerTwo addOutput:trackOutputTwo];
//音頻的一些配置包括音頻各種這里為AAC,音頻通道、采樣率和音頻的比特率
NSDictionary *audioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
[ NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[ NSNumber numberWithFloat: 44100], AVSampleRateKey,
[ NSNumber numberWithInt: 128000], AVEncoderBitRateKey,
nil];
//初始化音頻寫入類
AVAssetWriterInput *audioInputTwo = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:audioSettings];
//表明輸入是否應該調整其處理為實時數據源的數據
audioInputTwo.expectsMediaDataInRealTime = YES;
//將音頻輸入源加入
[_assetWriter addInput:audioInputTwo];
// 加入 額外的 音頻
[readerTwo startReading];
[_reader startReading];
[_assetWriter startWriting];
[_assetWriter startSessionAtSourceTime:kCMTimeZero];
NSLog(@"開始");
while ([_reader status] == AVAssetReaderStatusReading ) {
CMSampleBufferRef videoBuffer = [_videoReaderOutput copyNextSampleBuffer];
CMSampleBufferRef audioBuffer = [_audioReaderOutput copyNextSampleBuffer];
CMSampleBufferRef audioBufferTwo = [trackOutputTwo copyNextSampleBuffer];
// buffer 轉圖片
UIImage *image = [self imageFromSampleBuffer:videoBuffer];
if (image == nil) {
continue;
}
// 在這可對這一幀圖片 做處理
// UIImage *newImage = [self addFiliterFrom:image filiterImage:_filiterImage];
// 轉回可寫入的buffer
CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:[image CGImage] size:CGSizeMake(image.size.width, image.size.height)];
if (buffer)
{
while (!_videoInput.isReadyForMoreMediaData || !_audioInput.isReadyForMoreMediaData || !audioInputTwo.isReadyForMoreMediaData) {
usleep(1);
}
CMTime startTime = CMSampleBufferGetPresentationTimeStamp(videoBuffer);
if (audioBuffer) {
[_audioInput appendSampleBuffer:audioBuffer];
[audioInputTwo appendSampleBuffer:audioBufferTwo];
}
if(![_adaptor appendPixelBuffer:buffer withPresentationTime:startTime])
NSLog(@"FAIL");
CFRelease(buffer);
}
}
// [readerTwo cancelReading];
// __weak JBAssetReader *weakSelf = self;
[_assetWriter finishWritingWithCompletionHandler:^{
NSLog(@"完成");
// if (weakSelf.delegate) {
// [weakSelf.delegate videoPath:_path];
// }
}];
NSLog(@"...");
}
- (void)setupAssetReader {
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:_videoPath] options:nil];
_reader = [[AVAssetReader alloc] initWithAsset:asset error:nil];
AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
int m_pixelFormatType = kCVPixelFormatType_32BGRA;
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:@(m_pixelFormatType) forKey:(id)kCVPixelBufferPixelFormatTypeKey];
_videoReaderOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:videoTrack outputSettings:options];
[_reader addOutput:_videoReaderOutput];
AVAssetTrack *audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject];
NSDictionary *dic = @{AVFormatIDKey :@(kAudioFormatLinearPCM),
AVLinearPCMIsBigEndianKey:@NO,
AVLinearPCMIsFloatKey:@NO,
AVLinearPCMBitDepthKey :@(16)
};
_audioReaderOutput = [[AVAssetReaderTrackOutput alloc]initWithTrack:audioTrack outputSettings:dic];
[_reader addOutput:_audioReaderOutput];
}
- (void)setupAssetWriter {
_assetWriter = [AVAssetWriter assetWriterWithURL:[NSURL fileURLWithPath:_path] fileType:AVFileTypeMPEG4 error:nil];
[[NSFileManager defaultManager] removeItemAtPath:_path error:nil];
NSParameterAssert(_assetWriter);
//錄制視頻的一些配置,分辨率,編碼方式等等
NSDictionary* videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInteger: 480], AVVideoWidthKey,
[NSNumber numberWithInteger: 480], AVVideoHeightKey,
nil];
_videoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
_videoInput.expectsMediaDataInRealTime = YES;
NSParameterAssert(_videoInput);
NSParameterAssert([_assetWriter canAddInput:_videoInput]);
//將視頻輸入源加入
[_assetWriter addInput:_videoInput];
NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey, nil];
_adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:_videoInput
sourcePixelBufferAttributes:sourcePixelBufferAttributesDictionary];
//音頻的一些配置包括音頻各種這里為AAC,音頻通道、采樣率和音頻的比特率
NSDictionary *audioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
[ NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[ NSNumber numberWithFloat: 44100], AVSampleRateKey,
[ NSNumber numberWithInt: 128000], AVEncoderBitRateKey,
nil];
//初始化音頻寫入類
_audioInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:audioSettings];
//表明輸入是否應該調整其處理為實時數據源的數據
_audioInput.expectsMediaDataInRealTime = YES;
//將音頻輸入源加入
[_assetWriter addInput:_audioInput];
}