import Foundation import Flutter import UIKit import AliyunVideoSDKPro public class CameraViewFactory: NSObject, FlutterPlatformViewFactory { var messenger: FlutterBinaryMessenger! public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView { return CameraView(withFrame: frame, viewIdentifier: viewId, arguments: args, binaryMessenger: messenger) } @objc public init(messenger: (NSObject & FlutterBinaryMessenger)?) { super.init() self.messenger = messenger } public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { return FlutterStandardMessageCodec.sharedInstance() } } public class CameraView: NSObject, FlutterPlatformView, AliyunIRecorderDelegate, AliyunIPlayerCallback, AliyunIExporterCallback, AliyunIRenderCallback { public func playerDidEnd() { } public func playProgress(_ playSec: Double, streamProgress streamSec: Double) { } public func playError(_ errorCode: Int32) { } public func seekDidEnd() { } public func playerDidStart() { } fileprivate var viewId: Int64! fileprivate var cameraView: UIView! fileprivate var channel: FlutterMethodChannel! fileprivate var recordPath: String? fileprivate var taskPath: String? fileprivate var recorder: AliyunIRecorder! fileprivate var composeResult: FlutterResult? public init(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger: FlutterBinaryMessenger) { super.init() self.viewId = viewId self.cameraView = UIView() self.cameraView.frame = UIScreen.main.bounds self.channel = FlutterMethodChannel(name: "flutter_ali_camera_\(viewId)", binaryMessenger: binaryMessenger) self.channel.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in if let this = self { this.onMethodCall(call: call, result: result) } }) } public func view() -> UIView { return self.cameraView } func onMethodCall(call: FlutterMethodCall, result: @escaping FlutterResult) { let args = call.arguments as? [String: Any] let method = call.method if call.method == "initializeSdk" { // initSdk(result) result(true) } else if call.method == "cleanAudioData" { let videoId = args!["videoId"] as! String let pathAudio = args!["pathAudio"] as! String deleteFileWithPrefix(folderPath: pathAudio, prefix: "\(videoId)_") result(true) } else if call.method == "getFilterParentPath" { print("path \(Bundle.main.path(forResource: "icon", ofType: "png"))") let url = Bundle.main.bundlePath result("\(url)/filter/") } else if method == "startPreview" { initCameraView() recorder?.clipManager?.deleteAllPart() recorder?.startPreview(withPositon: AliyunIRecorderCameraPosition.front) result(true) } else if method == "startPreview" { initCameraView() recorder?.clipManager?.deleteAllPart() recorder?.startPreview(withPositon: AliyunIRecorderCameraPosition.front) result(true) } else if method == "setRecordPath" { self.recordPath = args!["path"] as? String self.taskPath = args!["taskPath"] as? String result(true) } else if method == "onStop" { onStop() result(true) } else if method == "onResume" { recorder?.startPreview(withPositon: AliyunIRecorderCameraPosition.front) result(true) } else if method == "onDestory" { onStop() onDestory() result(true) } else if method == "switchCamera" { recorder.switchCameraPosition() result(true) } else if method == "setBeautyLevel" { let level = args!["level"] as! Int recorder.beautifyStatus = (level == 0) recorder.beautifyValue = Int32(level) result(true) } else if method == "startRecord" { let maxDuration = args!["maxDuration"] as! Int let videoId = args!["videoId"] as! String let index = args!["index"] as! Int let fileName = args!["fileName"] as! String if recorder?.clipManager?.videoAbsolutePaths != nil && recorder?.clipManager?.videoAbsolutePaths.count != 0 { recorder?.clipManager?.deletePart() } clearCacheVideo(videoId: videoId, index: index) recorder?.outputPath = self.recordPath! + "\(fileName).mp4" recorder?.clipManager?.maxDuration = CGFloat(Float(maxDuration) / 1000.0) recorder?.startRecording() result(true) } else if method == "stopRecord" { recorder?.stopRecording() result(true) } else if method == "finishRecord" { recorder?.finishRecording() result(true) } else if method == "setFilter" { let path: String? = args?["path"] as? String if path == nil || path?.count == 0 { // delete filter recorder?.deleteFilter() return } recorder?.apply(AliyunEffectFilter.init(file: path)) } else if method == "startCompose" { let outputPath = args!["outputPath"] as! String let bgmPath = args!["bgmPath"] as! String let paths = args!["paths"] as! [String] let durations = args!["durations"] as! [Int] composeResult = result startCompose(outputPath: outputPath, bgmPath: bgmPath, paths: paths, durations: durations) } else if method == "create"{ result(FlutterMethodNotImplemented) } } private func initCameraView() { recorder = AliyunIRecorder.init(delegate: self, videoSize: CGSize(width: 720, height: 1280)) recorder?.preview = self.cameraView recorder?.taskPath = self.taskPath recorder?.clipManager?.maxDuration = 0 } private func onStop() { recorder?.stopRecording() recorder?.stopPreview() } private func onDestory() { recorder?.destroy() recorder = nil cameraView = nil } var editor: AliyunEditor? private func startCompose(outputPath: String, bgmPath: String, paths: [String], durations: [Int]) { AliyunVideoSDKInfo.print() if durations.count != paths.count { return } // AliyunVideoSDKInfo.setLogLevel(AlivcLogLevel.debug) let importer = AliyunImporter.init(path: self.taskPath, outputSize: CGSize(width: 480, height: 720)) let param = AliyunVideoParam.init() param.fps = 30 param.gop = 30 param.videoQuality = AliyunVideoQuality.medium param.scaleMode = AliyunScaleMode.fill // 编码模式 param.codecType = AliyunVideoCodecType.hardware importer?.setVideoParam(param) for index in 0.. Int? { return Int(self) } func toFloat() -> Float? { return Float(self) } func toDouble() -> Double? { return Double(self) } //MARK:- 去除字符串两端的空白字符 func trim() -> String { return self.trimmingCharacters(in: CharacterSet.whitespaces) } func subString(to: Int) -> String { var to = to if to > self.count { to = self.count } return String(self.prefix(to)) } func subString(from: Int) -> String { if from >= self.count { return "" } let startIndex = self.index(self.startIndex, offsetBy: from) let endIndex = self.endIndex return String(self[startIndex.. String { if start < end { let startIndex = self.index(self.startIndex, offsetBy: start) let endIndex = self.index(self.startIndex, offsetBy: end) return String(self[startIndex..