我目前正在制作一个小型应用程序,该程序可以使Mac上的网络摄像头延时播放,将捕获的帧保存为png,并且正在考虑将捕获的帧导出为单个视频。
我使用CGImage处理原始图像,并将它们设置在数组中,但是我不确定从那里开始。根据我自己的研究,我不得不以某种方式使用AVAssetWriter和AVAssetWriterInput。
我在这里浏览了一下,阅读了苹果文档并搜索了谷歌。但是所有指南等都在obj-c中,而不是快捷的,这使得它真的很难理解(因为我没有Obj-C的经验)。
任何帮助将不胜感激。
非常感谢,卢克。
我在Swift中解决了同样的问题。从UIImage数组开始,尝试一下(有点长:-),但是可以):
var choosenPhotos: [UIImage] = [] *** your array of UIImages ***
var outputSize = CGSizeMake(1280, 720)
func build(outputSize outputSize: CGSize) {
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
guard let documentDirectory: NSURL = urls.first else {
fatalError("documentDir Error")
}
let videoOutputURL = documentDirectory.URLByAppendingPathComponent("OutputVideo.mp4")
if NSFileManager.defaultManager().fileExistsAtPath(videoOutputURL.path!) {
do {
try NSFileManager.defaultManager().removeItemAtPath(videoOutputURL.path!)
} catch {
fatalError("Unable to delete file: \(error) : \(__FUNCTION__).")
}
}
guard let videoWriter = try? AVAssetWriter(URL: videoOutputURL, fileType: AVFileTypeMPEG4) else {
fatalError("AVAssetWriter error")
}
let outputSettings = [AVVideoCodecKey : AVVideoCodecH264, AVVideoWidthKey : NSNumber(float: Float(outputSize.width)), AVVideoHeightKey : NSNumber(float: Float(outputSize.height))]
guard videoWriter.canApplyOutputSettings(outputSettings, forMediaType: AVMediaTypeVideo) else {
fatalError("Negative : Can't apply the Output settings...")
}
let videoWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: outputSettings)
let sourcePixelBufferAttributesDictionary = [kCVPixelBufferPixelFormatTypeKey as String : NSNumber(unsignedInt: kCVPixelFormatType_32ARGB), kCVPixelBufferWidthKey as String: NSNumber(float: Float(outputSize.width)), kCVPixelBufferHeightKey as String: NSNumber(float: Float(outputSize.height))]
let pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: videoWriterInput, sourcePixelBufferAttributes: sourcePixelBufferAttributesDictionary)
if videoWriter.canAddInput(videoWriterInput) {
videoWriter.addInput(videoWriterInput)
}
if videoWriter.startWriting() {
videoWriter.startSessionAtSourceTime(kCMTimeZero)
assert(pixelBufferAdaptor.pixelBufferPool != nil)
let media_queue = dispatch_queue_create("mediaInputQueue", nil)
videoWriterInput.requestMediaDataWhenReadyOnQueue(media_queue, usingBlock: { () -> Void in
let fps: Int32 = 1
let frameDuration = CMTimeMake(1, fps)
var frameCount: Int64 = 0
var appendSucceeded = true
while (!self.choosenPhotos.isEmpty) {
if (videoWriterInput.readyForMoreMediaData) {
let nextPhoto = self.choosenPhotos.removeAtIndex(0)
let lastFrameTime = CMTimeMake(frameCount, fps)
let presentationTime = frameCount == 0 ? lastFrameTime : CMTimeAdd(lastFrameTime, frameDuration)
var pixelBuffer: CVPixelBuffer? = nil
let status: CVReturn = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pixelBufferAdaptor.pixelBufferPool!, &pixelBuffer)
if let pixelBuffer = pixelBuffer where status == 0 {
let managedPixelBuffer = pixelBuffer
CVPixelBufferLockBaseAddress(managedPixelBuffer, 0)
let data = CVPixelBufferGetBaseAddress(managedPixelBuffer)
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGBitmapContextCreate(data, Int(self.outputSize.width), Int(self.outputSize.height), 8, CVPixelBufferGetBytesPerRow(managedPixelBuffer), rgbColorSpace, CGImageAlphaInfo.PremultipliedFirst.rawValue)
CGContextClearRect(context, CGRectMake(0, 0, CGFloat(self.outputSize.width), CGFloat(self.outputSize.height)))
let horizontalRatio = CGFloat(self.outputSize.width) / nextPhoto.size.width
let verticalRatio = CGFloat(self.outputSize.height) / nextPhoto.size.height
//aspectRatio = max(horizontalRatio, verticalRatio) // ScaleAspectFill
let aspectRatio = min(horizontalRatio, verticalRatio) // ScaleAspectFit
let newSize:CGSize = CGSizeMake(nextPhoto.size.width * aspectRatio, nextPhoto.size.height * aspectRatio)
let x = newSize.width < self.outputSize.width ? (self.outputSize.width - newSize.width) / 2 : 0
let y = newSize.height < self.outputSize.height ? (self.outputSize.height - newSize.height) / 2 : 0
CGContextDrawImage(context, CGRectMake(x, y, newSize.width, newSize.height), nextPhoto.CGImage)
CVPixelBufferUnlockBaseAddress(managedPixelBuffer, 0)
appendSucceeded = pixelBufferAdaptor.appendPixelBuffer(pixelBuffer, withPresentationTime: presentationTime)
} else {
print("Failed to allocate pixel buffer")
appendSucceeded = false
}
}
if !appendSucceeded {
break
}
frameCount++
}
videoWriterInput.markAsFinished()
videoWriter.finishWritingWithCompletionHandler { () -> Void in
print("FINISHED!!!!!")
}
})
}
}
问题内容: 我是swift的新手,任何人都可以帮助我快速集成PayU Money…。我正在使用此SDK:https : //github.com/payu-intrepos/Documentations/wiki/8.1/NEW-iOS-Seamless -SDK集成 问题答案: 这个答案来自PayU文档本身,我在这里回答的原因只是因为花了我几个小时才能实现他们的文档。 嗨,我可以为您提供NON无
问题内容: 这是我的代码,但显示了进度。这段代码有什么错误吗?请提供一些想法来解决此问题,或者提供一些与此相关的链接。 问题答案: 更新的答案: 要关闭ProgressHUD:
问题内容: 我是一个Node.js新手,并且正在用它创建我的第一个大型应用程序(我正在使用Express)。当用户使用get请求加载ID时,我需要让我的网页执行一些javascript画布绘制 我知道我可以用一个简单的方法来处理 但我不知道如何使用该ID的要求的图纸开始我的网页。互联网上Express和Get上的每个教程都说明了如何处理get请求…这个问题是关于“接下来会发生什么?” 改写:我不确
我们的视频播放软件(本地的,不是流媒体),可以随意跳到第 n 秒 这个功能是怎么实现的? 因为视频的一个一个 packet 组成,每个 packet 包含 [0,+∞) 个 frame 所以跳转到第 10 秒怎么实现? 一个视频 30 fps,难道要,从第 0 帧开始读取 300 帧,才播放吗? 这样的话,越拖到后面越慢 但是实际使用这些播放软件的时候,感觉都是秒级别的
我们录制了一个简短的视频来展示如何开始使用Ansible,当你阅读文档时可以用到它。 快速学习视频 长度大概为30分钟,介绍了刚开始使用Ansible的一些基本知识。 欢迎观看本视频,请确保阅读剩余的文档来进行进一步的学习。
Vanilla 的 Service vanilla 的 Service 预设为项目对某些通用业务逻辑封装为独立的 Service,方便维护、管理、缓存等。 Vanilla 的 Service 在项目的 models/service 路径下,一般使用 LoadModel 方法进行加载 最简单的 Service 由自动生成的 demo 中默认生成了 UserService,可以看出 UserServi