AVURLAsset 获取视频大小

问题描述 投票:0回答:9

这真是令人沮丧。我正在尝试获取 AVURLasset 的大小,但尽量避免

naturalSize
,因为 Xcode 告诉我,这在 iOS5 中已弃用。

但是:替代品是什么?

我找不到任何关于如何在不使用“naturalsize”的情况下获取视频尺寸的线索...

xcode ios5 avurlasset
9个回答
53
投票

Swift 3 中的解决方案:

func resolutionSizeForLocalVideo(url:NSURL) -> CGSize? {
    guard let track = AVAsset(URL: url).tracksWithMediaType(AVMediaTypeVideo).first else { return nil }
    let size = CGSizeApplyAffineTransform(track.naturalSize, track.preferredTransform)
    return CGSize(width: fabs(size.width), height: fabs(size.height))
}

对于 Swift 4:

func resolutionSizeForLocalVideo(url:NSURL) -> CGSize? {
    guard let track = AVAsset(url: url as URL).tracks(withMediaType: AVMediaType.video).first else { return nil }
    let size = track.naturalSize.applying(track.preferredTransform)
    return CGSize(width: fabs(size.width), height: fabs(size.height))
}

没有

preferredTransform
的解决方案不会为最新设备上的某些视频返回正确的值!


34
投票

我刚刚在线查看了文档,对于 AVAsset 对象,

naturalSize
方法已被弃用。但是,应该始终有一个 AVAssetTrack 引用 AVAsset,并且 AVAssetTrack 有一个可以调用的
naturalSize
方法。

自然尺寸

轨道引用的媒体数据的自然尺寸。 (只读)

@property(非原子,只读)CGSize naturalSize

可用性

适用于 iOS 4.0 及更高版本。在 AVAssetTrack.h 中声明

通过:iOS 版 AVAssetTrack 参考


26
投票

官方文档中的弃用警告建议:“酌情使用资产视频轨道的

naturalSize
preferredTransform
(另请参阅
tracksWithMediaType:
)。”

我将代码更改为:

CGSize size = [movieAsset naturalSize];

CGSize size = [[[movieAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] naturalSize];

现在不太漂亮,也不太安全,但当他们放弃该方法时不会破坏。


17
投票

弃用警告说:

Use the naturalSize and preferredTransform, as appropriate, 
of the asset’s video tracks instead (see also tracksWithMediaType:).

所以我们需要一个 AVAssetTrack,并且我们想要它的 naturalSizepreferredTransform。可以通过以下方式访问:

AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
CGSize dimensions = CGSizeApplyAffineTransform(track.naturalSize, track.preferredTransform);

资产显然是您的AVAsset


5
投票

这是

Swift 4
AVAsset 的一个相当简单的扩展,用于获取视频的大小(如果可用):

extension AVAsset {
    var screenSize: CGSize? {
        if let track = tracks(withMediaType: .video).first {
            let size = __CGSizeApplyAffineTransform(track.naturalSize, track.preferredTransform)
            return CGSize(width: fabs(size.width), height: fabs(size.height))
        } 
        return nil
    }
}

3
投票

要导出

AVAsset
的维度,您应该计算所有视觉轨迹矩形的并集(在应用相应的首选变换之后):

CGRect unionRect = CGRectZero;
for (AVAssetTrack *track in [asset tracksWithMediaCharacteristic:AVMediaCharacteristicVisual]) {
    CGRect trackRect = CGRectApplyAffineTransform(CGRectMake(0.f,
                                                             0.f,
                                                             track.naturalSize.width,
                                                             track.naturalSize.height),
                                                  track.preferredTransform);
    unionRect = CGRectUnion(unionRect, trackRect);
}
CGSize naturalSize = unionRect.size;

当您的资源包含具有非平凡仿射变换的曲目(例如,45 度旋转)或者您的资源包含具有不同来源的曲目(例如,两个曲目与第二个曲目并排播放)时,依赖于

CGSizeApplyAffineTransform
的方法会失败轨道的原点增加了第一条轨道的宽度)。

参见:

MediaPlayerPrivateAVFoundationCF::sizeChanged()
at https://opensource.apple.com/source/WebCore/WebCore-7536.30.2/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp


3
投票

对于 Swift 5

let assetSize =  asset.tracks(withMediaType: .video)[0].naturalSize

2
投票

适用于 iOS 15.0 及以上版本,

extension AVAsset {
    func naturalSize() async -> CGSize? {
        guard let tracks = try? await loadTracks(withMediaType: .video) else { return nil }
        guard let track = tracks.first else { return nil }
        guard let size = try? await track.load(.naturalSize) else { return nil }
        return size
    }
}

你可以像这样使用它,

Task.init { 
    let videoSize = await videoView.naturalSize() ?? .zero
    DispatchQueue.main.async { [self] in 
        // do your thing 
    } 
} 

1
投票

@David_H 答案的 Swift 版本。

extension AVAsset {
    func resolutionSizeForLocalVideo() -> CGSize {
        var unionRect = CGRect.zero;
        for track in self.tracks(withMediaCharacteristic: .visual) {
            let trackRect = CGRect(x: 0, y: 0, width: 
            track.naturalSize.width, height: 
            track.naturalSize.height).applying(track.preferredTransform)
            unionRect = unionRect.union(trackRect)
            
        }
        return unionRect.size
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.