@@ -9,8 +9,8 @@ import SwiftTUI
99@main struct FXUpscale : AsyncParsableCommand {
1010 @Argument ( help: " The video file to upscale " , transform: URL . init ( fileURLWithPath: ) ) var url : URL
1111
12- @Option ( help: " The output file width " ) var width : Int
13- @Option ( help: " The output file height " ) var height : Int
12+ @Option ( help: " The output file width " ) var width : Int ?
13+ @Option ( help: " The output file height " ) var height : Int ?
1414
1515 mutating func run( ) async throws {
1616 guard FileManager . default. fileExists ( atPath: url. path) else {
@@ -26,16 +26,27 @@ import SwiftTUI
2626 throw ValidationError ( " File already exists at \( outputURL. path ( percentEncoded: false ) ) " )
2727 }
2828
29- guard width <= 7680 , height <= 7680 else {
30- throw ValidationError ( " Maximum supported width/height: 7680 " )
31- }
32-
3329 let asset = AVAsset ( url: url)
3430 guard let videoTrack = try await asset. loadTracks ( withMediaType: . video) . first else {
3531 throw ValidationError ( " Failed to get video track from input file " )
3632 }
3733
3834 let inputSize = try await videoTrack. load ( . naturalSize)
35+
36+ // 1. Use passed in width/height
37+ // 2. Use proportional width/height if only one is specified
38+ // 3. Default to 2x upscale
39+
40+ let width = width ??
41+ height. map { Int ( inputSize. width * ( CGFloat ( $0) / inputSize. height) ) } ??
42+ Int ( inputSize. width) * 2
43+ let height = height ??
44+ Int ( inputSize. height * ( CGFloat ( width) / inputSize. width) )
45+
46+ guard width <= 7680 , height <= 7680 else {
47+ throw ValidationError ( " Maximum supported width/height: 7680 " )
48+ }
49+
3950 let outputSize = CGSize ( width: width, height: height)
4051
4152 let videoComposition = AVMutableVideoComposition ( )
0 commit comments