This commit is contained in:
parent
2a97ae1a40
commit
a0b318ad7b
|
@ -13,19 +13,20 @@ import SessionExporter
|
|||
import Nuke
|
||||
|
||||
extension AttachmentViewModel {
|
||||
func compressVideo(url: URL) async throws -> URL {
|
||||
func compressVideo(url: URL) async throws -> URL? {
|
||||
let urlAsset = AVURLAsset(url: url)
|
||||
|
||||
guard let track = urlAsset.tracks(withMediaType: .video).first else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let exporter = NextLevelSessionExporter(withAsset: urlAsset)
|
||||
exporter.outputFileType = .mp4
|
||||
|
||||
let isLandscape: Bool = {
|
||||
guard let track = urlAsset.tracks(withMediaType: .video).first else {
|
||||
return true
|
||||
}
|
||||
|
||||
let size = track.naturalSize.applying(track.preferredTransform)
|
||||
return abs(size.width) >= abs(size.height)
|
||||
}()
|
||||
|
||||
let preferredSize = try await preferredSizeFor(
|
||||
track: track,
|
||||
maxLongestSide: 1280
|
||||
)
|
||||
|
||||
let outputURL = try FileManager.default.createTemporaryFileURL(
|
||||
filename: UUID().uuidString,
|
||||
|
@ -40,8 +41,8 @@ extension AttachmentViewModel {
|
|||
]
|
||||
exporter.videoOutputConfiguration = [
|
||||
AVVideoCodecKey: AVVideoCodecType.h264,
|
||||
AVVideoWidthKey: NSNumber(integerLiteral: isLandscape ? 1280 : 720),
|
||||
AVVideoHeightKey: NSNumber(integerLiteral: isLandscape ? 720 : 1280),
|
||||
AVVideoWidthKey: NSNumber(floatLiteral: preferredSize.width),
|
||||
AVVideoHeightKey: NSNumber(floatLiteral: preferredSize.height),
|
||||
AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
|
||||
AVVideoCompressionPropertiesKey: compressionDict
|
||||
]
|
||||
|
@ -60,6 +61,27 @@ extension AttachmentViewModel {
|
|||
|
||||
return outputURL
|
||||
}
|
||||
|
||||
private func preferredSizeFor(track: AVAssetTrack, maxLongestSide: CGFloat) async throws -> CGSize {
|
||||
let trackSize = try await track.load(.naturalSize).applying(track.preferredTransform)
|
||||
let actualSize = CGSize(width: abs(trackSize.width), height: abs(trackSize.height))
|
||||
let isLandscape = actualSize.width >= actualSize.height
|
||||
|
||||
switch isLandscape {
|
||||
case false: // portrait mode, needs height altered eventually
|
||||
if actualSize.height > maxLongestSide {
|
||||
// reduce height, keep aspect ratio
|
||||
return CGSize(width: (maxLongestSide / (actualSize.height/actualSize.width)), height: maxLongestSide)
|
||||
}
|
||||
return actualSize
|
||||
case true: // landscape mode, needs width altered eventually
|
||||
if actualSize.width > maxLongestSide {
|
||||
// reduce width, keep aspect ratio
|
||||
return CGSize(width: maxLongestSide, height: (maxLongestSide * (actualSize.height/actualSize.width)))
|
||||
}
|
||||
return actualSize
|
||||
}
|
||||
}
|
||||
|
||||
private func exportVideo(by exporter: NextLevelSessionExporter) async throws -> URL {
|
||||
guard let outputURL = exporter.outputURL else {
|
||||
|
|
|
@ -145,7 +145,10 @@ final public class AttachmentViewModel: NSObject, ObservableObject, Identifiable
|
|||
case .video(let fileURL, let mimeType):
|
||||
self.output = output
|
||||
self.update(uploadState: .compressing)
|
||||
let compressedFileURL = try await compressVideo(url: fileURL)
|
||||
guard let compressedFileURL = try await compressVideo(url: fileURL) else {
|
||||
assertionFailure("Unable to compress video")
|
||||
return
|
||||
}
|
||||
output = .video(compressedFileURL, mimeType: mimeType)
|
||||
try? FileManager.default.removeItem(at: fileURL) // remove old file
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue