Replaykit, startCaptureWithHandler () não está enviando CMSampleBufferRef do tipo de vídeo em captureHandler
Eu implementei umRPScreenRecorder
, que grava a tela e o áudio do microfone. Após a conclusão de várias gravações, paro a gravação e mesclo os áudios com os vídeos usandoAVMutableComposition
e depois Mesclar todos os vídeos para formar um vídeo único.
Para gravar a tela e obter os arquivos de vídeo e áudio, estou usando
- (void)startCaptureWithHandler:(nullable void(^)(CMSampleBufferRef sampleBuffer, RPSampleBufferType bufferType, NSError * _Nullable error))captureHandler completionHandler:
Para parar a gravação. Eu chamo esta função:
- (void)stopCaptureWithHandler:(void (^)(NSError *error))handler;
E estes são bastante simples.
Na maioria das vezes funciona muito bem, recebo CMSampleBuffers de vídeo e áudio. Mas algumas vezes acontece questartCaptureWithHandler
só me envia buffers de áudio, mas não de vídeo. E quando encontrar esse problema, ele não será até reiniciar o dispositivo e reinstalar o aplicativo. Isso torna meu aplicativo tão confiável para o usuário. Acho que esse é um problema do kit de repetição, mas não foi possível descobrir problemas relacionados com outros desenvolvedores. deixe-me saber se algum de vocês se deparou com esse problema e conseguiu a solução.
Eu verifiquei várias vezes, mas não vi nenhum problema na configuração. Mas aqui está, de qualquer forma.
NSError *videoWriterError;
videoWriter = [[AVAssetWriter alloc] initWithURL:fileString fileType:AVFileTypeQuickTimeMovie
error:&videoWriterError];
NSError *audioWriterError;
audioWriter = [[AVAssetWriter alloc] initWithURL:audioFileString fileType:AVFileTypeAppleM4A
error:&audioWriterError];
CGFloat width =UIScreen.mainScreen.bounds.size.width;
NSString *widthString = [NSString stringWithFormat:@"%f", width];
CGFloat height =UIScreen.mainScreen.boNSString *heightString = [NSString stringWithFormat:@"%f", height];unds.size.height;
NSDictionary * videoOutputSettings= @{AVVideoCodecKey : AVVideoCodecTypeH264,
AVVideoWidthKey: widthString,
AVVideoHeightKey : heightString};
videoInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:videoOutputSettings];
videoInput.expectsMediaDataInRealTime = true;
AudioChannelLayout acl;
bzero( &acl, sizeof(acl));
acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
NSDictionary * audioOutputSettings = [ NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithInt: kAudioFormatAppleLossless ], AVFormatIDKey,
[ NSNumber numberWithInt: 16 ], AVEncoderBitDepthHintKey,
[ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey,
[ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey,
[ NSData dataWithBytes: &acl length: sizeof( acl ) ], AVChannelLayoutKey,
nil ];
audioInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:audioOutputSettings];
[audioInput setExpectsMediaDataInRealTime:YES];
[videoWriter addInput:videoInput];
[audioWriter addInput:audioInput];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
[RPScreenRecorder.sharedRecorder startCaptureWithHandler:^(CMSampleBufferRef _Nonnull sampleBuffer, RPSampleBufferType bufferType, NSError * _Nullable myError) {
Block
}
A função startCaptureWithHandler também possui uma funcionalidade bastante direta:
[RPScreenRecorder.sharedRecorder startCaptureWithHandler:^(CMSampleBufferRef _Nonnull sampleBuffer, RPSampleBufferType bufferType, NSError * _Nullable myError) {
dispatch_sync(dispatch_get_main_queue(), ^{
if(CMSampleBufferDataIsReady(sampleBuffer))
{
if (self->videoWriter.status == AVAssetWriterStatusUnknown)
{
self->writingStarted = true;
[self->videoWriter startWriting];
[self->videoWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
[self->audioWriter startWriting];
[self->audioWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
}
if (self->videoWriter.status == AVAssetWriterStatusFailed) {
return;
}
if (bufferType == RPSampleBufferTypeVideo)
{
if (self->videoInput.isReadyForMoreMediaData)
{
[self->videoInput appendSampleBuffer:sampleBuffer];
}
}
else if (bufferType == RPSampleBufferTypeAudioMic)
{
// printf("\n+++ bufferAudio received %d \n",arc4random_uniform(100));
if (writingStarted){
if (self->audioInput.isReadyForMoreMediaData)
{
[self->audioInput appendSampleBuffer:sampleBuffer];
}
}
}
}
});
}
Além disso, quando essa situação ocorre, o gravador de tela do sistema também é corrompido. Ao clicar no gravador do sistema, este erro aparece:
O erro indica "A gravação da tela foi interrompida devido a: Falha durante a gravação devido ao erro do Mediaservices".
Deve haver dois motivos:
O kit de reprodução do iOS está na versão beta, e é por isso que está dando problemas após algumas vezes de uso.Eu implementei qualquer lógica problemática, que causa o travamento do replaykit.Se é problema não. 1, então não há problema. Se este for o problema não. 2 então eu tenho que saber onde posso estar errado?
Opiniões e ajuda serão apreciadas.