无法使用 AVFoundation 将 JPEG 图像写入 HDD
Can't write JPEG image to HDD using AVFoundation
我正在使用 AVFoundation
模块访问 macOS 10.13.3 上的 FaceTime 摄像头。
captureSession.startRunning()
方法是运行,相机的指示灯是绿色的。但是我无法在我的硬盘上捕获和写入 JPEG 图像。我的代码有什么问题?
我需要输出 jpg
图像 167
x188
像素(宽 x 高)。
我在 Xcode 9,Swift 4 工作。
import Cocoa
import AVFoundation
import CoreImage
class ViewController: NSViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
@IBOutlet weak var camera: NSView!
@IBOutlet weak var captureButton: NSButton!
@IBOutlet weak var saveButton: NSButton!
let captureSession = AVCaptureSession()
var captureDevice: AVCaptureDevice?
var previewLayer: AVCaptureVideoPreviewLayer?
var imageOutput: AVCaptureStillImageOutput?
override func viewDidLoad() {
super.viewDidLoad()
self.view.layer?.backgroundColor = NSColor.black.cgColor
camera.layer = CALayer()
captureSession.sessionPreset = AVCaptureSession.Preset.low
let devices = AVCaptureDevice.devices()
for device in devices {
print(device)
if ((device as AnyObject).hasMediaType(AVMediaType.video)) {
print(device)
captureDevice = device
}
}
if captureDevice != nil {
do {
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice!))
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.frame = (self.camera.layer?.frame)!
self.camera.layer?.addSublayer(previewLayer!)
captureSession.startRunning()
} catch {
print(AVCaptureSessionErrorKey.description)
}
}
}
var assetWriter: AVAssetWriter!
var imageWriterInput: AVAssetWriterInput!
let outputSettings = [String: Any]()
let url = URL(fileURLWithPath: "/Users/catalyst/Desktop/image.jpg")
@IBAction func captureImage(_ sender: NSButton) {
print("Taking photo...")
imageOutput = AVCaptureStillImageOutput()
imageOutput?.outputSettings = [
AVVideoCodecKey: AVVideoCodecType.jpeg,
AVVideoWidthKey: NSNumber(value: Float(167)),
AVVideoHeightKey: NSNumber(value: Float(188))
] as [String : Any]
if captureSession.canAddOutput(imageOutput!) {
captureSession.addOutput(imageOutput!)
}
}
@IBAction func saveImage(_ sender: NSButton) {
print("Saving photo...")
let writerFileName = url
assetWriter = try? AVAssetWriter(outputURL: writerFileName, fileType: AVFileType.jpg)
imageWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: outputSettings)
assetWriter.add(imageWriterInput)
}
}
没有编译器错误,我的桌面上没有捕获的图像。
编辑完全改变了这个问题的性质,所以这里是
新答案
这帮我拍了张照片。确保沙盒不会阻止您写入您指定的路径。 AVCaptureStillImageOutput
似乎无法为您调整大小,因此您可以使用 .
调整大小
let captureSession = AVCaptureSession()
let stillImageOutput = AVCaptureStillImageOutput()
var previewLayer: AVCaptureVideoPreviewLayer! = nil
override func viewDidLoad() {
super.viewDidLoad()
let captureDevice = AVCaptureDevice.default(for: .video)
if captureDevice != nil {
do {
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice!))
// AVCaptureVideoPreviewLayer code
// assumes you have camera NSView
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer!.frame = (self.camera.layer?.frame)!
self.camera.layer?.addSublayer(previewLayer!)
captureSession.addOutput(stillImageOutput)
captureSession.startRunning()
} catch {
print(AVCaptureSessionErrorKey.description)
}
}
}
@IBAction func captureImage(_ sender: NSButton) {
print("Taking photo...")
if let videoConnection = stillImageOutput.connection(with: .video) {
stillImageOutput.captureStillImageAsynchronously(from: videoConnection) { jpegBuffer, error in
// TODO: check error here
if let data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(jpegBuffer!) {
// make sure sandboxing isn't blocking this path
let url = URL(fileURLWithPath: "/Users/swift/Desktop/picture.jpg")
// resize here using something like
//
try! data.write(to: url)
}
}
}
}
旧答案
您的 url 引用了一个目录。尝试引用一个文件:
let url = URL(fileURLWithPath: "/Users/swift/Desktop/movie.mov")
您还需要实施 AVCaptureVideoDataOutputSampleBufferDelegate
协议。
AVCaptureVideoDataOutput
不是文件,它是一种在 real-ish 时间内使用视频和音频缓冲区进行回调的方法,您应该将样本附加到 videoWriterInput
.
AVCaptureVideoDataOutput
和 AVAssetWriter
级别很低。如果你只是想记录到一个文件,你可以用更简单的 AVCaptureMovieFileOutput
.
替换它们
我正在使用 AVFoundation
模块访问 macOS 10.13.3 上的 FaceTime 摄像头。
captureSession.startRunning()
方法是运行,相机的指示灯是绿色的。但是我无法在我的硬盘上捕获和写入 JPEG 图像。我的代码有什么问题?
我需要输出 jpg
图像 167
x188
像素(宽 x 高)。
我在 Xcode 9,Swift 4 工作。
import Cocoa
import AVFoundation
import CoreImage
class ViewController: NSViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
@IBOutlet weak var camera: NSView!
@IBOutlet weak var captureButton: NSButton!
@IBOutlet weak var saveButton: NSButton!
let captureSession = AVCaptureSession()
var captureDevice: AVCaptureDevice?
var previewLayer: AVCaptureVideoPreviewLayer?
var imageOutput: AVCaptureStillImageOutput?
override func viewDidLoad() {
super.viewDidLoad()
self.view.layer?.backgroundColor = NSColor.black.cgColor
camera.layer = CALayer()
captureSession.sessionPreset = AVCaptureSession.Preset.low
let devices = AVCaptureDevice.devices()
for device in devices {
print(device)
if ((device as AnyObject).hasMediaType(AVMediaType.video)) {
print(device)
captureDevice = device
}
}
if captureDevice != nil {
do {
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice!))
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.frame = (self.camera.layer?.frame)!
self.camera.layer?.addSublayer(previewLayer!)
captureSession.startRunning()
} catch {
print(AVCaptureSessionErrorKey.description)
}
}
}
var assetWriter: AVAssetWriter!
var imageWriterInput: AVAssetWriterInput!
let outputSettings = [String: Any]()
let url = URL(fileURLWithPath: "/Users/catalyst/Desktop/image.jpg")
@IBAction func captureImage(_ sender: NSButton) {
print("Taking photo...")
imageOutput = AVCaptureStillImageOutput()
imageOutput?.outputSettings = [
AVVideoCodecKey: AVVideoCodecType.jpeg,
AVVideoWidthKey: NSNumber(value: Float(167)),
AVVideoHeightKey: NSNumber(value: Float(188))
] as [String : Any]
if captureSession.canAddOutput(imageOutput!) {
captureSession.addOutput(imageOutput!)
}
}
@IBAction func saveImage(_ sender: NSButton) {
print("Saving photo...")
let writerFileName = url
assetWriter = try? AVAssetWriter(outputURL: writerFileName, fileType: AVFileType.jpg)
imageWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: outputSettings)
assetWriter.add(imageWriterInput)
}
}
没有编译器错误,我的桌面上没有捕获的图像。
编辑完全改变了这个问题的性质,所以这里是
新答案
这帮我拍了张照片。确保沙盒不会阻止您写入您指定的路径。 AVCaptureStillImageOutput
似乎无法为您调整大小,因此您可以使用
let captureSession = AVCaptureSession()
let stillImageOutput = AVCaptureStillImageOutput()
var previewLayer: AVCaptureVideoPreviewLayer! = nil
override func viewDidLoad() {
super.viewDidLoad()
let captureDevice = AVCaptureDevice.default(for: .video)
if captureDevice != nil {
do {
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice!))
// AVCaptureVideoPreviewLayer code
// assumes you have camera NSView
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer!.frame = (self.camera.layer?.frame)!
self.camera.layer?.addSublayer(previewLayer!)
captureSession.addOutput(stillImageOutput)
captureSession.startRunning()
} catch {
print(AVCaptureSessionErrorKey.description)
}
}
}
@IBAction func captureImage(_ sender: NSButton) {
print("Taking photo...")
if let videoConnection = stillImageOutput.connection(with: .video) {
stillImageOutput.captureStillImageAsynchronously(from: videoConnection) { jpegBuffer, error in
// TODO: check error here
if let data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(jpegBuffer!) {
// make sure sandboxing isn't blocking this path
let url = URL(fileURLWithPath: "/Users/swift/Desktop/picture.jpg")
// resize here using something like
//
try! data.write(to: url)
}
}
}
}
旧答案
您的 url 引用了一个目录。尝试引用一个文件:
let url = URL(fileURLWithPath: "/Users/swift/Desktop/movie.mov")
您还需要实施 AVCaptureVideoDataOutputSampleBufferDelegate
协议。
AVCaptureVideoDataOutput
不是文件,它是一种在 real-ish 时间内使用视频和音频缓冲区进行回调的方法,您应该将样本附加到 videoWriterInput
.
AVCaptureVideoDataOutput
和 AVAssetWriter
级别很低。如果你只是想记录到一个文件,你可以用更简单的 AVCaptureMovieFileOutput
.