如何通过PhotosPicker获取图库中视频的比特率?

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

我想获得用我的 iPhone 拍摄的视频的正确比特率。 但我得到了错误:

Failed to load asset tracks: The operation could not be completed

这是我的代码:

Movie.swift(获取网址)

 struct Movie: Transferable {
    let url: URL

    static var transferRepresentation: some TransferRepresentation {
        FileRepresentation(contentType: .data) { movie in
            SentTransferredFile(movie.url)
        } importing: { received in
            return Self.init(url: received.file)
        }
    }
}

ContentView.swift

  struct ContentView: View {
   
    @State private var selectedItem: PhotosPickerItem?
    @State var bitrate: Float?
    
    var body: some View {
        VStack {
            PhotosPicker("Select video", selection: $selectedItem, matching: .videos)
            if let bitrate {
                Text("\(bitrate)")
            }
        }
        .onChange(of: selectedItem) { _ in
            Task {
                if let movie = try? await selectedItem?.loadTransferable(type: Movie.self) {
                    do {
                        bitrate = try await getVb(from: movie.url)
                        print(bitrate)
                    } catch {
                        print(error)
                    }
                }
            }
        }
    }
    
    func getVb(from url: URL) async throws -> Float? {
        let asset = AVAsset(url: url)
        let videoTrack = try await asset.loadTracks(withMediaType: .video)
        let bit = try await videoTrack.first?.load(.estimatedDataRate)
        return bit
    }
}

有什么建议吗?谢谢。

swiftui avasset photospicker
1个回答
0
投票

导入 使用给定文件承诺实例化项目的闭包。 ReceivedTransferredFile 实例的 file 属性引用的文件仅保证存在于导入闭包中。如果您需要文件保存更长时间,请在导入闭包中复制一份。

强调提供的 URL“仅保证存在于导入闭包中”,这意味着在

received.file
运行时
bitrate = try await getVb(from: movie.url)
为空,因为它是在
loadTransferable
之后。

您可以通过将文件放在您可以控制的地方来克服这个问题。

struct Movie: Transferable {
    let url: URL

    static var transferRepresentation: some TransferRepresentation {
        FileRepresentation(contentType: .movie) { movie in
            SentTransferredFile(movie.url)
        } importing: { received in
            //Put the file in the caches directory
            let cacheURL = URL.cachesDirectory.appending(path: received.file.lastPathComponent)

            if FileManager.default.fileExists(atPath: cacheURL.path()) {
                try FileManager.default.removeItem(at: cacheURL)
            }

            try FileManager.default.copyItem(at: received.file, to: cacheURL)
            return Self.init(url: cacheURL)
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.