使用 AVAssetReader 从 iPad 上的视频读取帧时,图像方向不正确
When reading frames from a video on an iPad with AVAssetReader, the images are not properly oriented
我想首先确定的几件事:
- 这适用于多部 iPhone (iOS 10.3 & 11.x)
- 这在任何 iPad 模拟器上都能正常工作(iOS 11.x)
我剩下的是这样一种情况,当我 运行 以下代码(从我的应用程序中浓缩以删除不相关的代码)时,我得到的图像是颠倒的(横向)或旋转 90度(肖像)。查看在此步骤之前处理的视频表明它的方向正确。所有测试均已在 iOS 11.2.5.
上完成
* 已更新 *
我做了一些进一步的测试,发现了一些更有趣的项目:
- 如果视频是从 phone 或外部来源导入的,则会得到正确处理
- 如果视频是在 iPad 上纵向录制的,则 reader 将视频向左旋转 90 度提取
- 如果视频是在 iPad 上横向录制的,则 reader 会将其倒置提取
- 在上述两种情况下,
UIImage
报告的方向是纵向
相关代码的精简版:
import UIKit
import AVFoundation
let asset = ...
let assetReader = try? AVAssetReader(asset: asset)
if let assetTrack = asset.tracks(withMediaType: .video).first,
let assetReader = assetReader {
let assetReaderOutputSettings = [
kCVPixelBufferPixelFormatTypeKey as String : NSNumber(value: kCVPixelFormatType_32BGRA)
]
let assetReaderOutput = AVAssetReaderTrackOutput(track: assetTrack,
outputSettings: assetReaderOutputSettings)
assetReaderOutput.alwaysCopiesSampleData = false
assetReader.add(assetReaderOutput)
var images = [UIImage]()
assetReader.startReading()
var sample = assetReaderOutput.copyNextSampleBuffer()
while (sample != nil) {
if let image = sample?.uiImage { // The image is inverted here
images.append(image)
sample = assetReaderOutput.copyNextSampleBuffer()
}
}
// Continue here with array of images...
}
经过一番探索,我发现了以下内容,可以让我从 AVAssetTrack
获取视频的方向:
let transform = assetTrack.preferredTransform
radians = atan2(transform.b, transform.a)
一旦我有了它,我就可以将它转换为度数:
let degrees = (radians * 180.0) / .pi
然后,使用 switch 语句我可以确定如何旋转图像:
Switch Int(degrees) {
case -90, 90:
// Rotate accordingly
case 180:
// Flip
default:
// Do nothing
}
我想首先确定的几件事:
- 这适用于多部 iPhone (iOS 10.3 & 11.x)
- 这在任何 iPad 模拟器上都能正常工作(iOS 11.x)
我剩下的是这样一种情况,当我 运行 以下代码(从我的应用程序中浓缩以删除不相关的代码)时,我得到的图像是颠倒的(横向)或旋转 90度(肖像)。查看在此步骤之前处理的视频表明它的方向正确。所有测试均已在 iOS 11.2.5.
上完成* 已更新 *
我做了一些进一步的测试,发现了一些更有趣的项目:
- 如果视频是从 phone 或外部来源导入的,则会得到正确处理
- 如果视频是在 iPad 上纵向录制的,则 reader 将视频向左旋转 90 度提取
- 如果视频是在 iPad 上横向录制的,则 reader 会将其倒置提取
- 在上述两种情况下,
UIImage
报告的方向是纵向
相关代码的精简版:
import UIKit
import AVFoundation
let asset = ...
let assetReader = try? AVAssetReader(asset: asset)
if let assetTrack = asset.tracks(withMediaType: .video).first,
let assetReader = assetReader {
let assetReaderOutputSettings = [
kCVPixelBufferPixelFormatTypeKey as String : NSNumber(value: kCVPixelFormatType_32BGRA)
]
let assetReaderOutput = AVAssetReaderTrackOutput(track: assetTrack,
outputSettings: assetReaderOutputSettings)
assetReaderOutput.alwaysCopiesSampleData = false
assetReader.add(assetReaderOutput)
var images = [UIImage]()
assetReader.startReading()
var sample = assetReaderOutput.copyNextSampleBuffer()
while (sample != nil) {
if let image = sample?.uiImage { // The image is inverted here
images.append(image)
sample = assetReaderOutput.copyNextSampleBuffer()
}
}
// Continue here with array of images...
}
经过一番探索,我发现了以下内容,可以让我从 AVAssetTrack
获取视频的方向:
let transform = assetTrack.preferredTransform
radians = atan2(transform.b, transform.a)
一旦我有了它,我就可以将它转换为度数:
let degrees = (radians * 180.0) / .pi
然后,使用 switch 语句我可以确定如何旋转图像:
Switch Int(degrees) {
case -90, 90:
// Rotate accordingly
case 180:
// Flip
default:
// Do nothing
}