Learn more about scaling video files from our in-depth blog post.
The associated Xcode project implements a SwiftUI app for macOS and iOS that scales video files stored on your device or iCloud.
A default video file is provided to set the initial state of the app.
After a video is imported it is displayed in the VideoPlayer where it can be viewed, along with its scaled counterpart.
Select the scale factor from a slider.
The project is comprised of:
ScaleVideoApp
- The App for import, scale and export.ScaleVideoObservable
- An ObservableObject that manages the user interaction to scale and play video files.ScaleVideo
- The AVFoundation and vDSP code that reads, scales and writes video files.
Videos to scale are imported from Files using fileImporter and exported to Files using fileExporter.
The scaling is monitored with a ProgressView.
The video and scaled video can be played with a VideoPlayer.
Creates the ScaleAudio
object to perform the scaling operation and send progress back to the app.
The URL
of the video to scale is received from the file import operation and, if needed, downloaded with startDownloadingUbiquitousItem or security accessed with startAccessingSecurityScopedResource.
To facilitate exporting using fileExporter
a FileDocument named VideoDocument
is prepared with a FileWrapper created from the URL of the scaled video.
Scaling video is performed using AVFoundation and vDSP.
The ScaleVideo initializer init
:
init?(path : String, desiredDuration: Float64, frameRate: Int32, destination: String, progress: @escaping (CGFloat, CIImage?) -> Void, completion: @escaping (URL?, String?) -> Void)
Arguments:
-
path: String - The path of the video file to be scaled.
-
desiredDuration: Float64 - The desired duration in seconds of the scaled video.
-
frameRate: Int32 - The desired frame rate of the scaled video.
-
destination: String - The path of the scaled video file.
-
progress: Closure - A handler that is periodically executed to send progress images and values.
-
completion: Closure - A handler that is executed when the operation has completed to send a message of success or not.
Example usage is provided in the code:
func testScaleVideo() {
let fm = FileManager.default
let docsurl = try! fm.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let destinationPath = docsurl.appendingPathComponent("DefaultVideoScaled.mov").path
let scaleVideo = ScaleVideo(path: kDefaultURL.path, desiredDuration: 8, frameRate: 30, expedited: false, destination: destinationPath) { p, _ in
print("p = \(p)")
} completion: { result, error in
print("result = \(String(describing: result))")
}
scaleVideo?.start()
}