1 import ABI49_0_0ExpoModulesCore 2 import AVFoundation 3 import UIKit 4 import CoreGraphics 5 6 public class VideoThumbnailsModule: Module { definitionnull7 public func definition() -> ModuleDefinition { 8 Name("ExpoVideoThumbnails") 9 10 AsyncFunction("getThumbnail", getVideoThumbnail).runOnQueue(.main) 11 } 12 getVideoThumbnailnull13 internal func getVideoThumbnail(sourceFilename: URL, options: VideoThumbnailsOptions) throws -> [String: Any] { 14 if sourceFilename.isFileURL { 15 guard let fileSystem = self.appContext?.fileSystem else { 16 throw Exceptions.FileSystemModuleNotFound() 17 } 18 19 guard fileSystem.permissions(forURI: sourceFilename).contains(.read) else { 20 throw FileSystemReadPermissionException(sourceFilename.absoluteString) 21 } 22 } 23 24 let asset = AVURLAsset.init(url: sourceFilename, options: ["AVURLAssetHTTPHeaderFieldsKey": options.headers]) 25 let generator = AVAssetImageGenerator.init(asset: asset) 26 27 generator.appliesPreferredTrackTransform = true 28 generator.requestedTimeToleranceBefore = CMTime.zero 29 generator.requestedTimeToleranceAfter = CMTime.zero 30 31 let time = CMTimeMake(value: options.time, timescale: 1000) 32 let imgRef = try generator.copyCGImage(at: time, actualTime: nil) 33 let thumbnail = UIImage.init(cgImage: imgRef) 34 let savedImageUrl = try saveImage(image: thumbnail, quality: options.quality) 35 36 return [ 37 "uri": savedImageUrl.absoluteString, 38 "width": thumbnail.size.width, 39 "height": thumbnail.size.height 40 ] 41 } 42 43 /** 44 Saves the image as a file. 45 */ saveImagenull46 internal func saveImage(image: UIImage, quality: Double) throws -> URL { 47 guard let fileSystem = self.appContext?.fileSystem else { 48 throw Exceptions.FileSystemModuleNotFound() 49 } 50 51 let directory = URL(fileURLWithPath: fileSystem.cachesDirectory).appendingPathComponent("VideoThumbnails") 52 let fileName = UUID().uuidString.appending(".jpg") 53 let fileUrl = directory.appendingPathComponent(fileName) 54 55 fileSystem.ensureDirExists(withPath: directory.path) 56 57 guard let data = image.jpegData(compressionQuality: CGFloat(quality)) else { 58 throw CorruptedImageDataException() 59 } 60 61 do { 62 try data.write(to: fileUrl, options: .atomic) 63 } catch let error { 64 throw ImageWriteFailedException(error.localizedDescription) 65 } 66 67 return fileUrl 68 } 69 } 70