最近在做直播內(nèi)錄制視頻分享的功能烧栋,便嘗試使用了ReplayKit,期間遇到一些問題拳球,在這里記錄下來审姓。
在嘗試過程中,遇到兩種場(chǎng)景:
場(chǎng)景1
- 開啟 AVAssetWriter (包含 Audio / Video Writer Input)
- 使用RPScreenRecorder開始錄制(不啟動(dòng)Microphone)
- 錄制成功并成功獲得視頻
場(chǎng)景2
- 開啟 AVAssetWriter (包含 Audio / Video Writer Input)
- 使用RPScreenRecorder開始錄制(啟動(dòng)Microphone)
- 錄制失敗
針對(duì)第二種情況祝峻,網(wǎng)上相應(yīng)的解決方案很少(不知道是不是只有我遇到了)魔吐。所以在經(jīng)過n次google(stackoverflow上的解決方案)和自己嘗試之后,終于成功解決莱找。下面是我的代碼
if (openMic) {
[RPScreenRecorder sharedRecorder].microphoneEnabled = YES;
} else {
[RPScreenRecorder sharedRecorder].microphoneEnabled = NO;
}
[self.videoWriter startWriting];
__weak typeof(self) weakSelf = self;
[[RPScreenRecorder sharedRecorder] startCaptureWithHandler:^(CMSampleBufferRef _Nonnull sampleBuffer,RPSampleBufferType bufferType, NSError *_Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!CMSampleBufferDataIsReady(sampleBuffer)) {
return;
}
if (strongSelf.videoWriter.status == AVAssetWriterStatusFailed) {
NSLog(@"[錄屏]AVAssetWriterStatusFailed");
return;
}
if (strongSelf.videoWriter.status == AVAssetWriterStatusWriting) {
if (bufferType == RPSampleBufferTypeVideo) {
if (!strongSelf.startedSession) {
[strongSelf.videoWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStam(sampleBuffer)];
strongSelf.startedSession = YES;
NSLog(@"[錄屏]開啟session 視頻處");
}
if (CMTimeCompare(kCMTimeInvalid, strongSelf.firstVideoFramTime) == 0) {
strongSelf.firstVideoFramTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
}
if ([strongSelf.videoWriterInput isReadyForMoreMediaData]) {
@try {
[strongSelf.videoWriterInput appendSampleBuffer:sampleBuffer];
NSLog(@"[錄屏]寫入視頻數(shù)據(jù)");
} @catch (NSException *exception) {
NSLog(@"[錄屏]寫入視頻數(shù)據(jù)失敗");
}
}
}
if (bufferType == RPSampleBufferTypeAudioApp || bufferType == RPSampleBufferTypeAudioMic) {
// 可以在這里做一些過濾操作
// if (onlyMicAudio && bufferType == RPSampleBufferTypeAudioApp) {
// return;
// }
if (CMTimeCompare(kCMTimeInvalid, strongSelf.firstVideoFramTime) == 0 || CMTimeCompar(strongSelf.firstVideoFramTime, CMSampleBufferGetPresentationTimeStamp(sampleBuffer)) == 1) {
return;
}
if (!strongSelf.startedSession) {
[strongSelf.videoWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStam(sampleBuffer)];
strongSelf.startedSession = YES;
NSLog(@"[錄屏]開啟session 音頻處");
}
if ([strongSelf.audioWriterInput isReadyForMoreMediaData]) {
@try {
[strongSelf.audioWriterInput appendSampleBuffer:sampleBuffer];
NSLog(@"[錄屏]寫入音頻數(shù)據(jù)");
} @catch (NSException *exception) {
NSLog(@"[錄屏]寫入音頻數(shù)據(jù)失敗");
}
}
}
}
} completionHandler:^(NSError *_Nullable error) {
}];
下面是 AVAssetWriter 和 AVAssetWriterInput 的配置(因?yàn)椴皇菍I(yè)的多媒體工程師酬姆,所以很多參數(shù)配置不一定合理,僅供大家參考)
- (void)setupVideoWriter
{
if (!_videoWriter) {
NSURL *outputURL = [NSURL fileURLWithPath:self.videoOutputPath];
NSError *error = nil;
_videoWriter = [AVAssetWriter assetWriterWithURL:outputURL fileType:AVFileTypeQuickTimeMovie error:&error];
if (error) {
NSLog(@"創(chuàng)建Video Writer失敯履纭:%@", [error localizedDescription]);
}
}
}
- (void)setupVideoWriterInput
{
if (!_videoWriterInput) {
CGFloat scale = [UIScreen mainScreen].scale;
CGSize size = CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds) * scale, CGRectGetHeight([UIScreen mainScreen].bounds) * scale);
NSDictionary *copressionProperties = @{ AVVideoAverageBitRateKey : @(1200 * 1024) };
_videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:@{
AVVideoCodecKey : AVVideoCodecH264,
AVVideoWidthKey : @(size.width),
AVVideoHeightKey : @(size.height),
AVVideoCompressionPropertiesKey : copressionProperties
}];
_videoWriterInput.expectsMediaDataInRealTime = YES;
if ([self.videoWriter canAddInput:_videoWriterInput]) {
[self.videoWriter addInput:_videoWriterInput];
} else {
NSLog(@"無法添加Video Writer Input");
}
}
}
- (void)setupAudioWriterInput
{
if (!_audioWriterInput) {
AudioChannelLayout acl;
bzero(&acl, sizeof(acl));
acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
_audioWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
outputSettings:@{
AVSampleRateKey : @(44100),
AVFormatIDKey : @(kAudioFormatAppleLossless),
AVEncoderBitDepthHintKey : @(16),
AVNumberOfChannelsKey : @(1),
AVChannelLayoutKey : [NSData dataWithBytes:&acl length:sizeof(acl)],
}];
_audioWriterInput.expectsMediaDataInRealTime = YES;
if ([self.videoWriter canAddInput:_audioWriterInput]) {
[self.videoWriter addInput:_audioWriterInput];
} else {
NSLog(@"無法添加Video Writer Input");
}
}
}