From Remote URL
VideoEditor SDK supports loading fonts from a remote URL, this can be a resource hosted by a video hosting provider or your own servers. Although the editor supports adding assets with remote URLs, we highly recommend that you manage the download of remote resources yourself, since this gives you more control over the whole process.
Download fonts#
We construct a remote URL pointing the remote resource hosting the font we want to add and create a download task. Upon successful download we save it to a temporary location after checking if a file already exists at that location and removing it if necessary.
Dispatch to main queue#
In order to keep the UI responsive and prevent race conditions while the filter files are downloading, we dispatch to the main queue.
Here, we keep track of the finished download task and the local URL of the downloaded font by writing to a localURL
variable.
Create Font
object#
Font
object#Now that our custom font has finished downloading, we can pass the localURL
to the Font
constructor.
A Font
object is a simple collection of the metadata of a font, the fontName
, the displayName
and the url
for non system fonts.
We also create another system font using only the fontName
.
Add fonts to asset catalog#
In order to add the new fonts to our asset catalog, we first add the default items and then append our fonts to the fonts
array.
import UIKitimport VideoEditorSDKclass VideoAddFontsFromRemoteURLSwift: Example, VideoEditViewControllerDelegate {// Save a reference to the downloaded file to remove it when done.private var localURL: URL?// Although the editor supports adding assets with remote URLs, we highly recommend// that you manage the download of remote resources yourself, since this// gives you more control over the whole process. After successfully downloading// the files you should pass the local URLs to the asset catalog of the configuration.override func invokeExample() {// Create a `Video` from a URL to a video in the app bundle.let video = Video(url: Bundle.main.url(forResource: "Skater", withExtension: "mp4")!)// Download the custom font.guard let remoteURL = URL(string: "https://img.ly/static/example-assets/custom_font_raleway_regular.ttf") else {fatalError("Unable to parse URL.")}let downloadTask = URLSession.shared.downloadTask(with: remoteURL) { downloadURL, _, error inif let error = error {fatalError("There was an error downloading the file: \(error)")}if let downloadURL = downloadURL {// File was downloaded successfully. Saving it in the temporary directory.let temporaryDirectoryURL = FileManager.default.temporaryDirectorylet localURL = temporaryDirectoryURL.appendingPathComponent(remoteURL.lastPathComponent)if FileManager.default.fileExists(atPath: localURL.path) {// Remove the file at the destination if it already existstry? FileManager.default.removeItem(at: localURL)}try? FileManager.default.moveItem(at: downloadURL, to: localURL)// Dispatch to the main queue for any UI work// and to prevent race conditions.DispatchQueue.main.async {self.localURL = localURL// Create a reference to the custom font.let customFont = Font(url: localURL, displayName: "Raleway", fontName: "custom_font_raleway_regular", identifier: "custom_font_raleway_regular")// Create a reference to a system font.let systemFont = Font(displayName: "Helvetica", fontName: "Helvetica", identifier: "system_font_helvetica")// Create a `Configuration` object.let configuration = Configuration { builder in// In this example we are using the default assets for the asset catalog as a base.// However, you can also create an empty catalog as well which only contains your// custom assets.let assetCatalog = AssetCatalog.defaultItems// Add the custom fonts to the asset catalog.assetCatalog.fonts.append(contentsOf: [customFont, systemFont])// Use the new asset catalog for the configuration.builder.assetCatalog = assetCatalog}// Create the video editor. Make this class the delegate of it to handle export and cancelation.let videoEditViewController = VideoEditViewController(videoAsset: video, configuration: configuration)videoEditViewController.delegate = self// Reenable user interaction. In production you would want to dismiss a progress indicator for example.self.presentingViewController?.view.isUserInteractionEnabled = true// Present the video editor.videoEditViewController.modalPresentationStyle = .fullScreenself.presentingViewController?.present(videoEditViewController, animated: true, completion: nil)}}}// Disable user interaction while the download is active. In production you would want to show a progress indicator for example.presentingViewController?.view.isUserInteractionEnabled = false// Start the file downloaddownloadTask.resume()}// Removes the previously downloaded resources.private func removeResources() {if let localURL = localURL {try? FileManager.default.removeItem(at: localURL)}}// MARK: - VideoEditViewControllerDelegatefunc videoEditViewControllerShouldStart(_ videoEditViewController: VideoEditViewController, task: VideoEditorTask) -> Bool {// Implementing this method is optional. You can perform additional validation and interrupt the process by returning `false`.true}func videoEditViewControllerDidFinish(_ videoEditViewController: VideoEditViewController, result: VideoEditorResult) {// The user exported a new video successfully and the newly generated video is located at `result.output.url`. Dismissing the editor.presentingViewController?.dismiss(animated: true, completion: {self.removeResources()})}func videoEditViewControllerDidFail(_ videoEditViewController: VideoEditViewController, error: VideoEditorError) {// There was an error generating the video.print(error.localizedDescription)// Dismissing the editor.presentingViewController?.dismiss(animated: true, completion: {self.removeResources()})}func videoEditViewControllerDidCancel(_ videoEditViewController: VideoEditViewController) {// The user tapped on the cancel button within the editor. Dismissing the editor.presentingViewController?.dismiss(animated: true, completion: {self.removeResources()})}}