如何从 Swift 中的本地视频文件中获取帧?
How to get frames from a local video file in Swift?
我需要从本地视频文件中获取帧,以便我可以在播放视频之前处理它们。我已经尝试过使用 AVAssetReader 和 VideoOutput。
[编辑] 这是我在
中使用的代码
let asset = AVAsset(URL: inputUrl)
let reader = try! AVAssetReader(asset: asset)
let videoTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
// read video frames as BGRA
let trackReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings:[String(kCVPixelBufferPixelFormatTypeKey): NSNumber(unsignedInt: kCVPixelFormatType_32BGRA)])
reader.addOutput(trackReaderOutput)
reader.startReading()
while let sampleBuffer = trackReaderOutput.copyNextSampleBuffer() {
print("sample at time \(CMSampleBufferGetPresentationTimeStamp(sampleBuffer))")
if let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
// process each CVPixelBufferRef here
// see CVPixelBufferGetWidth, CVPixelBufferLockBaseAddress, CVPixelBufferGetBaseAddress, etc
}
}
我相信 AVAssetReader 应该可以工作。你尝试了什么?您看过 Apple 的示例代码吗? https://developer.apple.com/library/content/samplecode/ReaderWriter/Introduction/Intro.html
你可以看看VideoToolbox:https://developer.apple.com/documentation/videotoolbox
但请注意:这接近于硬件解压缩器和稀疏记录的地形。
根据您想进行的处理,OpenCV 可能是一个选择 - 特别是如果您正在检测或跟踪帧中的对象。如果您的需求更简单,那么将 OpenCV 与 swift 一起使用的工作量可能有点太多 - 见下文。
您可以打开视频,逐帧阅读,对帧进行处理,然后显示 - 请记住需要高效以避免延迟显示。
基本代码结构非常简单 - 这是一个 python 示例,但相同的原则适用于支持的语言
import numpy as np
import cv2
cap = cv2.VideoCapture('vtest.avi')
while(cap.isOpened()):
ret, frame = cap.read()
//Do whatever work you want on the frame here - in this example
//from the tutorial the image is being converted from one colour
//space to another
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
//This displays the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
需要注意的是,将 OpenCV 与 swift 一起使用需要一些额外的努力 - 这是一个很好的例子,但它不断发展,因此如果您决定采用这种方式,则值得搜索:https://medium.com/@yiweini/opencv-with-swift-step-by-step-c3cc1d1ee5f1
我找到问题所在了!这是我的实施。我发布的代码是正确的。谢谢大家
我需要从本地视频文件中获取帧,以便我可以在播放视频之前处理它们。我已经尝试过使用 AVAssetReader 和 VideoOutput。
[编辑] 这是我在
let asset = AVAsset(URL: inputUrl)
let reader = try! AVAssetReader(asset: asset)
let videoTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
// read video frames as BGRA
let trackReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings:[String(kCVPixelBufferPixelFormatTypeKey): NSNumber(unsignedInt: kCVPixelFormatType_32BGRA)])
reader.addOutput(trackReaderOutput)
reader.startReading()
while let sampleBuffer = trackReaderOutput.copyNextSampleBuffer() {
print("sample at time \(CMSampleBufferGetPresentationTimeStamp(sampleBuffer))")
if let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
// process each CVPixelBufferRef here
// see CVPixelBufferGetWidth, CVPixelBufferLockBaseAddress, CVPixelBufferGetBaseAddress, etc
}
}
我相信 AVAssetReader 应该可以工作。你尝试了什么?您看过 Apple 的示例代码吗? https://developer.apple.com/library/content/samplecode/ReaderWriter/Introduction/Intro.html
你可以看看VideoToolbox:https://developer.apple.com/documentation/videotoolbox
但请注意:这接近于硬件解压缩器和稀疏记录的地形。
根据您想进行的处理,OpenCV 可能是一个选择 - 特别是如果您正在检测或跟踪帧中的对象。如果您的需求更简单,那么将 OpenCV 与 swift 一起使用的工作量可能有点太多 - 见下文。
您可以打开视频,逐帧阅读,对帧进行处理,然后显示 - 请记住需要高效以避免延迟显示。
基本代码结构非常简单 - 这是一个 python 示例,但相同的原则适用于支持的语言
import numpy as np
import cv2
cap = cv2.VideoCapture('vtest.avi')
while(cap.isOpened()):
ret, frame = cap.read()
//Do whatever work you want on the frame here - in this example
//from the tutorial the image is being converted from one colour
//space to another
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
//This displays the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
需要注意的是,将 OpenCV 与 swift 一起使用需要一些额外的努力 - 这是一个很好的例子,但它不断发展,因此如果您决定采用这种方式,则值得搜索:https://medium.com/@yiweini/opencv-with-swift-step-by-step-c3cc1d1ee5f1
我找到问题所在了!这是我的实施。我发布的代码是正确的。谢谢大家