William Hu
William Hu

Reputation: 16189

How to get bitrate of a video from gallery by PhotosPicker?

I want to get the right bitrate of a video which shot by my iPhone. But I got the error:

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

here is my code:

Movie.swift (get the url)

 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
    }
}

Any suggestions? thanks.

EDIT 1

Thanks @lorem ipsum 's point. Then I moved the get bitrate into the importing closure, the bitrate is larger.

static var transferRepresentation: some TransferRepresentation {
        FileRepresentation(contentType: .data) { movie in
            SentTransferredFile(movie.url)
        } importing: { received in
            let bitrate = try? await getVb(from: received.file)
            print(bitrate)

            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
            }
            return Self.init(url: received.file)
        }
        
        
    }

The print is 4231527.5 actually the size is 1356000bps.

Then I tried copy the item to another path.

static var transferRepresentation: some TransferRepresentation {
        FileRepresentation(contentType: .data) { movie in
            SentTransferredFile(movie.url)
        } importing: { received in
            
            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)
        }

The pirate is 23000497 bps.

It's interesting why the size is larger? thanks!

Upvotes: 0

Views: 46

Answers (0)

Related Questions