iOS 17中RPSystemBroadcastPickerView录屏仅2秒自动停止问题
iOS 17录屏2秒自动停止问题排查与修复建议
现有代码在iOS 17以下设备可正常同时录制屏幕与音频,但在iOS 17设备上录屏仅2秒后自动停止。由于是扩展程序,无法获取日志进行调试,且同款代码在其他低版本iOS设备上运行正常。
初始化AVAssetWriter代码
@try { NSLog(@"initAssesWriter"); NSError *error = nil; CGRect screenRect = [[UIScreen mainScreen] bounds]; _videoWriter = [[AVAssetWriter alloc] initWithURL: _filePath fileType:AVFileTypeMPEG4 error:&error]; NSParameterAssert(_videoWriter); //Configure video NSDictionary* videoCompressionProps = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithDouble:2048*1024.0], AVVideoAverageBitRateKey, nil ]; NSDictionary* videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecTypeH264, AVVideoCodecKey, [NSNumber numberWithInt:screenRect.size.width * 4], AVVideoWidthKey, [NSNumber numberWithInt:screenRect.size.height * 4], AVVideoHeightKey, videoCompressionProps, AVVideoCompressionPropertiesKey, nil]; _writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] ; _writerInput.expectsMediaDataInRealTime = YES; NSParameterAssert(_writerInput); NSParameterAssert([_videoWriter canAddInput:_writerInput]); [_videoWriter addInput:_writerInput]; AudioChannelLayout acl; bzero( &acl, sizeof(acl)); acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; NSDictionary* audioOutputSettings = [NSDictionary dictionaryWithObjectsAndKeys: [ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey, [ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey, [ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey, [ NSData dataWithBytes: &acl length: sizeof( AudioChannelLayout ) ], AVChannelLayoutKey, [ NSNumber numberWithInt: 64000 ], AVEncoderBitRateKey, nil]; _audioWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeAudio outputSettings: audioOutputSettings ]; _audioWriterInput.expectsMediaDataInRealTime = YES; // seems to work slightly better NSParameterAssert(_audioWriterInput); NSParameterAssert([_videoWriter canAddInput:_audioWriterInput]); [_videoWriter addInput:_audioWriterInput]; [_videoWriter setMovieFragmentInterval:CMTimeMake(1, 600)]; [_videoWriter startWriting]; } @catch (NSException *exception) { } @finally { }
处理SampleBuffer代码
-(void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType{ @try { if(!_isRecordingStarted){ [_videoWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)]; _isRecordingStarted = YES; [self saveFlurryLogs:@"Assest writer Start Recording" Details:@""]; NSLog(@"CMSampleBufferGetPresentationTimeStamp"); } } @catch (NSException *exception) { [self saveFlurryLogs:@"Recording Start Execption" Details:exception.description]; } @finally { } @try { switch (sampleBufferType) { case RPSampleBufferTypeVideo: // Handle video sample buffer if([_writerInput isReadyForMoreMediaData]){ [_writerInput appendSampleBuffer:sampleBuffer]; NSLog(@"writing matadata Video"); } break; case RPSampleBufferTypeAudioApp: // Handle audio sample buffer for app audio break; case RPSampleBufferTypeAudioMic: if([_audioWriterInput isReadyForMoreMediaData]){ [_audioWriterInput appendSampleBuffer:sampleBuffer]; NSLog(@"writing matadata Audio"); } // Handle audio sample buffer for mic audio break; default: break; } } @catch (NSException *exception) { [self saveFlurryLogs:@"Packet Write Execption" Details:exception.description]; } @finally { } }
修复建议
- 捕获AVAssetWriter错误信息:扩展环境下虽然无法直接查看NSLog,但可以通过
_videoWriter.error获取具体错误,将错误信息通过你已有的saveFlurryLogs方法上报,或者写入本地文件,这是定位问题的关键。 - 补全App音频处理分支:当前代码忽略了
RPSampleBufferTypeAudioApp类型的样本,如果你的录制包含App音频,iOS 17会因音频输入长时间无数据而终止录制。需要补上该分支的处理:
case RPSampleBufferTypeAudioApp: if([_audioWriterInput isReadyForMoreMediaData]){ [_audioWriterInput appendSampleBuffer:sampleBuffer]; } break;
- 修正视频分辨率设置:直接使用屏幕原生像素尺寸,避免固定乘以4导致的分辨率异常,替换为:
CGRect screenBounds = [[UIScreen mainScreen] nativeBounds]; // 后续用screenBounds.size.width和height作为视频宽高
- 调整Movie Fragment Interval:尝试注释掉
[_videoWriter setMovieFragmentInterval:CMTimeMake(1, 600)],或者将间隔调整为CMTimeMake(1, 30),iOS 17对该参数的兼容性可能有变化。 - 优化会话启动时机:优先等待第一个视频样本到来时再启动录制会话,避免因先收到音频样本导致视频后续跟不上触发超时:
@try { switch (sampleBufferType) { case RPSampleBufferTypeVideo: if(!_isRecordingStarted){ [_videoWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)]; _isRecordingStarted = YES; [self saveFlurryLogs:@"Assest writer Start Recording" Details:@""]; } if([_writerInput isReadyForMoreMediaData]){ [_writerInput appendSampleBuffer:sampleBuffer]; } break; // 其他分支... } }
内容的提问来源于stack exchange,提问作者user1115985
相关产品推荐
相关产品推荐

