123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- //
- // AliCameraViewFactory.swift
- // AliyunOSSiOS
- //
- // Created by weihong huang on 2020/8/20.
- //
- import Flutter
- import Foundation
- import AliyunVideoSDKPro
- public class AliCameraViewFactory : NSObject, FlutterPlatformViewFactory {
- var messeneger: FlutterBinaryMessenger!
-
- public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
- return AliCameraView(frame: frame, viewIdentifier: viewId, arguments: args, binaryMessenger: self.messeneger)
- }
-
- init(messeneger: FlutterBinaryMessenger) {
- super.init()
- self.messeneger = messeneger
- }
-
- public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
- return FlutterStandardMessageCodec.sharedInstance()
- }
- }
- public class AliCameraView : NSObject, FlutterPlatformView, AliyunIRecorderDelegate, AliyunIExporterCallback {
- fileprivate var uiView: UIView = UIView()
- fileprivate var recorder: AliyunIRecorder!
- fileprivate var methodChannel: FlutterMethodChannel!
- fileprivate var taskPath: String!
- fileprivate var aliyunEditor: AliyunEditor!
- fileprivate var exportResult: FlutterResult!
-
- init(frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger: FlutterBinaryMessenger) {
- super.init()
- // init view size
- let dict = args as! [String: Any]
- self.uiView.frame = CGRect.init(x: dict["x"] as? Float64 ?? 0,
- y: dict["y"] as? Float64 ?? 0,
- width: dict["width"] as? Float64 ?? Float64(UIScreen.main.bounds.width),
- height: dict["height"] as? Float64 ?? Float64(UIScreen.main.bounds.height))
- // init method channel
- self.methodChannel = FlutterMethodChannel(name: "com.i2edu.cameraLib/camera_view_\(viewId)", binaryMessenger: binaryMessenger)
- self.methodChannel?.setMethodCallHandler ({
- [weak self]
- (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
- if let this = self {
- this.onMethonCall(call: call, result: result)
- }
- })
- }
-
- public func view() -> UIView {
- return self.uiView
- }
-
- func onMethonCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
- let args = call.arguments as? [String: Any]
- switch call.method {
- case "create":
- let recordOptions = args?["recordOption"] as? [String: Any]
- let taskPath = args?["iosTaskPath"] as! String
- do {
- try setUpCameraView(recordOption: recordOptions!, taskPath: taskPath)
- result(true)
- } catch {
- result(false)
- }
- break
- case "startPreview":
- do {
- try startPreview()
- result(true)
- } catch {
- result(false)
- }
- break;
- case "stopPreview":
- do {
- try stopPreview()
- result(true)
- } catch {
- result(false)
- }
- break;
- case "switchCamera":
- do {
- try switchCamera()
- result(true)
- } catch {
- result(false)
- }
- break;
- case "setBeauty":
- do {
- try setBeauty(level: args?["level"] as? Int32 ?? 0)
- result(true)
- } catch {
- result(false)
- }
- break;
- case "setFilter":
- do {
- try setFilter(path: args?["path"] as? String)
- result(true)
- } catch {
- result(false)
- }
- break;
- case "startRecord":
- do {
- try startRecord(
- maxDuration: args?["max"] as! Int32,
- recordPath: args?["recordPath"] as! String)
- result(true)
- } catch {
- result(FlutterError.init(code: "1001", message: error.localizedDescription, details: nil))
- }
- break
- case "startCompose":
- do {
- self.exportResult = result
- let composeOption = args?["composeOption"] as! [String: Any]
- try startCompose(
- outputPath: args?["outputPath"] as! String,
- bgmPath: args?["bgmPath"] as? String,
- paths: args?["paths"] as! [String],
- durations: args?["durations"] as! [Int32],
- composeOption: composeOption
- )
- } catch {
- result(FlutterError.init(code: "1002", message: error.localizedDescription, details: nil))
- }
- break
- case "onDestroy":
- do {
- try onDestroy()
- result(true)
- } catch {
- result(false)
- }
- break
- default:
- result(FlutterMethodNotImplemented)
- }
- }
-
- func setUpCameraView(recordOption: [String: Any], taskPath: String) throws {
- self.taskPath = taskPath
- self.recorder = AliyunIRecorder.init(delegate: self, videoSize: CGSize(width: recordOption["videoWidth"] as! Int, height: recordOption["videoHeight"] as! Int))
- let keys = recordOption.keys
- if (keys.contains("fps")) {
- self.recorder.recordFps = recordOption["fps"] as! Int32
- }
- if (keys.contains("videoCodecs")) {
- if (recordOption["videoCodecs"] as! Int == 0) {
- self.recorder.encodeMode = 0
- } else {
- self.recorder.encodeMode = 1
- }
- }
- if (keys.contains("quality")) {
- self.recorder.videoQuality = AliyunVideoQuality.init(rawValue: recordOption["quality"] as! Int) ?? AliyunVideoQuality.medium
- }
- if (keys.contains("videoBitrate")) {
- self.recorder.bitrate = recordOption["videoBitrate"] as! Int32
- }
- if (keys.contains("gop")) {
- self.recorder.gop = recordOption["gop"] as! Int32
- }
-
- self.recorder?.beautifyStatus = false
- self.recorder?.beautifyValue = 0
- self.recorder?.preview = self.uiView
- }
-
- func startPreview() throws {
- self.recorder?.startPreview(withPositon: AliyunIRecorderCameraPosition.front)
- }
-
- func stopPreview() throws {
- self.recorder?.stopPreview()
- }
-
- func switchCamera() throws {
- self.recorder?.switchCameraPosition()
- }
-
- func setBeauty(level: Int32) throws {
- self.recorder?.beautifyStatus = level != 0
- self.recorder?.beautifyValue = level
- }
-
- func setFilter(path: String?) throws {
- if path == nil || path?.count == 0 {
- recorder?.deleteFilter()
- } else {
- self.recorder?.apply(AliyunEffectFilter.init(file: path))
- }
- }
-
- func startRecord(maxDuration: Int32, recordPath: String) throws {
- recorder?.taskPath = taskPath
- recorder?.clipManager?.deleteAllPart()
- recorder?.outputPath = recordPath
- recorder?.clipManager?.maxDuration = CGFloat(Float(maxDuration) / 1000.0)
- recorder?.startRecording()
- }
-
- func startCompose(outputPath: String, bgmPath: String?, paths: [String], durations: [Int32], composeOption: [String: Any]) throws {
- // set up AliyunImporter
- let importer = AliyunImporter.init(
- path: self.taskPath,
- outputSize: CGSize(width: composeOption["outputWidth"] as! CGFloat, height: composeOption["outputHeight"] as! CGFloat))
- let composeParam = AliyunVideoParam.init()
- let keys = composeOption.keys
- if keys.contains("gop") {
- composeParam.gop = composeOption["gop"] as! Int32
- }
- if keys.contains("bitrate") {
- composeParam.bitrate = composeOption["bitrate"] as! Int32
- }
- if keys.contains("frameRate") {
- composeParam.fps = composeOption["frameRate"] as! Int32
- }
- if keys.contains("videoCodecs") {
- var codecType:AliyunVideoCodecType
- let type = composeOption["videoCodecs"] as! Int32
- if type == 0 {
- codecType = AliyunVideoCodecType.hardware
- } else if type == 1 {
- codecType = AliyunVideoCodecType.openh264
- } else if type == 2 {
- codecType = AliyunVideoCodecType.fFmpeg
- } else {
- codecType = AliyunVideoCodecType.typeAuto
- }
- composeParam.codecType = codecType
- }
- if keys.contains("quality") {
- composeParam.videoQuality =
- AliyunVideoQuality.init(rawValue: composeOption["quality"] as! Int) ?? AliyunVideoQuality.medium
- }
- if keys.contains("scaleMode") {
- composeParam.scaleMode =
- AliyunScaleMode.init(rawValue: composeOption["scaleMode"] as! Int) ?? AliyunScaleMode.fit
- }
- for index in 0..<paths.count {
- importer?.addMediaClip(AliyunClip.init(videoPath: paths[index], animDuration: 0))
- }
- importer?.setVideoParam(composeParam)
- importer?.generateProjectConfigure()
- // set up AliyunEditor
- self.aliyunEditor = AliyunEditor.init(path: self.taskPath, preview: nil)
- if bgmPath != nil && bgmPath?.count != 0 {
- self.aliyunEditor.apply(AliyunEffectMusic.init(file: bgmPath))
- }
- self.aliyunEditor.delegate = self
- self.aliyunEditor.startEdit()
-
- let exporter = self.aliyunEditor.getExporter()
- exporter?.startExport(outputPath)
- }
-
- func onDestroy() throws {
- try stopPreview()
- recorder?.stopRecording()
- recorder?.destroy()
- recorder = nil
- }
-
- // ----- record delegate
-
- public func recorderDeviceAuthorization(_ status: AliyunIRecorderDeviceAuthor) {
- if status == AliyunIRecorderDeviceAuthor.enabled {
- print("sdk enabled")
- } else {
- print("sdk disabled")
- }
- }
-
- public func recorderVideoDuration(_ duration: CGFloat) {
- print("record update \(duration)")
- methodChannel.invokeMethod("recordUpdate", arguments: ["progress": Int(duration * 1000)])
- }
-
- public func recorderDidStopWithMaxDuration() {
- print("record stop with max duration")
- recorder?.finishRecording()
- }
-
- public func recorderDidFinishRecording() {
- print("record completed")
- methodChannel.invokeMethod("recordUpdate", arguments: ["progress": Int((recorder?.clipManager?.maxDuration ?? 0) * 1000), "path": recorder?.outputPath ?? ""])
- }
-
- public func recoderError(_ error: Error!) {
- print("record error \(error.localizedDescription)")
- recorder?.finishRecording()
- }
-
- // ----- export delegate
- public func exporterDidStart() {
- print("export did start")
- }
-
- public func exportProgress(_ progress: Float) {
- print("export progress \(progress)")
- }
-
- public func exportError(_ errorCode: Int32) {
- print("export error \(errorCode)")
- exportResult(false)
- }
-
- public func exporterDidEnd(_ outputPath: String!) {
- print("export did end \(outputPath ?? "")")
- exportResult(true)
- }
-
- public func exporterDidCancel() {
- print("export did cancel")
- }
- }
- extension AliCameraView : AliyunIPlayerCallback, AliyunIRenderCallback{
- public func playerDidEnd() {
- }
-
- public func playProgress(_ playSec: Double, streamProgress streamSec: Double) {
- }
-
- public func playError(_ errorCode: Int32) {
- }
-
- public func seekDidEnd() {
- }
-
- public func playerDidStart() {
- }
- }
|