- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
让我看看我是否理解正确。
在目前最先进的硬件上,iOS 允许我以以下 fps 进行录制:30、60、120 和 240。
但是这些 fps 的行为不同。如果我以 30 或 60 fps 拍摄,我希望以这些 fps 拍摄创建的视频文件分别以 30 和 60 fps 播放。
但如果我以 120 或 240 fps 拍摄,我希望以这些 fps 拍摄创建的视频文件以 30 fps 播放,否则我将看不到慢动作。
几个问题:
我正在像这样创建 AVAssetWriter 输入...
NSDictionary *videoCompressionSettings = @{AVVideoCodecKey : AVVideoCodecH264,
AVVideoWidthKey : @(videoWidth),
AVVideoHeightKey : @(videoHeight),
AVVideoCompressionPropertiesKey : @{ AVVideoAverageBitRateKey : @(bitsPerSecond),
AVVideoMaxKeyFrameIntervalKey : @(1)}
};
_assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoCompressionSettings];
并且没有明显的方法来控制它。
注意:我在 1
所在的位置尝试了不同的数字。我试过 1.0/fps
,我试过 fps
,我已经删除了 key 。没有区别。
这就是我设置 `AVAssetWriter 的方式:
AVAssetWriter *newAssetWriter = [[AVAssetWriter alloc] initWithURL:_movieURL fileType:AVFileTypeQuickTimeMovie
error:&error];
_assetWriter = newAssetWriter;
_assetWriter.shouldOptimizeForNetworkUse = NO;
CGFloat videoWidth = size.width;
CGFloat videoHeight = size.height;
NSUInteger numPixels = videoWidth * videoHeight;
NSUInteger bitsPerSecond;
// Assume that lower-than-SD resolutions are intended for streaming, and use a lower bitrate
// if ( numPixels < (640 * 480) )
// bitsPerPixel = 4.05; // This bitrate matches the quality produced by AVCaptureSessionPresetMedium or Low.
// else
NSUInteger bitsPerPixel = 11.4; // This bitrate matches the quality produced by AVCaptureSessionPresetHigh.
bitsPerSecond = numPixels * bitsPerPixel;
NSDictionary *videoCompressionSettings = @{AVVideoCodecKey : AVVideoCodecH264,
AVVideoWidthKey : @(videoWidth),
AVVideoHeightKey : @(videoHeight),
AVVideoCompressionPropertiesKey : @{ AVVideoAverageBitRateKey : @(bitsPerSecond)}
};
if (![_assetWriter canApplyOutputSettings:videoCompressionSettings forMediaType:AVMediaTypeVideo]) {
NSLog(@"Couldn't add asset writer video input.");
return;
}
_assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoCompressionSettings
sourceFormatHint:formatDescription];
_assetWriterVideoInput.expectsMediaDataInRealTime = YES;
NSDictionary *adaptorDict = @{
(id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA),
(id)kCVPixelBufferWidthKey : @(videoWidth),
(id)kCVPixelBufferHeightKey : @(videoHeight)
};
_pixelBufferAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc]
initWithAssetWriterInput:_assetWriterVideoInput
sourcePixelBufferAttributes:adaptorDict];
// Add asset writer input to asset writer
if (![_assetWriter canAddInput:_assetWriterVideoInput]) {
return;
}
[_assetWriter addInput:_assetWriterVideoInput];
captureOutput
方法非常简单。我从过滤器中获取图像并使用以下方法将其写入文件:
if (videoJustStartWriting)
[_assetWriter startSessionAtSourceTime:presentationTime];
CVPixelBufferRef renderedOutputPixelBuffer = NULL;
OSStatus err = CVPixelBufferPoolCreatePixelBuffer(nil,
_pixelBufferAdaptor.pixelBufferPool,
&renderedOutputPixelBuffer);
if (err) return; // NSLog(@"Cannot obtain a pixel buffer from the buffer pool");
//_ciContext is a metal context
[_ciContext render:finalImage
toCVPixelBuffer:renderedOutputPixelBuffer
bounds:[finalImage extent]
colorSpace:_sDeviceRgbColorSpace];
[self writeVideoPixelBuffer:renderedOutputPixelBuffer
withInitialTime:presentationTime];
- (void)writeVideoPixelBuffer:(CVPixelBufferRef)pixelBuffer withInitialTime:(CMTime)presentationTime
{
if ( _assetWriter.status == AVAssetWriterStatusUnknown ) {
// If the asset writer status is unknown, implies writing hasn't started yet, hence start writing with start time as the buffer's presentation timestamp
if ([_assetWriter startWriting]) {
[_assetWriter startSessionAtSourceTime:presentationTime];
}
}
if ( _assetWriter.status == AVAssetWriterStatusWriting ) {
// If the asset writer status is writing, append sample buffer to its corresponding asset writer input
if (_assetWriterVideoInput.readyForMoreMediaData) {
if (![_pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:presentationTime]) {
NSLog(@"error", [_assetWriter.error localizedFailureReason]);
}
}
}
if ( _assetWriter.status == AVAssetWriterStatusFailed ) {
NSLog(@"failed");
}
}
我将整件事以 240 fps 的速度拍摄。这些是附加帧的呈现时间。
time ======= 113594.311510508
time ======= 113594.324011508
time ======= 113594.328178716
time ======= 113594.340679424
time ======= 113594.344846383
如果您对它们进行一些计算,您会发现帧速率约为 240 fps。因此,帧以正确的时间存储。
但是当我看视频时,运动不是慢动作,而是快时间说视频是 30 fps。
注意:此应用从相机抓取帧,帧进入 CIFilters,这些过滤器的结果被转换回存储到文件并显示在屏幕上的样本缓冲区。
最佳答案
我到了这里,但我认为这是你出错的地方。将您的视频捕获视为管道。
(1) Capture buffer -> (2) Do Something With buffer -> (3) Write buffer as frames in video.
听起来您已经成功完成了 (1) 和 (2),您获得缓冲区的速度足够快并且正在处理它们,以便您可以将它们作为帧出售。
几乎可以肯定问题出在 (3) 写入视频帧中。
https://developer.apple.com/reference/avfoundation/avmutablevideocomposition
检查您的 AVMutableComposition 中的 frameDuration 设置,您需要像 CMTime(1, 60)//60FPS 或 CMTime(1, 240)//240FPS 这样的东西来获得您想要的(告诉视频写入这么多帧并以此速率编码)。
使用 AVAssetWriter,原理完全相同,但您将帧速率设置为 AVAssetWriterInput outputSettings 中的一个属性,添加了 AVVideoExpectedSourceFrameRateKey。
NSDictionary *videoCompressionSettings = @{AVVideoCodecKey : AVVideoCodecH264,
AVVideoWidthKey : @(videoWidth),
AVVideoHeightKey : @(videoHeight),
AVVideoExpectedSourceFrameRateKey : @(60),
AVVideoCompressionPropertiesKey : @{ AVVideoAverageBitRateKey : @(bitsPerSecond),
AVVideoMaxKeyFrameIntervalKey : @(1)}
};
进一步扩展 - 您无法严格控制或同步您的相机捕捉到输出/回放速率,时间不能那样工作,也不那么准确,当然还有处理管道增加开销。当您捕获帧时,它们带有时间戳,您已经看到了这一点,但在写入/压缩阶段,它仅使用它需要的帧来生成为合成指定的输出。
它是双向的,你可以只捕获 30 FPS 并以 240 FPS 输出,视频会显示正常,你只是有很多帧“丢失”并被算法填充。你甚至可以每秒只输出 1 帧并以 30FPS 播放,这两者是相互独立的(我捕获的速度与每秒显示的帧数和呈现的内容的速度)
至于如何以不同的速度播放它,你只需要调整播放速度 - 根据需要减慢它。
如果您正确设置了时基 (frameDuration),它将始终“正常”播放 - 您告诉它“播放是每秒 X 帧”,当然,您的眼睛可能会注意到差异(几乎可以肯定在低 FPS 和高 FPS 之间),并且屏幕可能不会刷新那么高(高于 60FPS),但无论视频将以其时基的“正常”1X 速度。通过放慢视频速度,如果我的时基是 120,我将它减慢到 0.5 倍,我知道有效地看到 60FPS,一秒的播放需要两秒。
您可以通过设置 AVPlayer 的速率属性来控制播放速度 https://developer.apple.com/reference/avfoundation/avplayer
关于ios - 如何控制 AVAssetWriter 以正确的 FPS 写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43365266/
我有一个计数器可以计算每一帧。我想做的是将其除以时间以确定我的程序的 FPS。但是我不确定如何在 python 中对计时函数执行操作。 我试过将时间初始化为 fps_time = time.time
我发布了我的 original question here .试过suggested solution .但这并不能解决我的问题。 这就是我所做的。下载 this video来自 Youtube 作为
JavaFX UI 线程上限为每秒 60 次更新(1、2)似乎是一种共识。据我了解,更新意味着 pulse。 A pulse is an event that indicates to the Jav
在处理来自相机的帧时,我正在尝试测量每秒帧数。计算没什么特别的,可以在这个问题中找到:How to write function with parameter which type is deduce
我在 Xcode 6.1.1 中使用 OpenGL ES 3.0 开发了一款针对 iPad Air 的游戏。当我捕获 OpenGL ES 帧时,FPS 数字和着色器程序时间始终显示为 0。 我在项目方
我正在尝试通过 ffmpeg 对视频进行编码在 Linux 系统中。原始视频有 60 FPS,我需要将其更改为 25,但是当我这样做时,视频比原始视频慢。 当我将其更改为 30 时,一切都很好(我想编
我正在尝试将视频从 25 fps 加速到 60 fps。我想要完全相同的帧数,只是更快地呈现给我,并且每秒可以让我获得 60 帧。 ffmpeg -i Spider.mov -r 62500/1000
我们如何才能以更高的帧速率(例如 500 - 800 FPS)运行 OpenGL 应用程序(例如游戏)? 例如,AOE 2 的运行速度超过 700 FPS(我知道它与 DirectX 有关)。尽管我只
为了高性能的科学目的,我们需要渲染视频并在设备上以 60fps 的速度播放。我假设 H.264 视频的通常帧率低于该值。 这是可能的,还是帧率是固定的?如果是这样,在设备上全屏播放 H.264 视频时
拥有 50 fps 的 5 秒视频 想要在 10 秒内将其转换为 25 fps 的视频,而且一切都变慢了,即使是音频 是否可以使用 ffmpeg 最佳答案 利用 ffmpeg -i input.mp4
我有下面的代码(移植到 JOGL 2.0 的 Nehe 教程 1 的基本版本)请求一个以 30 FPS 为动画的 FPSAnimator。当我运行代码时,它会打印 21.321962 或 21.413
我在下面有一些非常简单的性能测试代码,用于在 2011 年末的 Macbook Pro 上使用 OpenCV 3.1 + Python3 测量我的网络摄像头的 FPS: cap = cv2.Video
我正在开发 ARKit 应用以及 Vision/AVKit 框架。我正在使用 MLModel 对我的手势进行分类。我的应用程序可以识别Victory、Okey 和¡No pasarán! 手势来控制视
我从其他 SO 问题中使用了这个命令: $ ffmpeg -i obraz%04d.png -framerate 1 -c:v libx265 output.mkv 我告诉它最多 1 FPS,但日志和
我错误地在 iPhone SE (2) 上录制了慢动作视频,而不是延时摄影。 我知道这里有很多关于这个问题的答案,但我一次又一次地尝试并且总是出现问题(比如一个视频的总帧数正确,但持续了 3 个小时并
任何人都可以帮助我默认情况下以 240 fps 或 120 fps 录制视频,使用 AVCapture session 录制 session 需要 30 fps。 用这个库录制视频 https://g
我目前正在用 Java 制作 3D 游戏。我的问题是当我通过 Eclipse 运行它时,我得到了大约 40 fps,这很好。虽然当我在导出的 jar 文件中运行它时,我得到了 18 fps? 我不太确
自从我在 C++ 项目中从 OpenCV 3.x 更改为 4.x(从源代码编译)以来,我遇到了一些麻烦。我在一个小例子中复制了这个行为,这个例子只打开了一个网络摄像头并记录了 5 秒钟。 使用 3.x
我通过 VLC 录制了一个 RTSP 流(4K)大约一个小时,发生了一些奇怪的事情。 文件大小为 6.6 GB,但视频长度只有 12 分钟。 当我在 VLC 上播放时,进度条到达末尾,但视频仍在连续播
我正在尝试运行此命令。 ffmpeg -i out_frames/frame%08d.jpg -i input.mp4 -map 0:v:0 -map 1:a:0 -c:a copy -c:v lib
我是一名优秀的程序员,十分优秀!