如何使用 AVFoundation 中的捕获管道在录制过程中更新时间标签:
Mic -> AVCaptureDeviceInput -> AVCaptureSession -> AVCaptureAudioDataOutput
Run Code Online (Sandbox Code Playgroud)
AVCaptureAudioDataOutput 有 Delegate 和 AVAssetWritter 将sampleBuffers写入输出文件。在此解决方案中,我想更新录制时间。我可以记录用户点击“记录/暂停/恢复/停止”按钮时的时间,但是 Apple 是否有任何官方方法如何在开始时以 00:00:00 时间更新某些 UILabel。我知道我可以使用 NSTimer 但当我使用 AVAudioRecorder 时我有属性:
var currentTime: TimeInterval
// The time, in seconds, since the beginning of the recording.
Run Code Online (Sandbox Code Playgroud)
上述属性也适用于暂停/继续按钮。
现在,在这个新管道中,我没有这个属性,我想知道我是否丢失了某些东西并且无法在任何地方找到它。我还注意到 AVCaptureSession 有名为 masterClock 的 CMClock 属性,但自记录开始以来我不确定如何使用它来计算时间。
我不明白时钟和方法的全部概念,例如:
CMClockGetHostTimeClock()
CMSyncConvertTime
Run Code Online (Sandbox Code Playgroud)
如何在基于sampleBuffer的AVCaptureAudioDataOutputSampleBufferDelegate方法中获取自录音开始以来的秒数?
更新
我发现了一个名为 CMTimebase 的类,我认为这正是我正在寻找的。目前我不知道如何使用它,但我在操场上进行了一些实验后发现了这一点。
import CoreMedia
let masterClock = CMClockGetHostTimeClock() // This masterclock should be from captureSession
var timebase: CMTimebase? = nil
CMTimebaseCreateWithMasterClock(kCFAllocatorDefault, masterClock, &timebase)
print(CMTimeGetSeconds(CMTimebaseGetTime(timebase!)))
CMTimebaseSetRate(timebase!, 1.0) // …Run Code Online (Sandbox Code Playgroud) 我有一个项目,目前使用 H.264 编码器在 iOS 上录制视频。我想尝试在 iOS 11 中使用新的 HEVC 编码器来减小文件大小,但发现使用 HEVC 编码器会导致文件大小急剧膨胀。 GitHub 上的一个项目显示了该问题 - 它使用 H.264 和 H.265 (HEVC) 编码器同时将相机中的帧写入文件,并将生成的文件大小打印到控制台。
AVFoundation 类的设置如下:
class VideoWriter {
var avAssetWriterInput: AVAssetWriterInput
var avAssetWriter: AVassetWriter
init() {
if #available(iOS 11.0, *) {
avAssetWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: [AVVideoCodecKey:AVVideoCodecType.hevc, AVVideoHeightKey:720, AVVideoWidthKey:1280])
}
avAssetWriterInput.expectsMediaDataInRealTime = true
do {
let url = directory.appendingPathComponent(UUID.init().uuidString.appending(".hevc"))
avAssetWriter = try AVAssetWriter(url: url, fileType: AVFileType.mp4)
avAssetWriter.add(avAssetWriterInput)
avAssetWriter.movieFragmentInterval = kCMTimeInvalid
} catch {
fatalError("Could not initialize AVAssetWriter \(error)")
}
}
...
Run Code Online (Sandbox Code Playgroud)
然后框架是这样写的: …
我有一个应用程序,它以不同的方式对视频进行编码并将其保存到照片库 - 它可以剪切特定的时间范围,添加图片、文本等。一切都运行良好,直到我尝试对视频进行 120+ fps 的编码。问题是视频似乎是慢动作,而我根本不追求这个目标。
在这里,我发现了有关AVAssetWritterInput名为 的属性AVVideoExpectedSourceFrameRateKey,但问题是当我尝试将此参数应用于我的 时AVAssetWritterInput,我收到此错误:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVAssetWriterInput initWithMediaType:outputSettings:sourceFormatHint:] Output settings dictionary contains one or more invalid keys: ExpectedFrameRate'
这是我的AVAssetWriterInput初始化,一点也不花哨:
let input = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: [AVVideoCodecKey: AVVideoCodecJPEG,
AVVideoHeightKey: correctedContentSize.height,
AVVideoWidthKey: correctedContentSize.width,
AVVideoExpectedSourceFrameRateKey: 60])
Run Code Online (Sandbox Code Playgroud)
任何帮助,将不胜感激。谢谢。
我有 SCNView,屏幕中间有一些对象,用户可以旋转它、缩放等。
我想在视频中记录所有这些动作并实时添加一些声音。另外,我只想记录SCNView的中间部分(例如SCNView框架是375x812,但我只想中间375x375,没有顶部和底部边框)。我还想在视频捕获的同时将其显示在屏幕上。
我当前的变体是:
func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
DispatchQueue.main.async {
if let metalLayer = self.sceneView.layer as? CAMetalLayer, let texture = metalLayer.currentSceneDrawable?.texture, let pixelBufferPool = self.pixelBufferPool {
//1
var maybePixelBuffer: CVPixelBuffer? = nil
let status = CVPixelBufferPoolCreatePixelBuffer(nil, pixelBufferPool, &maybePixelBuffer)
guard let pixelBuffer = maybePixelBuffer else { return }
CVPixelBufferLockBaseAddress(pixelBuffer, [])
let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
let region = MTLRegionMake2D(Int(self.fieldOfView.origin.x * UIScreen.main.scale),
Int(self.fieldOfView.origin.y * UIScreen.main.scale),
Int(self.fieldOfView.width * UIScreen.main.scale),
Int(self.fieldOfView.height * UIScreen.main.scale))
let pixelBufferBytes = CVPixelBufferGetBaseAddress(pixelBuffer)!
texture.getBytes(pixelBufferBytes, …Run Code Online (Sandbox Code Playgroud) 我编写了一个屏幕录制应用程序,它使用 VideoToolbox 和 AVWriter 写出 H.264 电影文件。与原始屏幕相比,录制文件中的颜色有点暗淡。我知道这是因为 colorProfile 未存储在视频文件中。
这与如何对 AVAssetWriter 输出进行颜色管理密切相关
我创建了一个测试台来在 github ScreenRecordTest上展示这一点
如果您运行此应用程序,您可以使用 CMD-R 开始录制并使用相同的 CMD-R 停止录制(您必须开始和停止录制一次才能获得完整写入的电影文件)。您将在 /tmp/ 文件夹中找到类似以下名称的录音:“/tmp/grab-2018-10-25 09:23:32 +0000.mov”
录制时,应用程序会显示两个实时图像:a)从 CGDisplayStream 获取的帧 - 和 - b)来自压缩器的 cmSampleBuffer。
我发现从 CGDisplayStream 返回的 IOSurface 没有进行颜色管理,因此您会注意到压缩之前已经出现“暗淡”颜色。如果您取消 AppDelegate.swift 中第 89 行的注释
// cgImage = cgImage.copy(colorSpace: screenColorSpace)!
Run Code Online (Sandbox Code Playgroud)
此实时预览将具有正确的颜色。现在这仅用于显示压缩前的 IOSurface。我不知道如何使其他实时预览(压缩后)(AppDelegate 中的第 69 行)显示正确的颜色(例如:如何将 colorProfile 应用于 CMSampleBuffer),或者最重要的是如何使用正确的配置文件,以便在打开 .mov 文件时我在播放时获得正确的颜色。
我有一组存储为 AVURLAsset 的视频录制,我想将视频合并到 1 个剪辑中,以便它们连续播放,视频之间没有时间间隔。下面是我希望做的,但它只显示第一个视频。注意:我希望视频连续播放,并且每个视频之间没有空白。例如,如果当手机未录音时,录音 1 和录音 2 之间存在实时时间,则输出不应显示此情况。
感谢您的帮助!
func mergeVideos(handler: @escaping (_ asset: AVAssetExportSession)->()) {
let mixComposition = AVMutableComposition()
var videoTime = CMTime.zero
for video in self.recordings {
let tracks = video.tracks(withMediaType: .video)
let videoTrack = tracks[0]
let videoTimeRange = CMTimeRangeMake(start: .zero, duration: video.duration)
guard let compositionVideoTrack: AVMutableCompositionTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
do {
try compositionVideoTrack.insertTimeRange(videoTimeRange, of: videoTrack, at: videoTime)
videoTime = CMTimeAdd(videoTime, video.duration)
} catch {
print("An error occurred")
return
}
} …Run Code Online (Sandbox Code Playgroud) xcode video-processing avassetwriter avassetexportsession swift
我有一个H.264/AVC NAL流,包括类型1(P帧),5(I帧),7(SPS)和8(PPS).我想将它们写入.mov文件而不重新编码.我试图用AVAssetWriter这个来做.AVAssetWriterInput各州的文件:
为outputSettings传递nil指示输入传递附加的样本,在将它们写入输出文件之前不进行任何处理.例如,如果要附加已经采用所需压缩格式的缓冲区,则此方法很有用.但是,只有在写入QuickTime Movie文件时才支持passthrough(即AVAssetWriter是使用AVFileTypeQuickTimeMovie初始化的).对于其他文件类型,您必须指定非零输出设置.
我正在尝试从这些NAL中创建CMSampleBuffers并将它们附加到资产编写器输入,但我无法以产生格式良好的.mov文件的方式输入数据,我无法在任何地方找到任何线索关于如何做到这一点.
到目前为止,我得到的最好结果是以附件B字节流格式传递NAL(按照顺序7 8 5 1 1 1 ....重复)并在VLC中播放结果.因此,我知道NAL包含有效数据,但由于.mov文件没有avcC原子且mdat原子填充了附件B字节流,因此QuickTime不会播放视频.
现在我试图用4字节(由lengthSizeMinusOne字段指定)长度字段而不是附件B分隔符传入NAL,就我所知,它们应该被打包到mdat原子中. .
我不知道如何让资产作者写一个avcC原子.我附加的每个样本都被推入mdat原子.
有谁知道如何将原始H.264数据传递到为传递(nil outputSettings)配置的AVAssetWriterInput并让它生成正确形成的QuickTime文件?
我正在尝试记录音频片段并重新组合它们而不会产生音频差距.
最终的目标是也有视频,但我发现音频本身在结合时会产生差距 ffmpeg -f concat -i list.txt -c copy out.mp4
如果我把音频放在HLS播放列表中,也有间隙,所以我不认为这是ffmpeg独有的.
这个想法是样本连续进入,我的控制器将样本路由到正确的样本AVAssetWriter.如何消除音频中的差距?
import Foundation
import UIKit
import AVFoundation
class StreamController: UIViewController, AVCaptureAudioDataOutputSampleBufferDelegate, AVCaptureVideoDataOutputSampleBufferDelegate {
var closingAudioInput: AVAssetWriterInput?
var closingAssetWriter: AVAssetWriter?
var currentAudioInput: AVAssetWriterInput?
var currentAssetWriter: AVAssetWriter?
var nextAudioInput: AVAssetWriterInput?
var nextAssetWriter: AVAssetWriter?
var videoHelper: VideoHelper?
var startTime: NSTimeInterval = 0
let closeAssetQueue: dispatch_queue_t = dispatch_queue_create("closeAssetQueue", nil);
override func viewDidLoad() {
super.viewDidLoad()
startTime = NSDate().timeIntervalSince1970
createSegmentWriter()
videoHelper = VideoHelper()
videoHelper!.delegate = self
videoHelper!.startSession()
NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "createSegmentWriter", userInfo: …Run Code Online (Sandbox Code Playgroud) 我们的应用程序使用 AVFoundation 来捕获视频、显示、操作和使用其示例缓冲区导出视频。我试图了解CMSampleBufferGetPresentationTimeStamp(_:)CMTime 实际代表什么。
例如,视频采集开始时,第一个样本的呈现时间为 93 小时 5 分钟。我不明白这个价值从何而来。使用第一个示例的演示时间来启动 AVAssetWriter 会话会在视频播放开始之前创建 93 小时的黑帧。
有人知道如何使用具有 2 个以上通道的 AVAssetWriterInput init 吗?
我正在尝试初始化一个音频输入,以这种方式在 AVAssetWriter 之后添加它:
let audioInput = AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: audioOutputSettings)
Run Code Online (Sandbox Code Playgroud)
assetWriter.add(audioInput)
assetWriter.startWriting()
但是当我使用包含大于 2 的通道键数的 audioOutputSettings 字典初始化 audioInput 时它会崩溃。错误是:
Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ’*** -[AVAssetWriterInput initWithMediaType:outputSettings:sourceFormatHint:] 6 is not a valid channel count for Format ID ‘aac ’. Use kAudioFormatProperty_AvailableEncodeNumberChannels (<AudioToolbox/AudioFormat.h>) to enumerate available channel counts for a given format.
avassetwriter ×10
ios ×8
avfoundation ×7
swift ×5
iphone ×2
frame-rate ×1
h.264 ×1
hevc ×1
macos ×1
metal ×1
scenekit ×1
video ×1
xcode ×1