mirror of
https://github.com/mastodon/mastodon-ios.git
synced 2025-01-31 17:45:17 +01:00
This commit is contained in:
parent
2a97ae1a40
commit
a0b318ad7b
@ -13,19 +13,20 @@ import SessionExporter
|
|||||||
import Nuke
|
import Nuke
|
||||||
|
|
||||||
extension AttachmentViewModel {
|
extension AttachmentViewModel {
|
||||||
func compressVideo(url: URL) async throws -> URL {
|
func compressVideo(url: URL) async throws -> URL? {
|
||||||
let urlAsset = AVURLAsset(url: url)
|
let urlAsset = AVURLAsset(url: url)
|
||||||
|
|
||||||
|
guard let track = urlAsset.tracks(withMediaType: .video).first else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
let exporter = NextLevelSessionExporter(withAsset: urlAsset)
|
let exporter = NextLevelSessionExporter(withAsset: urlAsset)
|
||||||
exporter.outputFileType = .mp4
|
exporter.outputFileType = .mp4
|
||||||
|
|
||||||
let isLandscape: Bool = {
|
let preferredSize = try await preferredSizeFor(
|
||||||
guard let track = urlAsset.tracks(withMediaType: .video).first else {
|
track: track,
|
||||||
return true
|
maxLongestSide: 1280
|
||||||
}
|
)
|
||||||
|
|
||||||
let size = track.naturalSize.applying(track.preferredTransform)
|
|
||||||
return abs(size.width) >= abs(size.height)
|
|
||||||
}()
|
|
||||||
|
|
||||||
let outputURL = try FileManager.default.createTemporaryFileURL(
|
let outputURL = try FileManager.default.createTemporaryFileURL(
|
||||||
filename: UUID().uuidString,
|
filename: UUID().uuidString,
|
||||||
@ -40,8 +41,8 @@ extension AttachmentViewModel {
|
|||||||
]
|
]
|
||||||
exporter.videoOutputConfiguration = [
|
exporter.videoOutputConfiguration = [
|
||||||
AVVideoCodecKey: AVVideoCodecType.h264,
|
AVVideoCodecKey: AVVideoCodecType.h264,
|
||||||
AVVideoWidthKey: NSNumber(integerLiteral: isLandscape ? 1280 : 720),
|
AVVideoWidthKey: NSNumber(floatLiteral: preferredSize.width),
|
||||||
AVVideoHeightKey: NSNumber(integerLiteral: isLandscape ? 720 : 1280),
|
AVVideoHeightKey: NSNumber(floatLiteral: preferredSize.height),
|
||||||
AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
|
AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
|
||||||
AVVideoCompressionPropertiesKey: compressionDict
|
AVVideoCompressionPropertiesKey: compressionDict
|
||||||
]
|
]
|
||||||
@ -61,6 +62,27 @@ extension AttachmentViewModel {
|
|||||||
return outputURL
|
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 {
|
private func exportVideo(by exporter: NextLevelSessionExporter) async throws -> URL {
|
||||||
guard let outputURL = exporter.outputURL else {
|
guard let outputURL = exporter.outputURL else {
|
||||||
throw AppError.badRequest
|
throw AppError.badRequest
|
||||||
|
@ -145,7 +145,10 @@ final public class AttachmentViewModel: NSObject, ObservableObject, Identifiable
|
|||||||
case .video(let fileURL, let mimeType):
|
case .video(let fileURL, let mimeType):
|
||||||
self.output = output
|
self.output = output
|
||||||
self.update(uploadState: .compressing)
|
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)
|
output = .video(compressedFileURL, mimeType: mimeType)
|
||||||
try? FileManager.default.removeItem(at: fileURL) // remove old file
|
try? FileManager.default.removeItem(at: fileURL) // remove old file
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user