如何解决使用 iphone 4s、ipad 2 以 60fps 录制视频时出现的问题?
Posted
技术标签:
【中文标题】如何解决使用 iphone 4s、ipad 2 以 60fps 录制视频时出现的问题?【英文标题】:How to resolve the issue while recording a video at 60fps with iphone 4s, ipad 2? 【发布时间】:2014-09-16 11:58:29 【问题描述】:简而言之:
尝试以 59fps 录制时出现异常。如何解决?
2014-09-16 15:16:27.740 RosyWriter[2294:60b] ** 终止应用程序到期 未捕获的异常'NSInvalidArgumentException',原因:' 接收方不支持传递的 activeVideoMaxFrameDuration 主动格式。使用 -activeFormat.videoSupportedFrameRateRanges 来 发现有效范围。
详细我的问题:
我想做什么?
尝试以 30+ fps(60 fps 或更高 fps)录制视频。
到目前为止我尝试了什么?
-
最初尝试使用“AVCaptureConnection”的属性如下,后来了解到我使用的属性已被贬值。
AVCaptureConnection *conn = [output connectionWithMediaType:AVMediaTypeVideo];
CMTimeShow(conn.videoMinFrameDuration);
CMTimeShow(conn.videoMaxFrameDuration);
if (conn.isVideoMinFrameDurationSupported)
conn.videoMinFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);
if (conn.isVideoMaxFrameDurationSupported)
conn.videoMaxFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);
参考: 根据头文件(AVCaptureSession.h),
此属性在 ios 上已弃用,其中最小和最大帧速率调整仅在使用 activeVideoMinFrameDuration 和 activeVideoMaxFrameDuration 属性的 AVCaptureDevice 上应用。
然后,我尝试使用“AVCaptureDevice”如下:
-(void)setupCaptureSession
if ( _captureSession )
return;
_captureSession = [[AVCaptureSession alloc] init];
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
....................................
....................................
_videoConnection = [videoOut connectionWithMediaType:AVMediaTypeVideo];
int frameRate;
NSString *sessionPreset = AVCaptureSessionPreset640x480;
CMTime frameDuration = kCMTimeInvalid;
// For single core systems like iPhone 4 and iPod Touch 4th Generation wI
//use a lower resolution and framerate to maintain real-time performance.
if ( [[NSProcessInfo processInfo] processorCount] == 1 )
if ( [_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720] )
sessionPreset = AVCaptureSessionPreset1280x720;
frameRate = 59;
else
// USE_GPU_RENDERER is set in the project's build settings
#if ! use_gpu_renderer
// When using the CPU renderer we lower the resolution to 720p so that all devices can maintain real-time performance (this is primarily for A5 based devices like iPhone 4s and iPod Touch 5th Generation).
if ( [_captureSession canSetSessionPreset:AVCaptureSessionPreset640x480] )
sessionPreset = AVCaptureSessionPreset640x480;
#endif // ! use_gpu_renderer
frameRate = 59;
_captureSession.sessionPreset = sessionPreset;
frameDuration = CMTimeMake( 1, frameRate );
NSError *error = nil;
if ( [videoDevice lockForConfiguration:&error] )
videoDevice.activeFormat = bestFormat;
[**videoDevice setActiveVideoMaxFrameDuration:frameDuration];
[videoDevice setActiveVideoMinFrameDuration:frameDuration**];
[videoDevice unlockForConfiguration];
else
NSLog(@"videoDevice lockForConfiguration returned error %@", error);
self.videoOrientation = [_videoConnection videoOrientation];
[videoOut release];
return;
我的问题:
-
我遇到了异常
2014-09-16 15:16:27.740 RosyWriter[2294:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The activeVideoMaxFrameDuration passed is not supported by the receiver's active format. Use -activeFormat.videoSupportedFrameRateRanges to discover valid ranges.'
*** First throw call stack:
(0x2da2ff83 0x385d2ccf 0x2c919e4f 0xb4c7d 0xb4317 0x38aba81f 0x38ac07cb 0xb42b1 0xb2539 0x302676df 0x30258e89 0x3025864d 0x302584bf 0x30257fe5 0x30255827 0x302bf33d 0x302bbfad 0x302b656b 0x302526e9 0x30251851 0x302b5ca9 0x3288baed 0x3288b6d7 0x2d9faa67 0x2d9faa03 0x2d9f91d7 0x2d963ebf 0x2d963ca3 0x302b4ed1 0x302b014d 0xb1b4d 0x38adfab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
我在这里做错了吗?
后来,我把代码改成了
AVCaptureDeviceFormat *bestFormat = nil;
AVFrameRateRange *bestFrameRateRange = nil;
for ( AVCaptureDeviceFormat *format in [videoDevice formats] )
for ( AVFrameRateRange *range in format.videoSupportedFrameRateRanges )
if ( range.maxFrameRate > bestFrameRateRange.maxFrameRate )
bestFormat = format;
bestFrameRateRange = range;
NSError *error = nil;
if ( bestFormat )
if ( [videoDevice lockForConfiguration:&error] )
videoDevice.activeFormat = bestFormat;
videoDevice.activeVideoMinFrameDuration = bestFrameRateRange.minFrameDuration;
videoDevice.activeVideoMaxFrameDuration = bestFrameRateRange.maxFrameDuration;
[videoDevice unlockForConfiguration];
但是我得到的视频是用 bestFrameRateRange 以 30fps 录制的,但不是 59fps..
【问题讨论】:
也许,这些设备不支持,这就是您遇到异常的原因?也许这条线videoDevice.activeVideoMaxFrameDuration = bestFrameRateRange.minFrameDuration;
应该是videoDevice.activeVideoMaxFrameDuration = bestFrameRateRange.maxFrameDuration;
?
感谢您的输入。我更正了您在代码 sn-p 中记录的拼写错误。然而,许多开发者已经在旧的苹果设备上实现了 60fps。根据我的分析,我希望它可能......
另一个错字:videoDevice.activeVideoMinFrameDuration = bestFrameRateRange.maxFrameDuration; videoDevice.activeVideoMaxFrameDuration = bestFrameRateRange.minFrameDuration;
,在您的代码中,最小值是最大值,最大值是最小值。
【参考方案1】:
这是一个如何使用更高帧速率的工作示例:
查找并设置活动模式以使用可用的最大帧速率。
float maxFrameRate = 0.0;
int maxIndex = 0;
for(int i=0;i<_videoCaptureDevice.formats.count;i++)
AVCaptureDeviceFormat *format = [_videoCaptureDevice.formats objectAtIndex:i];
AVFrameRateRange *frameRateRange = [format.videoSupportedFrameRateRanges firstObject];
//You can add hard coded checking for specific format like if(frameRateRange.maxFrameRate == 240) etc I am using the max one
if(maxFrameRate<frameRateRange.maxFrameRate)
maxFrameRate = frameRateRange.maxFrameRate;
maxIndex = i;
AVCaptureDeviceFormat *format = [_videoCaptureDevice.formats objectAtIndex:maxIndex];
AVFrameRateRange *frameRateRange = [format.videoSupportedFrameRateRanges firstObject];
[self.videoCaptureDevice lockForConfiguration:nil];
self.videoCaptureDevice.activeFormat = format;
self.videoCaptureDevice.activeVideoMinFrameDuration = frameRateRange.minFrameDuration;
self.videoCaptureDevice.activeVideoMaxFrameDuration = frameRateRange.maxFrameDuration;
[self.videoCaptureDevice unlockForConfiguration];
然后改变帧率
if(YourFrameRate<=frameRateRange.maxFrameRate && YourFrameRate>=frameRateRange.minFrameRate)
if([device lockForConfiguration:&error])
[device setActiveVideoMinFrameDuration:CMTimeMake(1, YourFrameRate)];
[device setActiveVideoMaxFrameDuration:CMTimeMake(1, YourFrameRate)];
[device unlockForConfiguration];
else
[self passError:error];
从here得到答案
【讨论】:
【参考方案2】:您应该将有效格式设置为AVCaptureDevice
。
你可以这样做
// get device what you like
let device = xxxxx
// list all default formats for this device
for format in device.formats
var founded = false
// check what you want and pick a perfect format.
let formatDesc = format.formatDescription
// mediaType / SubType
let mediaType = format.mediaSubType
// if your target is above(equal) iOS 13. use formatDesc.mediaSubType
let mediaSubType = CMFormatDescriptionGetMediaSubType(formatDesc)
// dimensions
// if your target is above(equal) iOS 13. use formatDesc.dimensions
let dimensions = CMVideoFormatDescriptionGetDimensions(formatDesc)
// fps
let ranges = format.videoSupportedFrameRateRanges.first
for supportedFPSRange in ranges
if supportedFPSRange.maxFrameRate == 60
founded = true
// support Multi cam
let isMultiCamSupported = format.isMultiCamSupported
....
if founded
// Set activeFormat for device! Your capture device is up and loaded.
do
try device.lockForConfiguration()
device.activeFormat = format
device.unlockForConfiguration()
catch
// catch some locking error
// Don't forget break the loop.:p
break
【讨论】:
以上是关于如何解决使用 iphone 4s、ipad 2 以 60fps 录制视频时出现的问题?的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS/Cordova/Phonegap Ipad 3 和 Iphone 4s 不够快?
如何将商店中的 iOS 应用程序限制为仅限 4S 和 iPad 3
如何设计 UI 以支持 iPhone 和 iPad 的所有屏幕