我正在尝试查找刚刚打开的视频中的帧数,而不解码所有帧。
我使用AVAsset
打开,然后获得视频的AVAssetTrack
。下一步是什么?
答案 0 :(得分:5)
执行此操作的一种相对昂贵的方法是使用AVAssetReader读取所有帧并随时计算它们。
let asset = AVAsset(url: url)
let assetTrack = asset.tracksWithMediaType(AVMediaTypeVideo).first!
let assetReader = try! AVAssetReader(asset: self)
let assetReaderOutputSettings = [
kCVPixelBufferPixelFormatTypeKey as String: NSNumber(unsignedInt: kCVPixelFormatType_32BGRA)
]
let assetReaderOutput = AVAssetReaderTrackOutput(track: assetTrack, outputSettings: assetReaderOutputSettings)
assetReaderOutput.alwaysCopiesSampleData = false
assetReader.addOutput(assetReaderOutput)
assetReader.startReading()
var frameCount = 0
var sample: CMSampleBufferRef? = assetReaderOutput.copyNextSampleBuffer()
while (sample != nil) {
frameCount++
sample = assetReaderOutput.copyNextSampleBuffer()
}
// now you have frame count
print(frameCount)
答案 1 :(得分:4)
你可以这样做:
float durationInSeconds = CMTimeGetSeconds(asset.duration);
float framesPerSecond = assetTrack.nominalFrameRate;
float numberOfFrames = durationInSeconds * framesPerSecond;
答案 2 :(得分:2)
已更新为 Swift 4.2 ,并转换为URL
的扩展名。
import AVFoundation
extension URL {
var videoFrameCount: Int? {
let asset = AVAsset(url: self)
guard let assetTrack = asset.tracks(withMediaType: .video).first else {
return nil
}
var assetReader: AVAssetReader?
do {
assetReader = try AVAssetReader(asset: asset)
} catch {
print(error.localizedDescription)
return nil
}
let assetReaderOutputSettings = [
kCVPixelBufferPixelFormatTypeKey as String: NSNumber(value: kCVPixelFormatType_32BGRA)
]
let assetReaderOutput = AVAssetReaderTrackOutput(track: assetTrack,
outputSettings: assetReaderOutputSettings)
assetReaderOutput.alwaysCopiesSampleData = false
assetReader?.add(assetReaderOutput)
assetReader?.startReading()
var frameCount = 0
var sample: CMSampleBuffer? = assetReaderOutput.copyNextSampleBuffer()
while (sample != nil) {
frameCount += 1
sample = assetReaderOutput.copyNextSampleBuffer()
}
return frameCount
}
}
如果能够将URL
转换为类型AVAsset
的{{1}},则会继续。否则,返回值video
。
接下来,创建nil
。如果此步骤失败,它将再次返回AVAssetReader
。
由于所有内容都已正确设置,现在它将继续解析输出并计算帧数。只要生成nil
,循环将继续帧计数递增。一旦不再生成样本,它将终止循环并返回sample
的值。
答案 3 :(得分:0)
尽管使用Checkbutton
+ main.iconify()
global motor_wire
motor_wire = Toplevel(main)
motorframe = LabelFrame(motor_wire, text="SIZE OF WIRE", font = ('Garamond', '25', 'bold', 'underline'), padx = 270, pady = 167, bd = 8)
motorframe.place(x = 30, y = 5)
Label(motorframe).pack()
thirteen = Checkbutton(motor_wire, text = '#13',font=("Calibri", '30', 'bold'), relief = 'groove' ,
bd = 5,padx = 0, pady = 5).place(x = 52, y = 50)
fourteen = Checkbutton(motor_wire, text = '#14',font=("Calibri", '30', 'bold'),relief = 'groove' ,
bd = 5,padx = 0, pady = 5).place(x = 189, y = 50)
fifteen = Checkbutton(motor_wire, text = '#15',font=("Calibri", '30','bold'),relief = 'groove' ,
bd = 5, padx = 0, pady = 5).place(x = 326, y = 50)
的解决方案是正确的,但我建议使用AVAssetReader
输出设置来创建AVAssetReaderTrackOutput
。这样AVAssetReaderTrackOutput
不会解压缩帧,您可以更快地得到结果。
这是一个示例实现:
nil