diff --git a/APIDiffs/api-diffs-1.10.0.md b/APIDiffs/api-diffs-1.10.0.md new file mode 100644 index 00000000..01b4ee7c --- /dev/null +++ b/APIDiffs/api-diffs-1.10.0.md @@ -0,0 +1,38 @@ +# PLShortVideoKit 1.9.0 to 1.10.0 API Differences + +## General Headers + +``` +PLSUploaderConfiguration.h +``` + +- *Added* @property (nonatomic, strong) NSDictionary * _Nullable params; +- *Added* - (instancetype _Nullable)initWithToken:(NSString * _Nonnull)token videoKey:(NSString * _Nullable)videoKey https:(BOOL)https recorder:(NSString * _Nullable)recorder params:(NSDictionary * _Nullable)params; + + +``` +Added Class PLSTextSetting +Added Class PLSImageSetting +Added Class PLSFadeTranstion +Added Class PLSScaleTransition +Added Class PLSRotateTransition +Added Class PLSPositionTransition +Added Class PLSTransitionMaker + +Added Class PLSRangeMedia +Added Class PLSRangeMovieExport +Added Class PLSRangeMediaTools +``` + + + + + + + + + + + + + diff --git a/Example/PLShortVideoKitDemo.xcodeproj/project.pbxproj b/Example/PLShortVideoKitDemo.xcodeproj/project.pbxproj index fbb84a61..b1e1833e 100644 --- a/Example/PLShortVideoKitDemo.xcodeproj/project.pbxproj +++ b/Example/PLShortVideoKitDemo.xcodeproj/project.pbxproj @@ -182,7 +182,6 @@ 0A9CB4EF1EF042FB00EABA76 /* btn_sound@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A9CB4EB1EF042FB00EABA76 /* btn_sound@3x.png */; }; 0A9E5F731FC7E2390002FB8B /* counter-6s.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 0A9E5F721FC7E2380002FB8B /* counter-6s.m4a */; }; 0A9E5F751FC7F4350002FB8B /* counter-35s.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 0A9E5F741FC7F4340002FB8B /* counter-35s.m4a */; }; - 0AB74A0E201D754A007C22AB /* video_draft_test.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 0AB74A0D201D7549007C22AB /* video_draft_test.mp4 */; }; 0ACE7C361ED8B072002FF4C9 /* PLSClipMovieView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ACE7C2C1ED8B072002FF4C9 /* PLSClipMovieView.m */; }; 0ACE7C371ED8B072002FF4C9 /* PLSDeleteButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ACE7C2E1ED8B072002FF4C9 /* PLSDeleteButton.m */; }; 0ACE7C381ED8B072002FF4C9 /* PLSEditVideoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ACE7C301ED8B072002FF4C9 /* PLSEditVideoCell.m */; }; @@ -217,6 +216,24 @@ 0AF33C0E1F7180D200CCFB42 /* mv4.png in Resources */ = {isa = PBXBuildFile; fileRef = 0AF33C001F7180D200CCFB42 /* mv4.png */; }; 0AF33C0F1F7180D200CCFB42 /* plsMVs.json in Resources */ = {isa = PBXBuildFile; fileRef = 0AF33C011F7180D200CCFB42 /* plsMVs.json */; }; 0AF8AA632018A5610077123D /* SceneEffectTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AF8AA602018A5610077123D /* SceneEffectTools.m */; }; + 766CEB95205BD80100F708D7 /* TransitionModelSelectView.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB83205BD80000F708D7 /* TransitionModelSelectView.m */; }; + 766CEB96205BD80100F708D7 /* TransitionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB84205BD80000F708D7 /* TransitionViewController.m */; }; + 766CEB97205BD80100F708D7 /* TransitionModelMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB85205BD80000F708D7 /* TransitionModelMaker.m */; }; + 766CEB98205BD80100F708D7 /* TransitionTextEditViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB86205BD80000F708D7 /* TransitionTextEditViewController.m */; }; + 766CEB99205BD80100F708D7 /* MulitClipViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB89205BD80100F708D7 /* MulitClipViewController.m */; }; + 766CEB9A205BD80100F708D7 /* MulitPhotoAlbumViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB8A205BD80100F708D7 /* MulitPhotoAlbumViewController.m */; }; + 766CEB9B205BD80100F708D7 /* MulitEditViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB8C205BD80100F708D7 /* MulitEditViewController.m */; }; + 766CEB9C205BD80100F708D7 /* BaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB8D205BD80100F708D7 /* BaseViewController.m */; }; + 766CEB9D205BD80100F708D7 /* PLSPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB8E205BD80100F708D7 /* PLSPlayerView.m */; }; + 766CEB9E205BD80100F708D7 /* PLSClipMulitMediaView.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEB91205BD80100F708D7 /* PLSClipMulitMediaView.m */; }; + 766CEBA1205BD85F00F708D7 /* H265MovieViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 766CEBA0205BD85E00F708D7 /* H265MovieViewController.m */; }; + 766CEBA3205BD8CC00F708D7 /* video_draft_test.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 766CEBA2205BD8CC00F708D7 /* video_draft_test.mp4 */; }; + 766CEBA5205BD8FD00F708D7 /* h265_video in Resources */ = {isa = PBXBuildFile; fileRef = 766CEBA4205BD8FD00F708D7 /* h265_video */; }; + 766CEBAC205BD91400F708D7 /* zcool-gdh.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 766CEBA7205BD91400F708D7 /* zcool-gdh.ttf */; }; + 766CEBAD205BD91400F708D7 /* HappyZcool-2016.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 766CEBA8205BD91400F708D7 /* HappyZcool-2016.ttf */; }; + 766CEBAE205BD91400F708D7 /* green_quot.png in Resources */ = {isa = PBXBuildFile; fileRef = 766CEBA9205BD91400F708D7 /* green_quot.png */; }; + 766CEBAF205BD91400F708D7 /* transition_black.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 766CEBAA205BD91400F708D7 /* transition_black.mp4 */; }; + 766CEBB0205BD91400F708D7 /* pink_line.png in Resources */ = {isa = PBXBuildFile; fileRef = 766CEBAB205BD91400F708D7 /* pink_line.png */; }; 9343A8C01F66763A007213BD /* Time_Machine_No_Reverser.png in Resources */ = {isa = PBXBuildFile; fileRef = 9343A8BE1F66763A007213BD /* Time_Machine_No_Reverser.png */; }; 9343A8C11F66763A007213BD /* Time_Machine_Reverser.png in Resources */ = {isa = PBXBuildFile; fileRef = 9343A8BF1F66763A007213BD /* Time_Machine_Reverser.png */; }; C35043641FB3152600F9633D /* draft_video.png in Resources */ = {isa = PBXBuildFile; fileRef = C35043631FB3121E00F9633D /* draft_video.png */; }; @@ -714,7 +731,6 @@ 0A9CB4EB1EF042FB00EABA76 /* btn_sound@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "btn_sound@3x.png"; path = "images/btn_sound@3x.png"; sourceTree = ""; }; 0A9E5F721FC7E2380002FB8B /* counter-6s.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; name = "counter-6s.m4a"; path = "musics/counter-6s.m4a"; sourceTree = ""; }; 0A9E5F741FC7F4340002FB8B /* counter-35s.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; name = "counter-35s.m4a"; path = "musics/counter-35s.m4a"; sourceTree = ""; }; - 0AB74A0D201D7549007C22AB /* video_draft_test.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; name = video_draft_test.mp4; path = videos/video_draft_test.mp4; sourceTree = ""; }; 0ACE7C2B1ED8B072002FF4C9 /* PLSClipMovieView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSClipMovieView.h; sourceTree = ""; }; 0ACE7C2C1ED8B072002FF4C9 /* PLSClipMovieView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSClipMovieView.m; sourceTree = ""; }; 0ACE7C2D1ED8B072002FF4C9 /* PLSDeleteButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSDeleteButton.h; sourceTree = ""; }; @@ -760,6 +776,35 @@ 0AF8AA622018A5610077123D /* SceneEffectTools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneEffectTools.h; sourceTree = ""; }; 29048327CD6F75BD8D75B80B /* Pods-PLShortVideoKitDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PLShortVideoKitDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo.debug.xcconfig"; sourceTree = ""; }; 57AEAFA0012D959C08AB23AE /* libPods-PLShortVideoKitDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PLShortVideoKitDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 766CEB80205BD80000F708D7 /* TransitionTextEditViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransitionTextEditViewController.h; sourceTree = ""; }; + 766CEB81205BD80000F708D7 /* TransitionModelMaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransitionModelMaker.h; sourceTree = ""; }; + 766CEB82205BD80000F708D7 /* TransitionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransitionViewController.h; sourceTree = ""; }; + 766CEB83205BD80000F708D7 /* TransitionModelSelectView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransitionModelSelectView.m; sourceTree = ""; }; + 766CEB84205BD80000F708D7 /* TransitionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransitionViewController.m; sourceTree = ""; }; + 766CEB85205BD80000F708D7 /* TransitionModelMaker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransitionModelMaker.m; sourceTree = ""; }; + 766CEB86205BD80000F708D7 /* TransitionTextEditViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransitionTextEditViewController.m; sourceTree = ""; }; + 766CEB87205BD80000F708D7 /* TransitionModelSelectView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransitionModelSelectView.h; sourceTree = ""; }; + 766CEB89205BD80100F708D7 /* MulitClipViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MulitClipViewController.m; sourceTree = ""; }; + 766CEB8A205BD80100F708D7 /* MulitPhotoAlbumViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MulitPhotoAlbumViewController.m; sourceTree = ""; }; + 766CEB8B205BD80100F708D7 /* PLSClipMulitMediaView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSClipMulitMediaView.h; sourceTree = ""; }; + 766CEB8C205BD80100F708D7 /* MulitEditViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MulitEditViewController.m; sourceTree = ""; }; + 766CEB8D205BD80100F708D7 /* BaseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseViewController.m; sourceTree = ""; }; + 766CEB8E205BD80100F708D7 /* PLSPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSPlayerView.m; sourceTree = ""; }; + 766CEB8F205BD80100F708D7 /* MulitClipViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MulitClipViewController.h; sourceTree = ""; }; + 766CEB90205BD80100F708D7 /* MulitEditViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MulitEditViewController.h; sourceTree = ""; }; + 766CEB91205BD80100F708D7 /* PLSClipMulitMediaView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSClipMulitMediaView.m; sourceTree = ""; }; + 766CEB92205BD80100F708D7 /* MulitPhotoAlbumViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MulitPhotoAlbumViewController.h; sourceTree = ""; }; + 766CEB93205BD80100F708D7 /* BaseViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseViewController.h; sourceTree = ""; }; + 766CEB94205BD80100F708D7 /* PLSPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSPlayerView.h; sourceTree = ""; }; + 766CEB9F205BD85E00F708D7 /* H265MovieViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = H265MovieViewController.h; sourceTree = ""; }; + 766CEBA0205BD85E00F708D7 /* H265MovieViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = H265MovieViewController.m; sourceTree = ""; }; + 766CEBA2205BD8CC00F708D7 /* video_draft_test.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; name = video_draft_test.mp4; path = test_videos/video_draft_test.mp4; sourceTree = ""; }; + 766CEBA4205BD8FD00F708D7 /* h265_video */ = {isa = PBXFileReference; lastKnownFileType = folder; name = h265_video; path = test_videos/h265_video; sourceTree = ""; }; + 766CEBA7205BD91400F708D7 /* zcool-gdh.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "zcool-gdh.ttf"; sourceTree = ""; }; + 766CEBA8205BD91400F708D7 /* HappyZcool-2016.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "HappyZcool-2016.ttf"; sourceTree = ""; }; + 766CEBA9205BD91400F708D7 /* green_quot.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = green_quot.png; sourceTree = ""; }; + 766CEBAA205BD91400F708D7 /* transition_black.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = transition_black.mp4; sourceTree = ""; }; + 766CEBAB205BD91400F708D7 /* pink_line.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pink_line.png; sourceTree = ""; }; 85B60FAE619932ED649E6840 /* Pods-PLShortVideoKitDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PLShortVideoKitDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo.release.xcconfig"; sourceTree = ""; }; 9343A8BE1F66763A007213BD /* Time_Machine_No_Reverser.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Time_Machine_No_Reverser.png; path = images/Time_Machine_No_Reverser.png; sourceTree = ""; }; 9343A8BF1F66763A007213BD /* Time_Machine_Reverser.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Time_Machine_Reverser.png; path = images/Time_Machine_Reverser.png; sourceTree = ""; }; @@ -1598,6 +1643,8 @@ C3A78F901F95F61000C3F2D6 /* EasyARSDK */, C3F91D2D1F1CBD4900698322 /* KiwiFaceSDK */, 0ACE7C281ED8B072002FF4C9 /* UI+Tools */, + 766CEB88205BD80100F708D7 /* SegmentEffects */, + 766CEB7F205BD80000F708D7 /* Transition */, 0A9435821E6CA2E2008845A3 /* AppDelegate.h */, 0A9435831E6CA2E2008845A3 /* AppDelegate.m */, 0A9435851E6CA2E2008845A3 /* ViewController.h */, @@ -1612,6 +1659,8 @@ 0A398F6B1ED6259000996229 /* PhotoAlbumViewController.m */, 0A6340281F15C9C9005ADF6C /* MovieTransCodeViewController.h */, 0A6340291F15C9C9005ADF6C /* MovieTransCodeViewController.m */, + 766CEB9F205BD85E00F708D7 /* H265MovieViewController.h */, + 766CEBA0205BD85E00F708D7 /* H265MovieViewController.m */, 0A398F6E1ED625DD00996229 /* ClipMovieViewController.h */, 0A398F6F1ED625DD00996229 /* ClipMovieViewController.m */, 0A52C1911E9C987900561F37 /* EditViewController.h */, @@ -1634,6 +1683,8 @@ 0A94357F1E6CA2E2008845A3 /* Supporting Files */ = { isa = PBXGroup; children = ( + 766CEBA6205BD91400F708D7 /* TransitionResources */, + 766CEBA4205BD8FD00F708D7 /* h265_video */, 0AF33BF41F7180D100CCFB42 /* 爱马仕.mp4 */, 0AF33BF51F7180D100CCFB42 /* 爱马仕轨迹.mp4 */, 0AF33BF61F7180D100CCFB42 /* 川久保玲.mp4 */, @@ -1648,8 +1699,8 @@ 0AF33BFF1F7180D200CCFB42 /* mv3.png */, 0AF33C001F7180D200CCFB42 /* mv4.png */, 0AF33C011F7180D200CCFB42 /* plsMVs.json */, - 0AB74A0D201D7549007C22AB /* video_draft_test.mp4 */, 0AE8ACA31F065F42006166E2 /* If_I_Had_a_Chicken.m4a */, + 766CEBA2205BD8CC00F708D7 /* video_draft_test.mp4 */, 0A9E5F721FC7E2380002FB8B /* counter-6s.m4a */, 0A9E5F741FC7F4340002FB8B /* counter-35s.m4a */, 0AE8AC9A1F065DCD006166E2 /* Fire_Breather.m4a */, @@ -1795,6 +1846,52 @@ name = Pods; sourceTree = ""; }; + 766CEB7F205BD80000F708D7 /* Transition */ = { + isa = PBXGroup; + children = ( + 766CEB80205BD80000F708D7 /* TransitionTextEditViewController.h */, + 766CEB81205BD80000F708D7 /* TransitionModelMaker.h */, + 766CEB82205BD80000F708D7 /* TransitionViewController.h */, + 766CEB83205BD80000F708D7 /* TransitionModelSelectView.m */, + 766CEB84205BD80000F708D7 /* TransitionViewController.m */, + 766CEB85205BD80000F708D7 /* TransitionModelMaker.m */, + 766CEB86205BD80000F708D7 /* TransitionTextEditViewController.m */, + 766CEB87205BD80000F708D7 /* TransitionModelSelectView.h */, + ); + path = Transition; + sourceTree = ""; + }; + 766CEB88205BD80100F708D7 /* SegmentEffects */ = { + isa = PBXGroup; + children = ( + 766CEB89205BD80100F708D7 /* MulitClipViewController.m */, + 766CEB8A205BD80100F708D7 /* MulitPhotoAlbumViewController.m */, + 766CEB8B205BD80100F708D7 /* PLSClipMulitMediaView.h */, + 766CEB8C205BD80100F708D7 /* MulitEditViewController.m */, + 766CEB8D205BD80100F708D7 /* BaseViewController.m */, + 766CEB8E205BD80100F708D7 /* PLSPlayerView.m */, + 766CEB8F205BD80100F708D7 /* MulitClipViewController.h */, + 766CEB90205BD80100F708D7 /* MulitEditViewController.h */, + 766CEB91205BD80100F708D7 /* PLSClipMulitMediaView.m */, + 766CEB92205BD80100F708D7 /* MulitPhotoAlbumViewController.h */, + 766CEB93205BD80100F708D7 /* BaseViewController.h */, + 766CEB94205BD80100F708D7 /* PLSPlayerView.h */, + ); + path = SegmentEffects; + sourceTree = ""; + }; + 766CEBA6205BD91400F708D7 /* TransitionResources */ = { + isa = PBXGroup; + children = ( + 766CEBA7205BD91400F708D7 /* zcool-gdh.ttf */, + 766CEBA8205BD91400F708D7 /* HappyZcool-2016.ttf */, + 766CEBA9205BD91400F708D7 /* green_quot.png */, + 766CEBAA205BD91400F708D7 /* transition_black.mp4 */, + 766CEBAB205BD91400F708D7 /* pink_line.png */, + ); + path = TransitionResources; + sourceTree = ""; + }; 897018225EF668D16731032B /* Frameworks */ = { isa = PBXGroup; children = ( @@ -2713,6 +2810,7 @@ 0A398F751ED62A1500996229 /* btn_banner_a@2x.png in Resources */, 0A4393F51FF662C100608588 /* lsq_filter_thumb_Forest01.jpg in Resources */, 0A4393E21FF662C100608588 /* lsq_filter_thumb_Leica.jpg in Resources */, + 766CEBA5205BD8FD00F708D7 /* h265_video in Resources */, C3F91F7D1F1CBD4900698322 /* stickers_gift.json in Resources */, C3F21A421F7246C3004D76FB /* toasterOverlayMapWarm.png in Resources */, 0A06925C1E8A3C720035CB7B /* btn_del_active_a@3x.png in Resources */, @@ -2726,6 +2824,7 @@ C3F219981F7246AE004D76FB /* huiquan@2x.png in Resources */, C3F219861F7246AE004D76FB /* distorting mirror@3x.png in Resources */, 0A1E2CE71E8CAF8C002C9296 /* btn_record_shine@2x.png in Resources */, + 766CEBA3205BD8CC00F708D7 /* video_draft_test.mp4 in Resources */, 0A1E2CF41E8CAF8C002C9296 /* qiniu_logo.png in Resources */, C3F21A3D1F7246C3004D76FB /* sutroEdgeBurn.png in Resources */, C3F219AB1F7246AE004D76FB /* presentSticker_sys@3x.png in Resources */, @@ -2781,6 +2880,7 @@ 0A94DFCF1E6DF5D2007BDD0D /* delete.png in Resources */, C3F219991F7246AE004D76FB /* huiquan@3x.png in Resources */, C3F2199B1F7246AE004D76FB /* isoff@3x.png in Resources */, + 766CEBAC205BD91400F708D7 /* zcool-gdh.ttf in Resources */, C3F219921F7246AE004D76FB /* gesturesSticker_sys@2x.png in Resources */, C3F21A461F7246C3004D76FB /* vignetteMap.png in Resources */, 0A94DFD01E6DF5D2007BDD0D /* flash_close.png in Resources */, @@ -2797,10 +2897,12 @@ C3F219C51F7246AE004D76FB /* xiazai@2x.png in Resources */, C3F219961F7246AE004D76FB /* huangquan@2x.png in Resources */, C3F21A211F7246C3004D76FB /* brannanProcess.png in Resources */, + 766CEBB0205BD91400F708D7 /* pink_line.png in Resources */, C3F219A01F7246AE004D76FB /* mask@2x.png in Resources */, 0A9CB4EE1EF042FB00EABA76 /* btn_sound@2x.png in Resources */, 0A4393E11FF662C100608588 /* video_style_default_btn_sticker@2x.png in Resources */, 0A0692481E8A3B590035CB7B /* btn_bar_next_a@3x.png in Resources */, + 766CEBAF205BD91400F708D7 /* transition_black.mp4 in Resources */, C3F2199A1F7246AE004D76FB /* isoff@2x.png in Resources */, 0A4393E51FF662C100608588 /* lsq_filter_thumb_sugar.jpg in Resources */, 0A1E32731E8CDED8002C9296 /* Effects4.png in Resources */, @@ -2810,6 +2912,7 @@ 0A4394001FF662C100608588 /* lsq_filter_thumb_Grapefruit01.jpg in Resources */, 0A09F0B0201ABE4F00B585D9 /* btn_revocation@2x.png in Resources */, 0A0692511E8A3B590035CB7B /* btn_camera_done_b@2x.png in Resources */, + 766CEBAE205BD91400F708D7 /* green_quot.png in Resources */, C3F219881F7246AE004D76FB /* download@3x.png in Resources */, C3F219A71F7246AE004D76FB /* off@3x.png in Resources */, 0A06924C1E8A3B590035CB7B /* btn_camera_cancel_a@3x.png in Resources */, @@ -2851,7 +2954,6 @@ C3F219B11F7246AE004D76FB /* quanjumeiyanliang@3x.png in Resources */, 0AE8AC9F1F065DCD006166E2 /* Fire_Breather.m4a in Resources */, 9343A8C11F66763A007213BD /* Time_Machine_Reverser.png in Resources */, - 0AB74A0E201D754A007C22AB /* video_draft_test.mp4 in Resources */, 0AF25339201D771800FCD6C8 /* PLShortVideoKit.bundle in Resources */, C3A78F981F95F61000C3F2D6 /* arScene.js in Resources */, C3F21A441F7246C3004D76FB /* valenciaGradientMap.png in Resources */, @@ -2913,6 +3015,7 @@ 0A398F761ED62A1500996229 /* btn_banner_a@3x.png in Resources */, C3F219B01F7246AE004D76FB /* quanjumeiyanliang@2x.png in Resources */, C3F21A2D1F7246C3004D76FB /* hefeMap.png in Resources */, + 766CEBAD205BD91400F708D7 /* HappyZcool-2016.ttf in Resources */, C3F2197F1F7246AE004D76FB /* cutoutIcon@3x.png in Resources */, C3F21A351F7246C3004D76FB /* nashvilleMap.png in Resources */, C3F219911F7246AE004D76FB /* filter@3x.png in Resources */, @@ -3029,6 +3132,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 766CEBA1205BD85F00F708D7 /* H265MovieViewController.m in Sources */, C3F21A491F7246C3004D76FB /* KWGlobalFilter.m in Sources */, C3F91F6B1F1CBD4900698322 /* row_neon.cc in Sources */, C3F91F861F1CBD4900698322 /* SDWebImageDownloaderOperation.m in Sources */, @@ -3060,6 +3164,7 @@ C3F21A4A1F7246C3004D76FB /* KWGlobalFilterManager.m in Sources */, C3F91F4C1F1CBD4900698322 /* compare.cc in Sources */, C3F91F621F1CBD4900698322 /* rotate_mips.cc in Sources */, + 766CEB95205BD80100F708D7 /* TransitionModelSelectView.m in Sources */, C3F91F651F1CBD4900698322 /* rotate_win.cc in Sources */, C3F91F5A1F1CBD4900698322 /* mjpeg_decoder.cc in Sources */, C3F91F661F1CBD4900698322 /* row_any.cc in Sources */, @@ -3074,12 +3179,16 @@ C3F91F571F1CBD4900698322 /* convert_to_argb.cc in Sources */, 0A9435841E6CA2E2008845A3 /* AppDelegate.m in Sources */, 0A9435811E6CA2E2008845A3 /* main.m in Sources */, + 766CEB98205BD80100F708D7 /* TransitionTextEditViewController.m in Sources */, C3F91F561F1CBD4900698322 /* convert_jpeg.cc in Sources */, C3FCBFCB1F305B21007EBB10 /* GifFormatViewController.m in Sources */, 0A20C1C11FBED85900E98B07 /* UIView+PLSLightFrame.m in Sources */, + 766CEB97205BD80100F708D7 /* TransitionModelMaker.m in Sources */, C3F91F6D1F1CBD4900698322 /* row_win.cc in Sources */, + 766CEB9E205BD80100F708D7 /* PLSClipMulitMediaView.m in Sources */, C3F91F7F1F1CBD4900698322 /* Reachability.m in Sources */, C3A791151FA02E6500C3F2D6 /* Auth.m in Sources */, + 766CEB9C205BD80100F708D7 /* BaseViewController.m in Sources */, C3F91F791F1CBD4900698322 /* KWSticker.m in Sources */, 0A20C1E41FBEE0C800E98B07 /* PLSColorPicker.m in Sources */, C3F91F931F1CBD4900698322 /* zip.c in Sources */, @@ -3102,14 +3211,17 @@ 0A694C571FE3774B00E2BA60 /* PLSColumnListView.m in Sources */, C3F91F731F1CBD4900698322 /* scale_mips.cc in Sources */, 0A928BE31EE75703007D2250 /* PLSAudioVolumeView.m in Sources */, + 766CEB9B205BD80100F708D7 /* MulitEditViewController.m in Sources */, C3F91F701F1CBD4900698322 /* scale_argb.cc in Sources */, C3F91F851F1CBD4900698322 /* SDWebImageDownloader.m in Sources */, 0A20C1E31FBEE0C800E98B07 /* PLSVideoEditingController.m in Sources */, + 766CEB9A205BD80100F708D7 /* MulitPhotoAlbumViewController.m in Sources */, 0ACE7C381ED8B072002FF4C9 /* PLSEditVideoCell.m in Sources */, 0A20C1E71FBEE0C800E98B07 /* PLSTextBar.m in Sources */, 0A534EAB200E27F10032A981 /* PLSViewRecorderManager.m in Sources */, 0ACE7C371ED8B072002FF4C9 /* PLSDeleteButton.m in Sources */, C3A7911F1FA02E6500C3F2D6 /* SSZipArchive.m in Sources */, + 766CEB99205BD80100F708D7 /* MulitClipViewController.m in Sources */, C3F219001F724699004D76FB /* KWUIManager.m in Sources */, C3A791171FA02E6500C3F2D6 /* JSONLoader.m in Sources */, C3F91F8B1F1CBD4900698322 /* UIImage+MultiFormat.m in Sources */, @@ -3119,6 +3231,7 @@ C3F91F6C1F1CBD4900698322 /* row_neon64.cc in Sources */, C3F91F821F1CBD4900698322 /* SDImageCache.m in Sources */, 0ACE7C391ED8B072002FF4C9 /* PLSProgressBar.m in Sources */, + 766CEB9D205BD80100F708D7 /* PLSPlayerView.m in Sources */, 0A20C1E51FBEE0C800E98B07 /* PLSEditToolbar.m in Sources */, 0AECA5001E88A60C00AF2931 /* RecordViewController.m in Sources */, 0AECA4F21E88466300AF2931 /* PlayViewController.m in Sources */, @@ -3145,6 +3258,7 @@ C3A791341FA0625700C3F2D6 /* EasyarARViewController.m in Sources */, C3F91F511F1CBD4900698322 /* compare_win.cc in Sources */, C3F91F891F1CBD4900698322 /* UIButton+WebCache.m in Sources */, + 766CEB96205BD80100F708D7 /* TransitionViewController.m in Sources */, C3F91F901F1CBD4900698322 /* ioapi.c in Sources */, C3F91F521F1CBD4900698322 /* convert.cc in Sources */, C3F91F4E1F1CBD4900698322 /* compare_gcc.cc in Sources */, @@ -3320,6 +3434,7 @@ "$(PROJECT_DIR)/PLShortVideoKitDemo/TuSDK/TuSDK-framework", "$(PROJECT_DIR)/PLShortVideoKitDemo/TuSDK/TuSDK-framework/Images", ); + GCC_PREFIX_HEADER = PLShortVideoKitDemo/PrefixHeader.pch; HEADER_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/PLShortVideoKitDemo/PLPlayerKit/include\"", @@ -3357,6 +3472,7 @@ "$(PROJECT_DIR)/PLShortVideoKitDemo/TuSDK/TuSDK-framework", "$(PROJECT_DIR)/PLShortVideoKitDemo/TuSDK/TuSDK-framework/Images", ); + GCC_PREFIX_HEADER = PLShortVideoKitDemo/PrefixHeader.pch; HEADER_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/PLShortVideoKitDemo/PLPlayerKit/include\"", diff --git a/Example/PLShortVideoKitDemo/AppDelegate.m b/Example/PLShortVideoKitDemo/AppDelegate.m index e5b775cc..6a397b88 100644 --- a/Example/PLShortVideoKitDemo/AppDelegate.m +++ b/Example/PLShortVideoKitDemo/AppDelegate.m @@ -17,6 +17,8 @@ // TuSDK mark #import + + // AR 特效的 key NSString *easyAR3DKey = @"zYnUPaCAWtl4WDH3qLu290KRFA7gCCU2iyI9127chA6gvLQyr9CUlawIjMdC1OXxLwsUWvNN2zI2XIElU8AP2QitdZ4WFAfoA8DdJbos2FL4FnPKiSjX52Avh524oxXLF8iOuZXg4YFSQWgKrhkLsJs8K8NxsEdoWh2UCuRsONxjHAdDX0V871RQMydPAyFzx4L0fTUe"; @@ -26,7 +28,6 @@ @interface AppDelegate () @implementation AppDelegate - - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json index d98c3c42..c0b84642 100755 --- a/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -143,6 +143,11 @@ "idiom" : "ipad", "filename" : "Icon-App-83.5x83.5@2x.png", "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/Example/PLShortVideoKitDemo/EditViewController.m b/Example/PLShortVideoKitDemo/EditViewController.m index 4f793962..c671252d 100644 --- a/Example/PLShortVideoKitDemo/EditViewController.m +++ b/Example/PLShortVideoKitDemo/EditViewController.m @@ -588,7 +588,7 @@ - (void)setupTuSDKFilter { // 传入图像的方向是否为原始朝向(相机采集的原始朝向),SDK 将依据该属性来调整人脸检测时图片的角度。如果没有对图片进行旋转,则为 YES BOOL isOriginalOrientation = NO; self.filterProcessor = [[TuSDKFilterProcessor alloc] initWithFormatType:kCVPixelFormatType_32BGRA isOriginalOrientation:isOriginalOrientation]; - [self.filterProcessor setEnableLiveSticker:YES]; + [self.filterProcessor setEnableLiveSticker:NO]; self.filterProcessor.delegate = self; self.effectTools = [[SceneEffectTools alloc] init]; diff --git a/Example/PLShortVideoKitDemo/H265MovieViewController.h b/Example/PLShortVideoKitDemo/H265MovieViewController.h new file mode 100644 index 00000000..4863e24a --- /dev/null +++ b/Example/PLShortVideoKitDemo/H265MovieViewController.h @@ -0,0 +1,13 @@ +// +// H265MovieViewController.h +// PLShortVideoKitDemo +// +// Created by suntongmian on 2018/2/12. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +@interface H265MovieViewController : UITableViewController + +@end diff --git a/Example/PLShortVideoKitDemo/H265MovieViewController.m b/Example/PLShortVideoKitDemo/H265MovieViewController.m new file mode 100644 index 00000000..8966eaf0 --- /dev/null +++ b/Example/PLShortVideoKitDemo/H265MovieViewController.m @@ -0,0 +1,111 @@ +// +// H265MovieViewController.m +// PLShortVideoKitDemo +// +// Created by suntongmian on 2018/2/12. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "H265MovieViewController.h" +#import "MovieTransCodeViewController.h" +#import "ClipMovieViewController.h" + +#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] + +static NSString *reuseIdentifier = @"reuseIdentifier"; + +@interface H265MovieViewController () +{ + NSMutableArray *_h265VideoArray; +} + +@end + +@implementation H265MovieViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Uncomment the following line to preserve selection between presentations. + // self.clearsSelectionOnViewWillAppear = NO; + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem; + + UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回 " style:(UIBarButtonItemStylePlain) target:self action:@selector(clickBackItem:)]; + self.navigationItem.leftBarButtonItem = backItem; + + [self loadH265Videos]; + + [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:reuseIdentifier]; +} + +- (void)loadH265Videos { + NSString *subpath = @"h265_video"; + _h265VideoArray = [[NSMutableArray alloc] init]; + + NSBundle *bundle = [NSBundle mainBundle]; + [_h265VideoArray addObjectsFromArray:[bundle pathsForResourcesOfType:@"mp4" inDirectory:subpath]]; + [_h265VideoArray addObjectsFromArray:[bundle pathsForResourcesOfType:@"mov" inDirectory:subpath]]; +} + +- (void)clickBackItem:(UIBarButtonItem *)item { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return _h265VideoArray.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; + cell.textLabel.text = [_h265VideoArray[indexPath.row] lastPathComponent]; + + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSString *h265VideoPath = _h265VideoArray[indexPath.row]; + + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:h265VideoPath delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"转码", nil]; + alertView.tag = 10001; + [alertView show]; +} + +#pragma mark - +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { + if (10001 == alertView.tag) { + NSURL *url = [NSURL fileURLWithPath:alertView.message]; + + if (1 == buttonIndex) { + // 转码 + MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; + transCodeViewController.url = url; + [self presentViewController:transCodeViewController animated:YES completion:nil]; + + } + } +} + +#pragma mark -- 隐藏状态栏 +- (BOOL)prefersStatusBarHidden { + return YES; +} + +#pragma mark -- dealloc +- (void)dealloc { + +} + +@end diff --git a/Example/PLShortVideoKitDemo/Info.plist b/Example/PLShortVideoKitDemo/Info.plist index 46e74c26..7ce343ac 100644 --- a/Example/PLShortVideoKitDemo/Info.plist +++ b/Example/PLShortVideoKitDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.9.0 + 1.10.0 CFBundleVersion 1 Fabric @@ -43,8 +43,15 @@ CameraUsageDescription NSMicrophoneUsageDescription MicrophoneUsageDescription + NSPhotoLibraryAddUsageDescription + PhotoLibraryAddUsageDescription NSPhotoLibraryUsageDescription PhotoLibraryUsageDescription + UIAppFonts + + zcool-gdh.ttf + HappyZcool-2016.ttf + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/GlobalFilterManager/filters.json b/Example/PLShortVideoKitDemo/KiwiFaceSDK/GlobalFilterManager/filters.json index 9a3c36ec..d86988cc 100755 --- a/Example/PLShortVideoKitDemo/KiwiFaceSDK/GlobalFilterManager/filters.json +++ b/Example/PLShortVideoKitDemo/KiwiFaceSDK/GlobalFilterManager/filters.json @@ -1,284 +1,94 @@ { - "filters": [ - { - "name": "gray", - "dir": "gray", - "category": "default" - }, - { - "name": "pailide", - "dir": "pailide", - "category": "default" - }, - { - "name": "Inkwell", - "dir": "Inkwell", - "category": "inner" - }, - { - "name": "dark", - "dir": "dark", - "category": "default" - }, - { - "name": "retro", - "dir": "retro", - "category": "default" - }, - { - "name": "funky", - "dir": "funky", - "category": "default" - }, - { - "name": "delicious", - "dir": "delicious", - "category": "default" - }, - { - "name": "good", - "dir": "good", - "category": "default" - }, - { - "name": "railway", - "dir": "railway", - "category": "default" - }, - { - "name": "Brannan", - "dir": "Brannan", - "category": "inner" - }, - { - "name": "Amaro", - "dir": "Amaro", - "category": "inner" - }, - { - "name": "Nashville", - "dir": "Nashville", - "category": "inner" - }, - { - "name": "purple", - "dir": "purple", - "category": "default" - }, - { - "name": "xibu", - "dir": "xibu", - "category": "default" - }, - { - "name": "Walden", - "dir": "Walden", - "category": "inner" - }, - { - "name": "Valencia", - "dir": "Valencia", - "category": "inner" - }, - { - "name": "Freud", - "dir": "Freud", - "category": "inner" - }, - { - "name": "normal", - "dir": "normal", - "category": "default" - }, - { - "name": "huang", - "dir": "huang", - "category": "default" - }, - { - "name": "red", - "dir": "red", - "category": "default" - }, - { - "name": "Rise", - "dir": "Rise", - "category": "inner" - }, - { - "name": "happy", - "dir": "happy", - "category": "default" - }, - { - "name": "camomile", - "dir": "camomile", - "category": "default" - }, - { - "name": "cold", - "dir": "cold", - "category": "default" - }, - { - "name": "nice", - "dir": "nice", - "category": "default" - }, - { - "name": "frog", - "dir": "frog", - "category": "default" - }, - { - "name": "blueberry", - "dir": "blueberry", - "category": "default" - }, - { - "name": "print", - "dir": "print", - "category": "default" - }, - { - "name": "miss", - "dir": "miss", - "category": "default" - }, - { - "name": "Fairy", - "dir": "Fairy", - "category": "default" - }, - { - "name": "Hudson", - "dir": "Hudson", - "category": "inner" - }, - { - "name": "Brooklyn", - "dir": "Brooklyn", - "category": "inner" - }, - { - "name": "Sutro", - "dir": "Sutro", - "category": "inner" - }, - { - "name": "lyon", - "dir": "lyon", - "category": "default" - }, - { - "name": "pink", - "dir": "pink", - "category": "default" - }, - { - "name": "siesta", - "dir": "siesta", - "category": "default" - }, - { - "name": "pld", - "dir": "pld", - "category": "default" - }, - { - "name": "yummy", - "dir": "yummy", - "category": "default" - }, - { - "name": "habana", - "dir": "habana", - "category": "default" - }, - { - "name": "sunny", - "dir": "sunny", - "category": "default" - }, - { - "name": "harvest", - "dir": "harvest", - "category": "default" - }, - { - "name": "Sierra", - "dir": "Sierra", - "category": "inner" - }, - { - "name": "lzp", - "dir": "lzp", - "category": "default" - }, - { - "name": "color", - "dir": "color", - "category": "default" - }, - { - "name": "kc", - "dir": "kc", - "category": "default" - }, - { - "name": "elegance", - "dir": "elegance", - "category": "default" - }, - { - "name": "toutong", - "dir": "toutong", - "category": "default" - }, - { - "name": "waltz", - "dir": "waltz", - "category": "default" - }, - { - "name": "Hefe", - "dir": "Hefe", - "category": "inner" - }, - { - "name": "Toaster", - "dir": "Toaster", - "category": "inner" - }, - { - "name": "dreamy", - "dir": "dreamy", - "category": "default" - }, - { - "name": "fuji", - "dir": "fuji", - "category": "default" - }, - { - "name": "Earlybird", - "dir": "Earlybird", - "category": "inner" - }, - { - "name": "candy", - "dir": "candy", - "category": "default" - }, - { - "name": "fun", - "dir": "fun", - "category": "default" - }, - { - "name": "lagoon", - "dir": "lagoon", - "category": "default" - } - ] + "filters": [ + { + "name": "gray", + "dir": "gray", + "category": "default" + }, + { + "name": "pailide", + "dir": "pailide", + "category": "default" + }, + { + "name": "Inkwell", + "dir": "Inkwell", + "category": "inner" + }, + { + "name": "dark", + "dir": "dark", + "category": "default" + }, + { + "name": "retro", + "dir": "retro", + "category": "default" + }, + { + "name": "Walden", + "dir": "Walden", + "category": "inner" + }, + { + "name": "Valencia", + "dir": "Valencia", + "category": "inner" + }, + { + "name": "Freud", + "dir": "Freud", + "category": "inner" + }, + { + "name": "normal", + "dir": "normal", + "category": "default" + }, + { + "name": "huang", + "dir": "huang", + "category": "default" + }, + { + "name": "lyon", + "dir": "lyon", + "category": "default" + }, + { + "name": "pink", + "dir": "pink", + "category": "default" + }, + { + "name": "siesta", + "dir": "siesta", + "category": "default" + }, + { + "name": "pld", + "dir": "pld", + "category": "default" + }, + { + "name": "yummy", + "dir": "yummy", + "category": "default" + }, + { + "name": "candy", + "dir": "candy", + "category": "default" + }, + { + "name": "fun", + "dir": "fun", + "category": "default" + }, + { + "name": "lagoon", + "dir": "lagoon", + "category": "default" + } + ] } diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/KWRenderManager.m b/Example/PLShortVideoKitDemo/KiwiFaceSDK/KWRenderManager.m index 230a23c2..f1e44aee 100755 --- a/Example/PLShortVideoKitDemo/KiwiFaceSDK/KWRenderManager.m +++ b/Example/PLShortVideoKitDemo/KiwiFaceSDK/KWRenderManager.m @@ -209,18 +209,18 @@ - (void)loadRender { - (void)resetDistortionParams { if ([[Global sharedManager] isPixcelBufferRotateVertical]) { - self.smallFaceBigEyeFilter.y_scale = self.varWidth / self.varHeight; - - ((ETDistortionFilter *) self.distortionFilters[1]).y_scale = self.varHeight / self.varWidth; - ((FatFaceDistortionFilter *) self.distortionFilters[2]).y_scale = self.varHeight / self.varWidth; - ((SlimFaceDistortionFilter *) self.distortionFilters[3]).y_scale = self.varHeight / self.varWidth; - ((PearFaceDistortionFilter *) self.distortionFilters[4]).y_scale = self.varHeight / self.varWidth; - } else { self.smallFaceBigEyeFilter.y_scale = self.varHeight / self.varWidth; ((ETDistortionFilter *) self.distortionFilters[1]).y_scale = self.varWidth / self.varHeight; ((FatFaceDistortionFilter *) self.distortionFilters[2]).y_scale = self.varWidth / self.varHeight; ((SlimFaceDistortionFilter *) self.distortionFilters[3]).y_scale = self.varWidth / self.varHeight; + ((PearFaceDistortionFilter *) self.distortionFilters[4]).y_scale = self.varHeight / self.varWidth; + } else { + self.smallFaceBigEyeFilter.y_scale = self.varWidth / self.varHeight; + + ((ETDistortionFilter *) self.distortionFilters[1]).y_scale = self.varHeight / self.varWidth; + ((FatFaceDistortionFilter *) self.distortionFilters[2]).y_scale = self.varHeight / self.varWidth; + ((SlimFaceDistortionFilter *) self.distortionFilters[3]).y_scale = self.varHeight / self.varWidth; ((PearFaceDistortionFilter *) self.distortionFilters[4]).y_scale = self.varWidth / self.varHeight; } @@ -238,26 +238,30 @@ + (void)processPixelBuffer:(CVPixelBufferRef)pixelBuffer{ switch (iDeviceOrientation) { case UIDeviceOrientationPortrait: - cvMobileRotate = CV_CLOCKWISE_ROTATE_0; - break; - + cvMobileRotate = CV_CLOCKWISE_ROTATE_0; + [Global sharedManager].PIXCELBUFFER_ROTATE = KW_PIXELBUFFER_ROTATE_270; + break; + case UIDeviceOrientationLandscapeLeft: - cvMobileRotate = mirrored ? CV_CLOCKWISE_ROTATE_90 : CV_CLOCKWISE_ROTATE_270; - break; - + cvMobileRotate = mirrored ? CV_CLOCKWISE_ROTATE_90 : CV_CLOCKWISE_ROTATE_270; + [Global sharedManager].PIXCELBUFFER_ROTATE = KW_PIXELBUFFER_ROTATE_180; + break; + case UIDeviceOrientationLandscapeRight: - cvMobileRotate = mirrored ? CV_CLOCKWISE_ROTATE_270 : CV_CLOCKWISE_ROTATE_90; - break; - + cvMobileRotate = mirrored ? CV_CLOCKWISE_ROTATE_270 : CV_CLOCKWISE_ROTATE_90; + [Global sharedManager].PIXCELBUFFER_ROTATE = KW_PIXELBUFFER_ROTATE_90; + break; + case UIDeviceOrientationPortraitUpsideDown: - cvMobileRotate = CV_CLOCKWISE_ROTATE_180; - break; - + cvMobileRotate = CV_CLOCKWISE_ROTATE_180; + [Global sharedManager].PIXCELBUFFER_ROTATE = KW_PIXELBUFFER_ROTATE_0; + break; + default: - cvMobileRotate = CV_CLOCKWISE_ROTATE_0; - break; + cvMobileRotate = CV_CLOCKWISE_ROTATE_0; + [Global sharedManager].PIXCELBUFFER_ROTATE = KW_PIXELBUFFER_ROTATE_270; + break; } - [instanceManager.renderer processPixelBuffer:pixelBuffer withRotation:cvMobileRotate mirrored:mirrored]; } @@ -456,13 +460,14 @@ - (void)onNewBeautyParamsChanged:(KW_NEWBEAUTY_TYPE)type value:(float)value { } - (void)releaseManager { + [self.stickerRender setSticker:nil]; [self.presentStickerRenderer setSticker:nil]; [self.smiliesStickerRenderer setSticker:nil]; self.presentStickerRenderer.presentStickerRendererPlayOverBlock = nil; self.smiliesStickerRenderer.smiliesStickerRendererPlayOverBlock = nil; [self.renderer removeAllFilters]; - + //release array [KWGlobalFilterManager removeAllColorFilters]; self.currentDistortionFilter = nil; @@ -471,7 +476,7 @@ - (void)releaseManager { self.presentStickers = nil; self.distortionTitleInfosArr = nil; self.distortionFilters = nil; - + //release render self.stickerRender = nil; self.currentGlobalFilter = nil; @@ -480,9 +485,9 @@ - (void)releaseManager { self.smiliesStickerRenderer = nil; self.presentStickerRenderer = nil; self.smallFaceBigEyeFilter = nil; + [self.renderer releaseRender]; self.renderer = nil; instanceManager = nil; - } diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Render/KWRenderer.h b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Render/KWRenderer.h index 82380920..caebdea9 100755 --- a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Render/KWRenderer.h +++ b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Render/KWRenderer.h @@ -17,34 +17,52 @@ #import "SmallFaceBigEyeFilter.h" #import "Global.h" -//大眼 -#define KW_NEWBEAUTY_EYEMAGNIFYING_START 0.0 -#define KW_NEWBEAUTY_EYEMAGNIFYING_END 0.15 +/** + Video frame rendering class + */ +@interface KWRenderer : NSObject -//瘦脸 -#define KW_NEWBEAUTY_CHINSLIMING_START 0.99 -#define KW_NEWBEAUTY_CHINSLIMING_END 0.95 +/* + 大眼 + 建议设置阈值:0.0~0.15 + */ +@property(nonatomic, assign) float eyeMagnifyingStart; +@property(nonatomic, assign) float eyeMagnifyingEnd; -//美白 -#define KW_NEWBEAUTY_SKINWHITENING_START 0.4 -#define KW_NEWBEAUTY_SKINWHITENING_END 0.6 +/* + 瘦脸 + 建议设置阈值:0.99~0.95 + */ +@property(nonatomic, assign) float chinSlimingStart; +@property(nonatomic, assign) float chinSlimingEnd; -//磨皮 -#define KW_NEWBEAUTY_BLEMISHREMOVAL_START -1.7 -#define KW_NEWBEAUTY_BLEMISHREMOVAL_END 0.4 +/* + 美白 + 建议设置阈值:0.4~0.6 + */ +@property(nonatomic, assign) float skinWhiteningStart; +@property(nonatomic, assign) float skinWhiteningEnd; -//饱和 -#define KW_NEWBEAUTY_SKINSATURATION_START 0.2 -#define KW_NEWBEAUTY_SKINSATURATION_END 1.1 +/* + 磨皮 + 建议设置阈值:-1.7~0.4 + */ +@property(nonatomic, assign) float blemishRemovalStart; +@property(nonatomic, assign) float blemishRemovalEnd; -//粉嫩 -#define KW_NEWBEAUTY_SKINTENDERNESS_START -0.5 -#define KW_NEWBEAUTY_SKINTENDERNESS_END -0.2 +/* + 饱和 + 建议设置阈值:0.2~1.1 + */ +@property(nonatomic, assign) float skinSaturationStart; +@property(nonatomic, assign) float skinSaturationEnd; -/** - Video frame rendering class +/* + 粉嫩 + 建议设置阈值:-0.5~-0.2 */ -@interface KWRenderer : NSObject +@property(nonatomic, assign) float skinTendernessStart; +@property(nonatomic, assign) float skinTendernessEnd; /** The execution block of the operation can be customized before the video frame is captured after rendering @@ -75,6 +93,8 @@ typedef void(^RenderAndGetFacePointsBlock) //Whether to open the face stickers @property(nonatomic, assign) BOOL isEnableSmiliesSticker; +//是否开启抠图 +@property(nonatomic, assign) BOOL isEnableCutOut; //是否开启换脸 @property(nonatomic, assign) BOOL isEnableAutomaticFace; @@ -104,6 +124,10 @@ typedef void(^RenderAndGetFacePointsBlock) + (float)beautyParamWithValue:(float)value type:(KW_NEWBEAUTY_TYPE)type; +//释放渲染对象 +- (void)releaseRender; + @end UIKIT_EXTERN NSString *const KWVerifyFailededNotification; + diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/1960s/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/1960s/filter.png deleted file mode 100755 index 04ea311b..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/1960s/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/1960s/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/1960s/thumb.png deleted file mode 100755 index a99aee70..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/1960s/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Amaro/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Amaro/thumb.png deleted file mode 100755 index 247a8579..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Amaro/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Brannan/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Brannan/thumb.png deleted file mode 100755 index 03b4bc50..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Brannan/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Brooklyn/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Brooklyn/thumb.png deleted file mode 100755 index 6d767a0c..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Brooklyn/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Calm/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Calm/thumb.png deleted file mode 100755 index 34f7cebe..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Calm/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Crayon/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Crayon/thumb.png deleted file mode 100755 index 99614d82..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Crayon/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Earlybird/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Earlybird/thumb.png deleted file mode 100755 index 40158a9b..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Earlybird/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Emerald/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Emerald/thumb.png deleted file mode 100755 index 58b5a7f2..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Emerald/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Evergreen/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Evergreen/thumb.png deleted file mode 100755 index 5971d3f4..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Evergreen/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Fairy/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Fairy/filter.png deleted file mode 100755 index 652f0b9d..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Fairy/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Fairy/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Fairy/thumb.png deleted file mode 100755 index 6d767a0c..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Fairy/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Happyly/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Happyly/thumb.png deleted file mode 100755 index 1bd1217e..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Happyly/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Healthy/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Healthy/thumb.png deleted file mode 100755 index 3b7a81fe..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Healthy/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Hefe/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Hefe/thumb.png deleted file mode 100755 index f474cefa..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Hefe/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Hudson/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Hudson/thumb.png deleted file mode 100755 index 7c8a3d10..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Hudson/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Kevin/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Kevin/thumb.png deleted file mode 100755 index 9bf649ee..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Kevin/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Latte/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Latte/thumb.png deleted file mode 100755 index bbba3faf..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Latte/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Nashville/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Nashville/thumb.png deleted file mode 100755 index b62c0bb4..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Nashville/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Nofilter/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Nofilter/thumb.png deleted file mode 100755 index 7671ae73..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Nofilter/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Pixar/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Pixar/thumb.png deleted file mode 100755 index 510239b6..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Pixar/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Rise/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Rise/thumb.png deleted file mode 100755 index f12471a7..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Rise/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Romance/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Romance/thumb.png deleted file mode 100755 index 94dea322..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Romance/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sakura/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sakura/thumb.png deleted file mode 100755 index fefc78ee..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sakura/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sierra/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sierra/thumb.png deleted file mode 100755 index 7cba2d42..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sierra/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sketch/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sketch/thumb.png deleted file mode 100755 index b59f127d..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sketch/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Skinwhiten/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Skinwhiten/thumb.png deleted file mode 100755 index 9457813c..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Skinwhiten/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sunrise/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sunrise/thumb.png deleted file mode 100755 index f006240e..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sunrise/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sunset/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sunset/thumb.png deleted file mode 100755 index 47dbe0d9..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sunset/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sutro/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sutro/thumb.png deleted file mode 100755 index d3752db0..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Sutro/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Tender/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Tender/thumb.png deleted file mode 100755 index 22ab2949..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Tender/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Toaster/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Toaster/thumb.png deleted file mode 100755 index f78c8729..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Toaster/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Whitecat/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Whitecat/thumb.png deleted file mode 100755 index e8cdac76..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Whitecat/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Years1977/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Years1977/thumb.png deleted file mode 100755 index a9fe937f..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/Years1977/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blueberry/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blueberry/filter.png deleted file mode 100755 index dd472551..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blueberry/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blueberry/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blueberry/thumb.png deleted file mode 100755 index c41085ba..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blueberry/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blush/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blush/filter.png deleted file mode 100755 index c1c744a6..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blush/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blush/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blush/thumb.png deleted file mode 100755 index 062f8504..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/blush/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/camomile/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/camomile/filter.png deleted file mode 100755 index a3607aa6..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/camomile/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/camomile/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/camomile/thumb.png deleted file mode 100755 index da30ee8f..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/camomile/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/cold/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/cold/filter.png deleted file mode 100755 index 02ee1bff..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/cold/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/cold/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/cold/thumb.png deleted file mode 100755 index 787094e3..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/cold/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/color/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/color/filter.png deleted file mode 100755 index d7295305..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/color/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/color/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/color/thumb.png deleted file mode 100755 index 32f6223c..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/color/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/curious/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/curious/filter.png deleted file mode 100755 index aa8e548f..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/curious/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/curious/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/curious/thumb.png deleted file mode 100755 index 9800a569..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/curious/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/daisy/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/daisy/filter.png deleted file mode 100755 index 73d92945..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/daisy/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/daisy/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/daisy/thumb.png deleted file mode 100755 index d5512a1d..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/daisy/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/delicious/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/delicious/filter.png deleted file mode 100755 index 3e063e6d..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/delicious/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/delicious/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/delicious/thumb.png deleted file mode 100755 index 469e2ccd..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/delicious/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/dreamy/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/dreamy/filter.png deleted file mode 100755 index 55d52f04..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/dreamy/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/dreamy/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/dreamy/thumb.png deleted file mode 100755 index c9ed3fe4..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/dreamy/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/elegance/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/elegance/filter.png deleted file mode 100755 index ccc6d4ec..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/elegance/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/elegance/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/elegance/thumb.png deleted file mode 100755 index 40158a9b..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/elegance/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/frog/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/frog/filter.png deleted file mode 100755 index 0a2c031a..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/frog/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/frog/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/frog/thumb.png deleted file mode 100755 index a2afc4be..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/frog/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/fuji/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/fuji/filter.png deleted file mode 100755 index e691623d..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/fuji/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/fuji/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/fuji/thumb.png deleted file mode 100755 index 2ad49d13..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/fuji/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/funky/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/funky/filter.png deleted file mode 100755 index 3169b37b..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/funky/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/funky/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/funky/thumb.png deleted file mode 100755 index 5008a811..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/funky/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/good/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/good/filter.png deleted file mode 100755 index 6db41688..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/good/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/good/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/good/thumb.png deleted file mode 100755 index 823928b8..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/good/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/habana/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/habana/filter.png deleted file mode 100755 index 827226b6..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/habana/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/habana/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/habana/thumb.png deleted file mode 100755 index 8029399f..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/habana/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/happy/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/happy/filter.png deleted file mode 100755 index 9f4c304b..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/happy/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/happy/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/happy/thumb.png deleted file mode 100755 index 6d8f0af9..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/happy/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/harvest/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/harvest/filter.png deleted file mode 100755 index 0c4b8e8f..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/harvest/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/harvest/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/harvest/thumb.png deleted file mode 100755 index 17d1a223..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/harvest/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/kc/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/kc/filter.png deleted file mode 100755 index 9d5deb49..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/kc/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/kc/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/kc/thumb.png deleted file mode 100755 index 3d654485..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/kc/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/labi/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/labi/filter.png deleted file mode 100755 index 1c502612..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/labi/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/labi/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/labi/thumb.png deleted file mode 100755 index a99aee70..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/labi/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/light/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/light/filter.png deleted file mode 100755 index 120b4e2d..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/light/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/light/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/light/thumb.png deleted file mode 100755 index 87715209..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/light/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/lzp/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/lzp/filter.png deleted file mode 100755 index d9256d19..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/lzp/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/lzp/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/lzp/thumb.png deleted file mode 100755 index 4c4ba842..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/lzp/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/miss/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/miss/filter.png deleted file mode 100755 index e1317d78..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/miss/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/miss/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/miss/thumb.png deleted file mode 100755 index c58535b7..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/miss/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/misty/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/misty/filter.png deleted file mode 100755 index 2bee4f00..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/misty/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/misty/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/misty/thumb.png deleted file mode 100755 index 67d8fb89..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/misty/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/nice/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/nice/filter.png deleted file mode 100755 index 4acb318c..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/nice/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/nice/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/nice/thumb.png deleted file mode 100755 index e4b6114b..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/nice/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/print/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/print/filter.png deleted file mode 100755 index d9ece3ba..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/print/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/print/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/print/thumb.png deleted file mode 100755 index 2bae1f03..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/print/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/purple/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/purple/filter.png deleted file mode 100755 index 405dd553..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/purple/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/purple/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/purple/thumb.png deleted file mode 100755 index aa2e7e44..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/purple/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/railway/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/railway/filter.png deleted file mode 100755 index ae2d313d..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/railway/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/railway/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/railway/thumb.png deleted file mode 100755 index b982373b..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/railway/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/rainday/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/rainday/filter.png deleted file mode 100755 index a5149724..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/rainday/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/rainday/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/rainday/thumb.png deleted file mode 100755 index f78cbc61..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/rainday/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/red/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/red/filter.png deleted file mode 100755 index 2212960f..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/red/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/red/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/red/thumb.png deleted file mode 100755 index 5f81be57..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/red/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/shuicai/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/shuicai/filter.png deleted file mode 100755 index 6cd524f6..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/shuicai/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/shuicai/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/shuicai/thumb.png deleted file mode 100755 index a99aee70..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/shuicai/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/spring/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/spring/filter.png deleted file mode 100755 index 468da944..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/spring/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/spring/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/spring/thumb.png deleted file mode 100755 index 8574957d..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/spring/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/sunny/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/sunny/filter.png deleted file mode 100755 index 4e5b033a..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/sunny/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/sunny/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/sunny/thumb.png deleted file mode 100755 index 81080c1e..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/sunny/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/tasty/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/tasty/filter.png deleted file mode 100755 index decc97ac..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/tasty/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/tasty/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/tasty/thumb.png deleted file mode 100755 index 84f75341..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/tasty/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/toutong/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/toutong/filter.png deleted file mode 100755 index 9c693e48..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/toutong/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/toutong/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/toutong/thumb.png deleted file mode 100755 index fb2b8200..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/toutong/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/turkish/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/turkish/filter.png deleted file mode 100755 index e901f07e..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/turkish/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/turkish/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/turkish/thumb.png deleted file mode 100755 index 7e98c985..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/turkish/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/waltz/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/waltz/filter.png deleted file mode 100755 index 61105bf6..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/waltz/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/waltz/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/waltz/thumb.png deleted file mode 100755 index c7e5fc7a..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/waltz/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/warm/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/warm/filter.png deleted file mode 100755 index a11abe2f..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/warm/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/warm/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/warm/thumb.png deleted file mode 100755 index 4698d4b9..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/warm/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/xibu/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/xibu/filter.png deleted file mode 100755 index 4a2cc8ac..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/xibu/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/xibu/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/xibu/thumb.png deleted file mode 100755 index 73b12497..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/xibu/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/yellow/filter.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/yellow/filter.png deleted file mode 100755 index cdcd8ea9..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/yellow/filter.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/yellow/thumb.png b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/yellow/thumb.png deleted file mode 100755 index fbf6a4d6..00000000 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Resource/KWResource.bundle/filter/yellow/thumb.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Tracker/libfaceTrackerSDK.a b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Tracker/libfaceTrackerSDK.a old mode 100755 new mode 100644 index d4c03a32..6af0e45b Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/Tracker/libfaceTrackerSDK.a and b/Example/PLShortVideoKitDemo/KiwiFaceSDK/Tracker/libfaceTrackerSDK.a differ diff --git a/Example/PLShortVideoKitDemo/KiwiFaceSDK/libKwSDK.a b/Example/PLShortVideoKitDemo/KiwiFaceSDK/libKwSDK.a old mode 100755 new mode 100644 index ad8d67df..691aae94 Binary files a/Example/PLShortVideoKitDemo/KiwiFaceSDK/libKwSDK.a and b/Example/PLShortVideoKitDemo/KiwiFaceSDK/libKwSDK.a differ diff --git a/Example/PLShortVideoKitDemo/Librarys/libMuseProcessor.a b/Example/PLShortVideoKitDemo/Librarys/libMuseProcessor.a new file mode 100644 index 00000000..bc296285 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Librarys/libMuseProcessor.a differ diff --git a/Example/PLShortVideoKitDemo/MovieTransCodeViewController.m b/Example/PLShortVideoKitDemo/MovieTransCodeViewController.m index 4e9bbd2e..b6e70ba9 100644 --- a/Example/PLShortVideoKitDemo/MovieTransCodeViewController.m +++ b/Example/PLShortVideoKitDemo/MovieTransCodeViewController.m @@ -13,6 +13,7 @@ #import #import "PLSSelectionView.h" +#define AlertViewShow(msg) [[[UIAlertView alloc] initWithTitle:@"warning" message:[NSString stringWithFormat:@"%@", msg] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil] show] #define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) #define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] #define PLS_BaseToolboxView_HEIGHT 64 @@ -319,7 +320,6 @@ - (void)movieTransCodeAction { self.shortVideoTranscoder.outputFilePreset = self.transcoderPreset; self.shortVideoTranscoder.timeRange = timeRange; self.shortVideoTranscoder.rotateOrientation = self.rotateOrientation; - [self.shortVideoTranscoder startTranscoding]; [self.shortVideoTranscoder setCompletionBlock:^(NSURL *url){ @@ -344,6 +344,8 @@ - (void)movieTransCodeAction { NSLog(@"transCoding failed: %@", error); + AlertViewShow(error); + dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf removeActivityIndicatorView]; weakSelf.progressLabel.text = @""; @@ -353,8 +355,12 @@ - (void)movieTransCodeAction { [self.shortVideoTranscoder setProcessingBlock:^(float progress){ // 更新压缩进度的 UI NSLog(@"transCoding progress: %f", progress); - weakSelf.progressLabel.text = [NSString stringWithFormat:@"转码进度%d%%", (int)(progress * 100)]; + dispatch_async(dispatch_get_main_queue(), ^{ + weakSelf.progressLabel.text = [NSString stringWithFormat:@"转码进度%d%%", (int)(progress * 100)]; + }); }]; + + [self.shortVideoTranscoder startTranscoding]; } #pragma mark -- 计算文件的大小,单位为 M diff --git a/Example/PLShortVideoKitDemo/PhotoAlbumViewController.h b/Example/PLShortVideoKitDemo/PhotoAlbumViewController.h index 91e18a1e..511364e5 100644 --- a/Example/PLShortVideoKitDemo/PhotoAlbumViewController.h +++ b/Example/PLShortVideoKitDemo/PhotoAlbumViewController.h @@ -53,5 +53,9 @@ @property (assign, nonatomic) NSInteger maxSelectCount; @property (assign, nonatomic) PHAssetMediaType mediaType; + +@property (strong, nonatomic) PLSScrollView *dynamicScrollView; +- (void)nextButtonClick:(UIButton *)sender; + @end diff --git a/Example/PLShortVideoKitDemo/PhotoAlbumViewController.m b/Example/PLShortVideoKitDemo/PhotoAlbumViewController.m index aabe2509..5abe8ad1 100644 --- a/Example/PLShortVideoKitDemo/PhotoAlbumViewController.m +++ b/Example/PLShortVideoKitDemo/PhotoAlbumViewController.m @@ -196,6 +196,7 @@ - (UIImage *)imageURL:(PHAsset *)phAsset targetSize:(CGSize)targetSize { __block UIImage *image = nil; PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; + options.networkAccessAllowed = YES; options.synchronous = YES; PHImageManager *manager = [PHImageManager defaultManager]; @@ -285,13 +286,14 @@ @interface PhotoAlbumViewController () - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { @@ -597,51 +606,25 @@ - (void)rateButtonView:(PLSRateButtonView *)rateButtonView didSelectedTitleIndex } } +#pragma mark -- imageDurationButtonClicked +- (void)imageDurationButtonClicked:(UIButton *)sender { + sender.selected = !sender.selected; + if (sender.selected) { + self.imageDuration = 3.0f; + } else { + self.imageDuration = 2.0f; + } +} + #pragma mark -- 下一步 - (void)nextButtonClick:(UIButton *)sender { // 视频选择器视图中图片、视频的选取数目可以做限制的,限制为1个、多个、不限 if (self.dynamicScrollView.selectedAssets.count > 0) { if (self.mediaType == PHAssetMediaTypeImage) { - [self.urls removeAllObjects]; - for (PHAsset *asset in self.dynamicScrollView.selectedAssets) { - UIImage *image = [asset imageURL:asset targetSize:CGSizeMake(544, 960)]; - [self.urls addObject:image]; - } - - [self loadActivityIndicatorView]; - - __weak typeof(self)weakSelf = self; - PLSImageToMovieComposer *imageToMovieComposer = [[PLSImageToMovieComposer alloc] initWithImages:self.urls]; - if (self.isMovieLandscapeOrientation) { - imageToMovieComposer.videoSize = CGSizeMake(960, 544); - } else { - imageToMovieComposer.videoSize = CGSizeMake(544, 960); - } - - [imageToMovieComposer setCompletionBlock:^(NSURL *url) { - NSLog(@"imageToMovieComposer ur: %@", url); - - [weakSelf removeActivityIndicatorView]; - weakSelf.progressLabel.text = @""; - - MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; - transCodeViewController.url = url; - [self presentViewController:transCodeViewController animated:YES completion:nil]; - }]; - [imageToMovieComposer setFailureBlock:^(NSError *error) { - NSLog(@"imageToMovieComposer failed"); - - [weakSelf removeActivityIndicatorView]; - weakSelf.progressLabel.text = @""; - }]; - [imageToMovieComposer setProcessingBlock:^(float progress) { - NSLog(@"imageToMovieComposer progress: %f", progress); - - weakSelf.progressLabel.text = [NSString stringWithFormat:@"合成进度%d%%", (int)(progress * 100)]; - }]; - - [imageToMovieComposer startComposing]; - + // 图片合成为视频 + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"图片合成为视频" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; + alertView.tag = 10001; + [alertView show]; } else if (self.mediaType == PHAssetMediaTypeVideo) { [self.urls removeAllObjects]; @@ -651,50 +634,146 @@ - (void)nextButtonClick:(UIButton *)sender { } if (self.urls.count == 1) { - MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; - transCodeViewController.url = self.urls[0]; - [self presentViewController:transCodeViewController animated:YES completion:nil]; + // 视频转码 + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"视频转码" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; + alertView.tag = 10002; + [alertView show]; + + }else { + // 多个视频拼接 或者 单个视频转码 都可以用 PLSMovieComposer + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"视频拼接" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; + alertView.tag = 10003; + [alertView show]; } - else { - [self loadActivityIndicatorView]; + } + } +} - __weak typeof(self)weakSelf = self; - self.movieComposer = [[PLSMovieComposer alloc] initWithUrls:self.urls]; - if (self.isMovieLandscapeOrientation) { - self.movieComposer.videoSize = CGSizeMake(960, 544); - } else { - self.movieComposer.videoSize = CGSizeMake(544, 960); - } - self.movieComposer.videoFrameRate = 25; - self.movieComposer.outputFileType = PLSFileTypeMPEG4; - - [self.movieComposer setCompletionBlock:^(NSURL *url) { - NSLog(@"movieComposer ur: %@", url); +#pragma mark -- UIAlertView delegate +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { + // 检测是否授权访问相册,没有授权就跳转到 App 的设置页 + if (10001 != alertView.tag && 10002 != alertView.tag && 10003 != alertView.tag) { + if (buttonIndex == alertView.firstOtherButtonIndex) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; + } + + [self dismissViewControllerAnimated:YES completion:nil]; + } +} - [weakSelf removeActivityIndicatorView]; - weakSelf.progressLabel.text = @""; - - MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; - transCodeViewController.url = url; - [weakSelf presentViewController:transCodeViewController animated:YES completion:nil]; - }]; - [self.movieComposer setFailureBlock:^(NSError *error) { - NSLog(@"movieComposer failed"); - - [weakSelf removeActivityIndicatorView]; - weakSelf.progressLabel.text = @""; - - }]; - [self.movieComposer setProcessingBlock:^(float progress){ - NSLog(@"movieComposer progress: %f", progress); - - weakSelf.progressLabel.text = [NSString stringWithFormat:@"拼接进度%d%%", (int)(progress * 100)]; - }]; - - [self.movieComposer startComposing]; - } +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { + if (10001 == alertView.tag) { + if (1 == buttonIndex) { + // 图片合成为视频 + [self imageToMovieEvent]; + } + + } else if (10002 == alertView.tag) { + if (1 == buttonIndex) { + // 视频转码 + [self movieTransCodeEvent]; } + + } else if (10003 == alertView.tag) { + if (1 == buttonIndex) { + // 多个视频拼接 或者 单个视频转码 都可以用 PLSMovieComposer + [self movieComposerEvent]; + } + } +} + +// 图片合成为视频 +- (void)imageToMovieEvent { + [self.urls removeAllObjects]; + for (PHAsset *asset in self.dynamicScrollView.selectedAssets) { + UIImage *image = [asset imageURL:asset targetSize:CGSizeMake(544, 960)]; + [self.urls addObject:image]; + } + + [self loadActivityIndicatorView]; + + __weak typeof(self)weakSelf = self; + PLSImageToMovieComposer *imageToMovieComposer = [[PLSImageToMovieComposer alloc] initWithImages:self.urls]; + if (self.isMovieLandscapeOrientation) { + imageToMovieComposer.videoSize = CGSizeMake(960, 544); + } else { + imageToMovieComposer.videoSize = CGSizeMake(544, 960); + } + + // Warning:在这之前一定要给 self.imageDuration 赋值,不然就会 crash。 + // 在 - (void)setupEditToolboxView 里设置了 self.imageDuration = 2.0f;,self.imageDuration 的值的改变通过 - (void)imageDurationButtonClicked:(UIButton *)sender 事件。 + imageToMovieComposer.imageDuration = self.imageDuration; + + [imageToMovieComposer setCompletionBlock:^(NSURL *url) { + NSLog(@"imageToMovieComposer ur: %@", url); + + [weakSelf removeActivityIndicatorView]; + weakSelf.progressLabel.text = @""; + + MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; + transCodeViewController.url = url; + [self presentViewController:transCodeViewController animated:YES completion:nil]; + }]; + [imageToMovieComposer setFailureBlock:^(NSError *error) { + NSLog(@"imageToMovieComposer failed"); + + [weakSelf removeActivityIndicatorView]; + weakSelf.progressLabel.text = @""; + }]; + [imageToMovieComposer setProcessingBlock:^(float progress) { + NSLog(@"imageToMovieComposer progress: %f", progress); + + weakSelf.progressLabel.text = [NSString stringWithFormat:@"合成进度%d%%", (int)(progress * 100)]; + }]; + + [imageToMovieComposer startComposing]; +} + +// 视频转码 +- (void)movieTransCodeEvent { + MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; + transCodeViewController.url = self.urls[0]; + [self presentViewController:transCodeViewController animated:YES completion:nil]; +} + +// 多个视频拼接 或者 单个视频转码 都可以用 PLSMovieComposer +- (void)movieComposerEvent { + [self loadActivityIndicatorView]; + + __weak typeof(self)weakSelf = self; + self.movieComposer = [[PLSMovieComposer alloc] initWithUrls:self.urls]; + if (self.isMovieLandscapeOrientation) { + self.movieComposer.videoSize = CGSizeMake(960, 544); + } else { + self.movieComposer.videoSize = CGSizeMake(544, 960); } + self.movieComposer.videoFrameRate = 25; + self.movieComposer.outputFileType = PLSFileTypeMPEG4; + + [self.movieComposer setCompletionBlock:^(NSURL *url) { + NSLog(@"movieComposer ur: %@", url); + + [weakSelf removeActivityIndicatorView]; + weakSelf.progressLabel.text = @""; + + MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; + transCodeViewController.url = url; + [weakSelf presentViewController:transCodeViewController animated:YES completion:nil]; + }]; + [self.movieComposer setFailureBlock:^(NSError *error) { + NSLog(@"movieComposer failed"); + + [weakSelf removeActivityIndicatorView]; + weakSelf.progressLabel.text = @""; + + }]; + [self.movieComposer setProcessingBlock:^(float progress){ + NSLog(@"movieComposer progress: %f", progress); + + weakSelf.progressLabel.text = [NSString stringWithFormat:@"拼接进度%d%%", (int)(progress * 100)]; + }]; + + [self.movieComposer startComposing]; } // 加载拼接视频的动画 diff --git a/Example/PLShortVideoKitDemo/PrefixHeader.pch b/Example/PLShortVideoKitDemo/PrefixHeader.pch new file mode 100644 index 00000000..ecee16ba --- /dev/null +++ b/Example/PLShortVideoKitDemo/PrefixHeader.pch @@ -0,0 +1,35 @@ +// +// PrefixHeader.pch +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/6. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#ifndef PrefixHeader_pch +#define PrefixHeader_pch + +// Include any system framework and library headers here that should be included in all compilation units. +// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. + +#ifndef dispatch_main_async_safe +#define dispatch_main_async_safe(block)\ + if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\ + block();\ + } else {\ + dispatch_async(dispatch_get_main_queue(), block);\ + } +#endif + +#ifndef dispatch_main_sync_safe +#define dispatch_main_sync_safe(block)\ + if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\ + block();\ + } else {\ + dispatch_sync(dispatch_get_main_queue(), block);\ + } +#endif + +#define ARRAY_SIZE(c_array) (sizeof((c_array))/sizeof((c_array)[0])) + +#endif /* PrefixHeader_pch */ diff --git a/Example/PLShortVideoKitDemo/RecordViewController.m b/Example/PLShortVideoKitDemo/RecordViewController.m index 33126f52..ba6f1576 100644 --- a/Example/PLShortVideoKitDemo/RecordViewController.m +++ b/Example/PLShortVideoKitDemo/RecordViewController.m @@ -681,7 +681,7 @@ - (void)musicButtonOnClick:(id)sender { self.musicButton.selected = !self.musicButton.selected; if (self.musicButton.selected) { // 背景音乐 - NSURL *audioURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Fire_Breather" ofType:@"m4a"]]; + NSURL *audioURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"counter-35s" ofType:@"m4a"]]; [self.shortVideoRecorder mixAudio:audioURL]; } else{ [self.shortVideoRecorder mixAudio:nil]; @@ -1018,7 +1018,8 @@ - (void)playEvent:(AVAsset *)asset { if (self.musicButton.selected) { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [self loadActivityIndicatorView]; - [self.shortVideoRecorder mixWithMusicVolume:0.3 videoVolume:0.8 completionHandler:^(AVMutableComposition * _Nullable composition, AVAudioMix * _Nullable audioMix, NSError * _Nullable error) { + // MusicVolume:1.0,videoVolume:0.0 即完全丢弃掉拍摄时的所有声音,只保留背景音乐的声音 + [self.shortVideoRecorder mixWithMusicVolume:1.0 videoVolume:0.0 completionHandler:^(AVMutableComposition * _Nullable composition, AVAudioMix * _Nullable audioMix, NSError * _Nullable error) { AVAssetExportSession *exporter = [[AVAssetExportSession alloc]initWithAsset:composition presetName:AVAssetExportPresetHighestQuality]; NSURL *outputPath = [self exportAudioMixPath]; exporter.outputURL = outputPath; diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.h b/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.h new file mode 100644 index 00000000..768a1423 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.h @@ -0,0 +1,35 @@ +// +// BaseViewController.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/1. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import +@import Photos; + +@interface BaseViewController : UIViewController + +@property (strong, nonatomic) UIView *baseToolboxView; +@property (strong, nonatomic) UILabel *titleLabel; +@property (strong, nonatomic) UIActivityIndicatorView *activityIndicatorView; +@property (strong, nonatomic) UILabel *progressLabel; +@property (strong, nonatomic) UIButton *nextButton; +@property (strong, nonatomic) UIButton *backButton; + +- (void)showWating; + +- (void)hideWating; + +- (void)backButtonClick; + +- (void)nextButtonClick; + +- (void)setProgress:(CGFloat)progress; + ++ (NSURL *)movieURL:(PHAsset *)phasset; + ++ (BOOL)checkForPortrait:(CGAffineTransform)transform; + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.m b/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.m new file mode 100644 index 00000000..dba3b0b0 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.m @@ -0,0 +1,207 @@ +// +// BaseViewController.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/1. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "BaseViewController.h" +#import + +#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) +#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] +#define PLS_BaseToolboxView_HEIGHT 64 +#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) +#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) + +@interface BaseViewController () +@end + +@implementation BaseViewController + +- (void)dealloc { + NSLog(@"[dealloc] %@", self.description); +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self setupBaseToolboxView]; + // Do any additional setup after loading the view. +} + +#pragma mark -- 配置视图 +- (void)setupBaseToolboxView { + self.baseToolboxView = [[UIView alloc] init]; + self.baseToolboxView.backgroundColor = [UIColor clearColor]; + [self.view addSubview:self.baseToolboxView]; + + // 关闭按钮 + UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [backButton setImage:[UIImage imageNamed:@"btn_bar_back_a"] forState:UIControlStateNormal]; + [backButton setImage:[UIImage imageNamed:@"btn_bar_back_b"] forState:UIControlStateHighlighted]; + [backButton setTitle:@"返回" forState:UIControlStateNormal]; + [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [backButton setTitleColor:PLS_RGBCOLOR(141, 141, 142) forState:UIControlStateHighlighted]; + backButton.titleEdgeInsets = UIEdgeInsetsMake(0, 7, 0, 0); + backButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [backButton addTarget:self action:@selector(backButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [self.baseToolboxView addSubview:backButton]; + self.backButton = backButton; + + // 标题 + self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 100, 64)]; + if (iPhoneX) { + self.titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 48); + } else { + self.titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 32); + } + self.titleLabel.text = @" "; + self.titleLabel.textAlignment = NSTextAlignmentCenter; + self.titleLabel.numberOfLines = 0; + self.titleLabel.textColor = [UIColor grayColor]; + self.titleLabel.font = [UIFont systemFontOfSize:18]; + [self.baseToolboxView addSubview:self.titleLabel]; + + + // 下一步 + UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [nextButton setImage:[UIImage imageNamed:@"btn_bar_next_a"] forState:UIControlStateNormal]; + [nextButton setImage:[UIImage imageNamed:@"btn_bar_next_b"] forState:UIControlStateHighlighted]; + [nextButton setTitle:@"下一步" forState:UIControlStateNormal]; + [nextButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [nextButton setTitleColor:PLS_RGBCOLOR(141, 141, 142) forState:UIControlStateHighlighted]; + nextButton.frame = CGRectMake(PLS_SCREEN_WIDTH - 80, 0, 80, 64); + nextButton.titleEdgeInsets = UIEdgeInsetsMake(0, -40, 0, 0); + nextButton.imageEdgeInsets = UIEdgeInsetsMake(0, 50, 0, 0); + nextButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [nextButton addTarget:self action:@selector(nextButtonClick) forControlEvents:UIControlEventTouchUpInside]; + [self.baseToolboxView addSubview:nextButton]; + + [self.baseToolboxView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.equalTo(self.view); + if (iPhoneX) { + make.height.equalTo(@(84)); + } else { + make.height.equalTo(@(PLS_BaseToolboxView_HEIGHT)); + } + }]; + + backButton.frame = CGRectMake(0, 0, 80, 64); + [backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.bottom.equalTo(self.baseToolboxView); + make.width.equalTo(@(80)); + make.height.equalTo(@(64)); + }]; + + [nextButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.bottom.equalTo(self.baseToolboxView); + make.width.equalTo(@(80)); + make.height.equalTo(@(64)); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.backButton); + make.centerX.equalTo(self.baseToolboxView); + make.left.equalTo(backButton.mas_right); + make.right.equalTo(nextButton.mas_left); + }]; + + self.nextButton = nextButton; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)nextButtonClick { +} + +-(void)backButtonClick { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)showWating { + if (nil == self.activityIndicatorView) { + self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.view.bounds]; + self.activityIndicatorView.center = self.view.center; + [self.activityIndicatorView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge]; + self.activityIndicatorView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]; + } + + [self.view addSubview:self.activityIndicatorView]; + if (![self.activityIndicatorView isAnimating]) { + [self.activityIndicatorView startAnimating]; + } +} + +- (void)hideWating { + if ([self.activityIndicatorView isAnimating]) { + [self.activityIndicatorView stopAnimating]; + } + [self.activityIndicatorView removeFromSuperview]; + [self.progressLabel removeFromSuperview]; + self.progressLabel.text = @""; +} + +- (void)setProgress:(CGFloat)progress { + if (nil == self.progressLabel) { + self.progressLabel = [[UILabel alloc] initWithFrame:CGRectMake(160, 0, 200, 45)]; + self.progressLabel.center = CGPointMake(self.view.center.x, self.view.center.y + 30); + self.progressLabel.textAlignment = NSTextAlignmentCenter; + self.progressLabel.textColor = [UIColor whiteColor]; + } + [self.view addSubview:self.progressLabel]; + + self.progressLabel.text = [NSString stringWithFormat:@"%d%%", (int)(progress * 100)]; +} + ++ (NSURL *)movieURL:(PHAsset *)phasset { + + __block NSURL *url = nil; + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init]; + options.version = PHVideoRequestOptionsVersionOriginal; + options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic; + options.networkAccessAllowed = YES; + + PHImageManager *manager = [PHImageManager defaultManager]; + [manager requestAVAssetForVideo:phasset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) { + AVURLAsset *urlAsset = (AVURLAsset *)asset; + url = urlAsset.URL; + + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + + return url; +} + ++ (BOOL)checkForPortrait:(CGAffineTransform)transform { + + BOOL assetPortrait = NO; + + if(transform.a == 0 && transform.b == 1.0 && transform.c == -1.0 && transform.d == 0) { + //is portrait + assetPortrait = YES; + } + else if(transform.a == 0 && transform.b == -1.0 && transform.c == 1.0 && transform.d == 0) { + //is portrait + assetPortrait = YES; + } + else if(transform.a == 1.0 && transform.b == 0 && transform.c == 0 && transform.d == 1.0) { + //is landscape + } + else if(transform.a == -1.0 && transform.b == 0 && transform.c == 0 && transform.d == -1.0) { + //is landscape + } + + return assetPortrait; +} + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.h b/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.h new file mode 100644 index 00000000..c6863758 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.h @@ -0,0 +1,45 @@ +// +// MulitClipViewController.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/1. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "BaseViewController.h" + +@interface MulitClipViewController : BaseViewController + +@property (nonatomic, strong)NSMutableArray *phAssetArray; +@property (nonatomic, strong)NSMutableArray *urlArray; + +@end + + +//需求: +//1,可以对一个或者多个视频进行同时切割 +//2,可以对切割后的效果进行实时预览 +//3,可以在段之间插入转场字幕,视频等 +// +//切割实现: +// +//  1、逻辑切割问题、如对一个视频A(0~50s)进行分割成三段A1(0~10s),A2(10~30s),A3(30~50s),由于这个操作都只是逻辑的操作,并没有将A视频分成三个视频,但是得给人的感觉是将A分成了三个视频。这个过程可以将 A视频进行三份拷贝,每一份拷贝作为一个分段,对每一段视频在A中的起止位置进行标记。 +// +// +// 2、预览和seek问题、对多个视频比如A(0~50s) 和 B(0~30)分别进行切割,分成A1(0~10s),A2(10~30s),A3(30~50s),B1(0~10s),B2(10~30s), +// 用户可以删除任何一段视频比如A2,现在要对剩下的4段视频进行预览和seek。 +// 预览可以用AVPlayer,AVMutableComposition继承自AVAsset。因此用AVMutableComposition和AVMutableCompositionTrack将A视频的0~10s(A1),A视频的30~50s(A3),B视频的0~10s(B1),B视频的10s~30s(B2)加入到AVMutableCompositionTrack中,让这几段视频在一个track中、这样用户在编辑操作中在进行seek的时候,可以准确的seek到需要的位置。 +// +// +// 3、iOS设备home键在上、下、左、右四个方向拍摄的视频混合预览的问题,AVMutableCompositionTrack只能在整个时间段中设置一种preferredTransform,如果以某一个方向拍摄视频的transform去设置AVMutableCompositionTrack的transform,那么其他三种视频预览的时候,方向会出现不对的情况,因此不能在AVMutableCompositionTrack的preferredTransform中去处理这个问题。 +// AVPlayerItem中有属性AVMutableVideoComposition,AVMutableVideoComposition可以针对对不同的时间段进行transform操作,因此可以用AVMutableVideoComposition + AVMutableVideoCompositionInstruction + AVMutableVideoCompositionLayerInstruction来解决iOS不同方向拍摄的视频混合在一个track钟预览的方向问题。 +// +// +// +// 代码实现思路: +// 开始的时候选择多个视频进行切割,用一个数组保存这些视频,并记下每一个视频的起止时间。当对其中某一个视频进行切割的时候,可以将该视频进行一个复制,然后标记切割之后两段视频的起止时间,然后更新播放器的AVPlayerItem,之后的每一次切割、删除或者插入新的视频,都用类似的方法进行操作。 + + + + + diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.m b/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.m new file mode 100644 index 00000000..e354ff73 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.m @@ -0,0 +1,440 @@ +// +// MulitClipViewController.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/1. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#ifndef MAS_SHORTHAND_GLOBALS + #define MAS_SHORTHAND_GLOBALS +#endif + +#import "MulitClipViewController.h" +#import "PLShortVideoKit/PLShortVideoKit.h" +#import +#import "PhotoAlbumViewController.h" +#import "MovieTransCodeViewController.h" +#import "PLSClipMulitMediaView.h" +#import "PLSSelectionView.h" +#import "PLSPlayerView.h" +#import "TransitionViewController.h" +#import "EditViewController.h" + +#define TransitionVideoFolder @"transition_mp4" +#define RangeVideoFolder @"range_mp4" + +@interface MulitClipViewController () +< +PLSClipMulitMediaViewDelegate, +TransitionViewControllerDelegate +> +{ + id _timeObserverToken; +} +// 播放器 +@property (strong, nonatomic) AVPlayer *player; +@property (strong, nonatomic) PLSPlayerView *playerView; + +// 选取需要的视频段 +@property (strong, nonatomic) PLSClipMulitMediaView *clipView; +@property (assign, nonatomic) CGFloat startTime; +@property (assign, nonatomic) CGFloat endTime; + +@property (strong, nonatomic) PLShortVideoTranscoder *shortVideoTranscoder; +@property (strong, nonatomic) NSMutableArray *avassetArray; + +@property (assign, nonatomic) BOOL isNeedResume; + +@property (strong, nonatomic) PLSRangeMovieExport *mergeExport; + +@property (strong, nonatomic) PLShortVideoTranscoder *singleExport; + +@property (strong, nonatomic) NSMutableArray *transcodingArray; + +@end + +@implementation MulitClipViewController + +- (void)dealloc { + [self removeTimeObserver]; + [self removeObserver]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.transcodingArray = [[NSMutableArray alloc] init]; + + self.view.backgroundColor = [UIColor blackColor]; + self.nextButton.hidden = YES; + self.titleLabel.text = @"单击屏幕播放/暂停"; + + [self setupClipView]; + + [self setupPlayerView]; + + UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [deleteButton setTitle:@"删除" forState:UIControlStateNormal]; + [deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [deleteButton setTitleColor:[UIColor colorWithRed:141.0/255 green:141.0/255 blue:142.0/255 alpha:1] forState:UIControlStateHighlighted]; + deleteButton.titleEdgeInsets = UIEdgeInsetsMake(0, -40, 0, 0); + deleteButton.imageEdgeInsets = UIEdgeInsetsMake(0, 50, 0, 0); + deleteButton.titleLabel.font = [UIFont systemFontOfSize:16]; + [deleteButton addTarget:self.clipView action:@selector(deleteAction) forControlEvents:UIControlEventTouchUpInside]; + [self.baseToolboxView addSubview:deleteButton]; + [deleteButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.nextButton); + }]; + + UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapPlayerView)]; + [self.playerView addGestureRecognizer:singleTap]; + self.playerView.player = self.player; + + [self addObserver]; +} + +- (void)setupClipView { + self.clipView = [[PLSClipMulitMediaView alloc] init]; + self.clipView.delegate = self; + [self.view addSubview:self.clipView]; + + [self.clipView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.bottom.equalTo(self.mas_bottomLayoutGuide); + make.height.equalTo(140); + }]; + + if (self.avassetArray) { + [self.clipView setAssetArray:self.avassetArray]; + } +} + +- (void)setupPlayerView { + self.playerView = [[PLSPlayerView alloc] init]; + [self.view addSubview:self.playerView]; + [self.playerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.top.equalTo(self.baseToolboxView.mas_bottom); + make.bottom.equalTo(self.clipView.mas_top); + }]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)viewDidDisappear:(BOOL)animated { + [self removeTimeObserver]; + [self.player pause]; + [super viewDidDisappear:animated]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self addTimeObserver]; +} + +- (NSURL *)transitionVideoURL { + + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *transitionFolder = [documentsDirectory stringByAppendingPathComponent:TransitionVideoFolder]; + BOOL isDir = NO; + NSError *error = nil; + if (!([[NSFileManager defaultManager] fileExistsAtPath:transitionFolder isDirectory:&isDir] && isDir)) { + BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:transitionFolder withIntermediateDirectories:YES attributes:nil error:&error]; + if (!result) { + NSLog(@"!!!====创建文件夹错误====!!!"); + return nil; + } + } + + NSDateFormatter *format = [[NSDateFormatter alloc] init]; + [format setDateFormat:@"yyyyMMddHHmmssmmm"]; + NSString *videoPath = [NSString stringWithFormat:@"%@/%@.mp4", transitionFolder, [format stringFromDate:[NSDate date]]]; + + return [NSURL fileURLWithPath:videoPath]; +} + +- (NSURL *)editVideoURL { + + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *transitionFolder = [documentsDirectory stringByAppendingPathComponent:RangeVideoFolder]; + BOOL isDir = NO; + NSError *error = nil; + if (!([[NSFileManager defaultManager] fileExistsAtPath:transitionFolder isDirectory:&isDir] && isDir)) { + BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:transitionFolder withIntermediateDirectories:YES attributes:nil error:&error]; + if (!result) { + NSLog(@"!!!====创建文件夹错误====!!!"); + return nil; + } + } + + NSDateFormatter *format = [[NSDateFormatter alloc] init]; + [format setDateFormat:@"yyyyMMddHHmmssmmm"]; + NSString *videoPath = [NSString stringWithFormat:@"%@/%@.mp4", transitionFolder, [format stringFromDate:[NSDate date]]]; + + return [NSURL fileURLWithPath:videoPath]; +} + ++ (dispatch_queue_t)setupPlayerQueue { + static dispatch_queue_t playerQueue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + playerQueue = dispatch_queue_create("mulit.player.init", DISPATCH_QUEUE_SERIAL); + }); + return playerQueue; +} + +- (void)singleTapPlayerView { + if (0 == self.player.rate) { + [self.player setRate:1]; + } else { + [self.player setRate:0]; + } +} + +- (void)setupClipMovieView { + +} + +static int KVOcontext = 0; +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if (context != &KVOcontext) return; + + if ([keyPath isEqualToString:@"player.status"]) { + NSNumber *num = change[NSKeyValueChangeNewKey]; + if (AVPlayerStatusReadyToPlay == [num integerValue]) { +// [self.player play]; + } + } +} + +- (void)addObserver { + [self addObserver:self forKeyPath:@"player.status" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:&KVOcontext]; +} + +- (void)removeObserver { + [self removeObserver:self forKeyPath:@"player.status"]; +} + +- (void)addTimeObserver { + if (nil == _timeObserverToken) { + __weak typeof(self) wself = self; + _timeObserverToken = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 10) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { + [wself.clipView setPlayPosition:time]; + }]; + } +} + +- (void)removeTimeObserver { + if (_timeObserverToken) { + [self.player removeTimeObserver:_timeObserverToken]; + _timeObserverToken = nil; + } +} + +- (void)setupPlayerWithItem:(AVPlayerItem *)playItem { + + [self removeTimeObserver]; + self.player = [AVPlayer playerWithPlayerItem:playItem]; + [self addTimeObserver]; + + dispatch_main_sync_safe(^{ + self.playerView.player = self.player; + }); +} + +- (void)setPhAssetArray:(NSMutableArray *)phAssetArray { + _phAssetArray = phAssetArray; + + dispatch_async([self.class setupPlayerQueue],^{ + + if (!self.avassetArray) { + self.avassetArray = [[NSMutableArray alloc] init]; + } else { + [self.avassetArray removeAllObjects]; + } + + if (self.phAssetArray.count) { + for (int i = 0; i < self.phAssetArray.count; i ++) { + AVAsset *asset = [AVURLAsset assetWithURL:[BaseViewController movieURL:self.phAssetArray[i]]]; + if (asset) { + [self.avassetArray addObject:asset]; + } + } + } else if (self.urlArray.count) { + for (int i = 0; i < self.urlArray.count; i ++) { + AVAsset *asset = [AVURLAsset assetWithURL:self.urlArray[i]]; + if (asset) { + [self.avassetArray addObject:asset]; + } + } + } + + if (self.clipView) { + self.clipView.assetArray = self.avassetArray; + } + }); +} + +- (void)transcoding { + + [self.singleExport cancelTranscoding]; + + if (self.transcodingArray.count) { + [self showWating]; + PLSRangeMedia *rangeMedia = [self.transcodingArray objectAtIndex:0]; + [self.transcodingArray removeObject:rangeMedia]; + + self.singleExport = [[PLShortVideoTranscoder alloc] initWithAsset:rangeMedia.asset]; + self.singleExport.timeRange = CMTimeRangeMake(rangeMedia.startTime, rangeMedia.endTime); + self.singleExport.outputURL = [self editVideoURL]; + __weak typeof(self) wself = self; + self.singleExport.processingBlock = ^(float progress) { + dispatch_main_async_safe(^{ + [wself setProgress:progress]; + }) + }; + self.singleExport.completionBlock = ^(NSURL *url) { + dispatch_main_async_safe(^{ + UISaveVideoAtPathToSavedPhotosAlbum([url path], nil, nil, nil); + [wself transcoding]; + }) + }; + self.singleExport.failureBlock = ^(NSError *error) { + dispatch_main_async_safe(^{ + NSLog(@"error = %@", error.localizedDescription); + [wself transcoding]; + }) + }; + + [self.singleExport startTranscoding]; + + } else { + [self hideWating]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"保存完成" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil]; + [alert show]; + } +} + +// PLSClipMulitMediaViewDelegate +- (void)clipScrollViewWillBeginDragging:(PLSClipMulitMediaView *)clipView { + self.isNeedResume = self.player.rate >= 1; + [self.player pause]; +} + +- (void)clipScrollViewWillEndDragging:(PLSClipMulitMediaView *)clipView { + if (self.isNeedResume) { +// [self.player play]; + } +} + +- (void)clipView:(PLSClipMulitMediaView *)clipView refreshPlayItem:(AVPlayerItem *)playItem { + [self setupPlayerWithItem:playItem]; +} + +- (void)clipView:(PLSClipMulitMediaView *)clipView seekToTime:(CMTime)seekTime { + [self.player seekToTime:seekTime completionHandler:^(BOOL finished) {}]; +} + +- (void)clipView:(PLSClipMulitMediaView *)clipView insertVideoWithAsset:(AVAsset *)asset{ + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"选择添加" message:nil preferredStyle:(UIAlertControllerStyleActionSheet)]; + + UIAlertAction *transitionAction = [UIAlertAction actionWithTitle:@"文字转场" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) { + TransitionViewController *transitionController = [[TransitionViewController alloc] init]; + transitionController.backgroundVideoURL = [(AVURLAsset *)asset URL]; + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:transitionController]; + transitionController.delegate = self; + [self presentViewController:navigationController animated:YES completion:nil]; + }]; + + UIAlertAction *videoAction = [UIAlertAction actionWithTitle:@"图片" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) { + + }]; + + UIAlertAction *imageAction = [UIAlertAction actionWithTitle:@"视频" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) { + + }]; + + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) { + + }]; + + [alert addAction:transitionAction]; +// [alert addAction:videoAction]; +// [alert addAction:imageAction]; + [alert addAction:cancelAction]; + + [self presentViewController:alert animated:YES completion:nil]; +} + +- (void)clipView:(PLSClipMulitMediaView *)clipView finishClip:(NSArray *)mediaArray { + + if (0 == mediaArray.count) { + [self dismissViewControllerAnimated:YES completion:nil]; + return; + } + + [self.mergeExport stopExport]; + self.mergeExport = [[PLSRangeMovieExport alloc] initWithRangeMedia:mediaArray]; + self.mergeExport.outURL = [self editVideoURL]; + + [self showWating]; + + __weak typeof(self) wself = self; + if (nil == self.mergeExport.completionBlock) { + self.mergeExport.completionBlock = ^(NSURL *url) { + [wself hideWating]; + // 设置音视频、水印等编辑信息 + NSMutableDictionary *outputSettings = [[NSMutableDictionary alloc] init]; + // 待编辑的原始视频素材 + NSMutableDictionary *plsMovieSettings = [[NSMutableDictionary alloc] init]; + AVAsset *asset = [AVAsset assetWithURL:url]; + plsMovieSettings[PLSURLKey] = url; + plsMovieSettings[PLSAssetKey] = asset; + plsMovieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:0.0]; + plsMovieSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(asset.duration)]; + plsMovieSettings[PLSVolumeKey] = [NSNumber numberWithFloat:1.0f]; + outputSettings[PLSMovieSettingsKey] = plsMovieSettings; + + EditViewController *videoEditViewController = [[EditViewController alloc] init]; + videoEditViewController.settings = outputSettings; + videoEditViewController.filesURLArray = @[url]; + [wself presentViewController:videoEditViewController animated:YES completion:nil]; + }; + self.mergeExport.failureBlock = ^(NSError *error) { + [wself hideWating]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:error.localizedDescription delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil]; + [alert show]; + }; + self.mergeExport.processingBlock = ^(float progress) { + [wself setProgress:progress]; + }; + } + + [self.mergeExport startExport]; +} + +- (void)transitionViewController:(TransitionViewController *)transitionController transitionMedia:(NSURL *)transitionURL { + + NSURL *videoURL = [self transitionVideoURL]; + BOOL result = [[NSFileManager defaultManager] moveItemAtPath:transitionURL.path toPath:videoURL.path error:nil]; + if (!result) { + NSLog(@"!!!====保存文件错误====!!!"); + return; + } + + AVAsset *asset = [AVAsset assetWithURL:videoURL]; + if (asset) { + [self.clipView addTransition:asset]; + } + + [self dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/MulitEditViewController.h b/Example/PLShortVideoKitDemo/SegmentEffects/MulitEditViewController.h new file mode 100644 index 00000000..8bd4aaa0 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/MulitEditViewController.h @@ -0,0 +1,13 @@ +// +// MulitEditViewController.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/1. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "BaseViewController.h" + +@interface MulitEditViewController : BaseViewController + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/MulitEditViewController.m b/Example/PLShortVideoKitDemo/SegmentEffects/MulitEditViewController.m new file mode 100644 index 00000000..5602babc --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/MulitEditViewController.m @@ -0,0 +1,38 @@ +// +// MulitEditViewController.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/1. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "MulitEditViewController.h" +#import + +@interface MulitEditViewController () + +@end + +@implementation MulitEditViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/MulitPhotoAlbumViewController.h b/Example/PLShortVideoKitDemo/SegmentEffects/MulitPhotoAlbumViewController.h new file mode 100644 index 00000000..fe6541f6 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/MulitPhotoAlbumViewController.h @@ -0,0 +1,13 @@ +// +// MulitPhotoAlbumViewController.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/1. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "PhotoAlbumViewController.h" + +@interface MulitPhotoAlbumViewController : PhotoAlbumViewController + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/MulitPhotoAlbumViewController.m b/Example/PLShortVideoKitDemo/SegmentEffects/MulitPhotoAlbumViewController.m new file mode 100644 index 00000000..3f14ca5f --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/MulitPhotoAlbumViewController.m @@ -0,0 +1,39 @@ +// +// MulitPhotoAlbumViewController.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/1. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "MulitPhotoAlbumViewController.h" +#import "MulitClipViewController.h" + +@interface MulitPhotoAlbumViewController () + +@end + +@implementation MulitPhotoAlbumViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)nextButtonClick:(UIButton *)sender { + + NSMutableArray *assetArray = [self.dynamicScrollView selectedAssets]; + if (0 == assetArray.count) return; + + MulitClipViewController *mulitClipViewController = [[MulitClipViewController alloc] init]; + mulitClipViewController.phAssetArray = assetArray; + + [self presentViewController:mulitClipViewController animated:YES completion:nil]; +} + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/PLSClipMulitMediaView.h b/Example/PLShortVideoKitDemo/SegmentEffects/PLSClipMulitMediaView.h new file mode 100644 index 00000000..5b14db89 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/PLSClipMulitMediaView.h @@ -0,0 +1,48 @@ +// +// PLSClipMulitMediaView.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/2. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import +#import + +@class PLSRangeMedia; +@class PLSClipMulitMediaView; +@protocol PLSClipMulitMediaViewDelegate +< +NSObject +> + +- (void)clipScrollViewWillBeginDragging:(PLSClipMulitMediaView *)clipView; + +- (void)clipScrollViewWillEndDragging:(PLSClipMulitMediaView *)clipView; + +- (void)clipView:(PLSClipMulitMediaView *)clipView seekToTime:(CMTime)seekTime; + +- (void)clipView:(PLSClipMulitMediaView *)clipView insertVideoWithAsset:(AVAsset *)asset; + +- (void)clipView:(PLSClipMulitMediaView *)clipView refreshPlayItem:(AVPlayerItem *)playItem; + +- (void)clipView:(PLSClipMulitMediaView *)clipView finishClip:(NSArray *)mediaArray; + +@end + +@interface PLSClipMulitMediaView : UIView + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, strong) NSArray *assetArray; + +// 设置播放进度 +- (void)setPlayPosition:(CMTime)playPositon; + +// 添加转场字母 +- (void)addTransition:(AVAsset *)asset; + +// 删除某一段 +- (void)deleteAction; + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/PLSClipMulitMediaView.m b/Example/PLShortVideoKitDemo/SegmentEffects/PLSClipMulitMediaView.m new file mode 100644 index 00000000..6917ef08 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/PLSClipMulitMediaView.m @@ -0,0 +1,621 @@ +// +// PLSClipMulitMediaView.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/2. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "PLSClipMulitMediaView.h" +#import +#import "BaseViewController.h" +#import "PLShortVideoKit/PLShortVideoKit.h" + +#ifndef MAS_SHORTHAND_GLOBALS + #define MAS_SHORTHAND_GLOBALS +#endif + +#import + +@interface PLSClipMulitMediaView () + +@property (nonatomic, strong) NSLock *lock; + +@property (nonatomic, strong) UIButton *cutButton; +@property (nonatomic, strong) UIButton *insertButton; +@property (nonatomic, strong) UIButton *continueButton; +@property (nonatomic, strong) UILabel *durationLabel; +@property (nonatomic, strong) UILabel *positionTimeLabel; + +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) UIImageView *positionLine; + +@property (nonatomic, strong) NSMutableArray *imageGeneratorArray; +@property (nonatomic, strong) NSMutableArray *thumbImageArray; +@property (nonatomic, strong) NSMutableArray *thumbCountArray; + +@property (nonatomic, strong) NSMutableArray *clipMediaArray; + +@property (nonatomic, assign) CGFloat positionOffset; +@property (nonatomic, assign) CGFloat totalDuration; + +@property (nonatomic, assign) NSInteger mediaInsertPosition; + +/** + 标记变量。在手滑动collectionview的时候,会将播放器的进度设置到对应的collectionview滑动的位置,而播放器播放位置变化的时候,也会来设置collectionView的contentoffset,避免循环作用,在手使collectionview.contentOffset发生变化的时候,播放器的播放位置变化将不会作用于collectionview.contentOffset + */ +@property (nonatomic, assign) BOOL isDragging; + +@end + +@implementation PLSClipMulitMediaView + +- (void)dealloc { + [self removeObservers]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.lock = [[NSLock alloc] init]; + self.clipMediaArray = [[NSMutableArray alloc] init]; + self.thumbImageArray = [[NSMutableArray alloc] init]; + self.thumbCountArray = [[NSMutableArray alloc] init]; + + [self initTopBar]; + + [self initSwipControl]; + } + + [self addObservers]; + + return self; +} + +- (void)showAlert:(NSString *)alertMessage { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:alertMessage delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil]; + [alert show]; +} + +- (void)initTopBar { + + self.durationLabel = [[UILabel alloc] init]; + self.durationLabel.font = [UIFont systemFontOfSize:12]; + if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0) { + self.durationLabel.font = [UIFont monospacedDigitSystemFontOfSize:12 weight:(UIFontWeightBold)]; + } + self.durationLabel.textColor = [UIColor whiteColor]; + self.durationLabel.textAlignment = NSTextAlignmentCenter; + + self.positionTimeLabel = [[UILabel alloc] init]; + self.positionTimeLabel.font = [UIFont systemFontOfSize:12]; + if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0) { + self.positionTimeLabel.font = [UIFont monospacedDigitSystemFontOfSize:12 weight:(UIFontWeightBold)]; + } + self.positionTimeLabel.textColor = [UIColor whiteColor]; + self.positionTimeLabel.textAlignment = NSTextAlignmentCenter; + + self.cutButton = [UIButton buttonWithType:(UIButtonTypeSystem)]; + [self.cutButton setTitle:@"切割" forState:UIControlStateNormal]; + self.cutButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.cutButton setTintColor:[UIColor whiteColor]]; + [self.cutButton addTarget:self action:@selector(clickCutButton:) forControlEvents:(UIControlEventTouchUpInside)]; + + self.insertButton = [UIButton buttonWithType:(UIButtonTypeSystem)]; + [self.insertButton setTitle:@"插入" forState:UIControlStateNormal]; + self.insertButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.insertButton setTintColor:[UIColor whiteColor]]; + [self.insertButton addTarget:self action:@selector(clickInsertButton:) forControlEvents:(UIControlEventTouchUpInside)]; + + self.continueButton = [UIButton buttonWithType:(UIButtonTypeSystem)]; + [self.continueButton setTitle:@"完成" forState:UIControlStateNormal]; + self.continueButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.continueButton setTintColor:[UIColor whiteColor]]; + [self.continueButton addTarget:self action:@selector(clickDoneButton:) forControlEvents:(UIControlEventTouchUpInside)]; + + UIView *superView = self; + [superView addSubview:self.continueButton]; + [superView addSubview:self.insertButton]; + [superView addSubview:self.cutButton]; + [superView addSubview:self.durationLabel]; + [superView addSubview:self.positionTimeLabel]; + + [self.cutButton sizeToFit]; + [self.cutButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.top.equalTo(self).offset(10); + make.size.equalTo(self.cutButton.bounds.size); + }]; + + [self.insertButton sizeToFit]; + [self.insertButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.top.equalTo(self).offset(10); + make.size.equalTo(self.insertButton.bounds.size); + }]; + + [self.continueButton sizeToFit]; + [self.continueButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self).offset(10); + make.right.equalTo(self).offset(-10); + make.size.equalTo(self.continueButton.bounds.size); + }]; + + [self.durationLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.cutButton); + make.left.equalTo(self.cutButton.mas_right).offset(10); + make.right.equalTo(self.continueButton.mas_left).offset(10); + }]; +} + +- (void)initSwipControl { + + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + layout.minimumLineSpacing = 0; + layout.minimumInteritemSpacing = 0; + + self.collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:layout]; + [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"]; + self.collectionView.dataSource = self; + self.collectionView.delegate = self; + self.collectionView.bounces = NO; + self.collectionView.delaysContentTouches = NO; + self.collectionView.showsHorizontalScrollIndicator = NO; + + self.positionLine = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cut_bar_progress"]]; + + UIView *superView = self; + [superView addSubview:self.collectionView]; + [superView addSubview:self.positionLine]; + + superView = self.collectionView; + + [self.positionLine mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.bottom.equalTo(superView); + make.centerX.equalTo(self); + make.width.equalTo(self.positionLine.image.size.width); + }]; + + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self); + make.top.equalTo(self.insertButton.mas_bottom).offset(10); + make.height.equalTo(60); + make.width.equalTo(self).offset(-20); + }]; + + + [self.positionTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self.positionLine.mas_bottom).offset(2); + }]; +} + +// 切割一个视频 +- (void)clickCutButton:(UIButton *)sender { + + CGFloat startX = -1; + CGFloat endX = -1; + NSInteger section = -1; + + [self getCenterSectionPosition:&startX endX:&endX section:§ion]; + + if (-1 == startX || + -1 == endX || + -1 == section) { + return; + } + + PLSRangeMedia *media = self.clipMediaArray[section]; + if (media.isTransition) {//禁止切割转场视频,开发者可以去掉限制 + [self showAlert:@"转场视频不支持切割"]; + return; + } + + CGPoint point = [self convertPoint:self.positionLine.center toView:self.collectionView]; + CGFloat duration = CMTimeGetSeconds(CMTimeSubtract(media.endTime, media.startTime)); + CGFloat frontWidth = point.x - startX; + CGFloat frontDuration = duration * frontWidth / (endX - startX); + CMTime cutTime = CMTimeAdd(media.startTime, CMTimeMake(frontDuration * 1000, 1000)); + + //小于1秒的视频和某个分段小于.5秒的视频不让切割,开发者可以去掉限制 + if (duration < 1 || frontDuration <.5 || duration - frontDuration < .5) { + [self showAlert:@"视频太短了,每一段视频必须大于0.5秒"]; + return; + } + + PLSRangeMedia *newMedia = [[PLSRangeMedia alloc] init]; + newMedia.asset = media.asset; + newMedia.endTime = media.endTime; + newMedia.startTime = cutTime; + media.endTime = cutTime; + + [_clipMediaArray insertObject:newMedia atIndex:[self.clipMediaArray indexOfObject:media] + 1]; + + [self mediaArrayHasUpdate]; +} + +// 插入一个视频 +- (void)clickInsertButton:(UIButton *)sender { + + CGPoint point = [self convertPoint:self.positionLine.center toView:self.collectionView]; + NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:CGPointMake(point.x - 21, point.y)]; + if (!indexPath) { + indexPath = [self.collectionView indexPathForItemAtPoint:CGPointMake(point.x + 20, point.y)]; + self.mediaInsertPosition = indexPath.section;//加入到第0个section + } else { + self.mediaInsertPosition = indexPath.section + 1; + } + if (!indexPath) return; + + if (self.clipMediaArray.count < indexPath.section) return; + + [self.delegate clipView:self insertVideoWithAsset:self.clipMediaArray[indexPath.section].asset]; +} + +// 所有视频分段完成之后 +- (void)clickDoneButton:(UIButton *)sender { + [self.delegate clipView:self finishClip:self.clipMediaArray]; +} + +// 删除某一分段 +- (void)deleteAction { + + CGPoint point = [self convertPoint:self.positionLine.center toView:self.collectionView]; + NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:point]; + if (!indexPath) return; + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"确定删除本段?" message:nil preferredStyle:(UIAlertControllerStyleAlert)]; + + UIAlertAction *deleteAction = [UIAlertAction actionWithTitle:@"删除" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) { + [self.clipMediaArray removeObjectAtIndex:indexPath.section]; + [self mediaArrayHasUpdate]; + }]; + + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) { + }]; + + [alert addAction:deleteAction]; + [alert addAction:cancelAction]; + + UIViewController *controller = [UIApplication sharedApplication].windows[0].rootViewController; + while (controller.presentedViewController) { + controller = controller.presentedViewController; + } + [controller presentViewController:alert animated:YES completion:nil]; +} + +// 分段视频有更新,包括删除,插入转场视频,插入新视频,切割视频 +- (void)mediaArrayHasUpdate { + + if (0 == _clipMediaArray.count) { + [self.delegate clipView:self finishClip:nil]; + return; + } + + [self refreshThumbImage:nil]; + + AVPlayerItem *playItem = [PLSRangeMediaTools playerItemWithRangeMedia:_clipMediaArray]; + [self.delegate clipView:self refreshPlayItem:playItem]; +} + +// set方法, +- (void)setAssetArray:(NSArray *)assetArray { + _assetArray = assetArray; + + @synchronized(self.clipMediaArray) { + self.totalDuration = 0; + [self.clipMediaArray removeAllObjects]; + for (int i = 0; i < assetArray.count; i ++) { + + PLSRangeMedia *mediaObj = [[PLSRangeMedia alloc] init]; + mediaObj.asset = assetArray[i]; + mediaObj.startTime = CMTimeMake(0, 1000); + mediaObj.endTime = mediaObj.asset.duration; + self.totalDuration += CMTimeGetSeconds(CMTimeSubtract(mediaObj.endTime, mediaObj.startTime)); + + [self.clipMediaArray addObject:mediaObj]; + } + } + + [self mediaArrayHasUpdate]; +} + +// 添加转场字母 +- (void)addTransition:(AVAsset *)asset { + + PLSRangeMedia *mediaObj = [[PLSRangeMedia alloc] init]; + mediaObj.asset = asset; + mediaObj.isTransition = YES; + mediaObj.startTime = CMTimeMake(0, 1000); + mediaObj.endTime = mediaObj.asset.duration; + self.totalDuration += CMTimeGetSeconds(CMTimeSubtract(mediaObj.endTime, mediaObj.startTime)); + + @synchronized(self.clipMediaArray) { + [self.clipMediaArray insertObject:mediaObj atIndex:self.mediaInsertPosition]; + } + + [self mediaArrayHasUpdate]; +} + + +// KVO +static int clipKVOContext = 0; + +static NSString *keyPaths [] = { + @"collectionView.contentOffset", +}; + +- (void)addObservers { + NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew; + for (int i = 0; i < ARRAY_SIZE(keyPaths); i ++) { + [self addObserver:self forKeyPath:keyPaths[i] options:options context:&clipKVOContext]; + } +} + +- (void)removeObservers { + for (int i = 0; i < ARRAY_SIZE(keyPaths); i ++) { + [self removeObserver:self forKeyPath:keyPaths[i]]; + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if (&clipKVOContext != context) return; + + NSValue *newValue = change[NSKeyValueChangeNewKey]; + + if ([keyPaths[0] isEqualToString:keyPath]) { + [self collectionViewContentOffsetChange:[newValue CGPointValue]]; + } +} + +// 监听collectionView的contentOffset来设置按钮的显示和隐藏 +- (void)collectionViewContentOffsetChange:(CGPoint)contentOffset { + + CGPoint point = [self convertPoint:self.positionLine.center toView:self.collectionView]; + NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:point]; + if (indexPath) { + self.cutButton.hidden = NO; + self.insertButton.hidden = YES; + self.durationLabel.hidden = NO; + self.positionTimeLabel.hidden = NO; + } else { + self.cutButton.hidden = YES; + self.insertButton.hidden = NO; + self.durationLabel.hidden = YES; + self.positionTimeLabel.hidden = YES; + return; + } + + if (indexPath.section >= _clipMediaArray.count) return; + + CMTime duration = CMTimeSubtract(_clipMediaArray[indexPath.section].endTime, _clipMediaArray[indexPath.section].startTime); + self.durationLabel.text = [NSString stringWithFormat:@"%3.1f\"", CMTimeGetSeconds(duration)]; + + CGFloat startX = -1; + CGFloat endX = -1; + NSInteger section = -1; + + [self getCenterSectionPosition:&startX endX:&endX section:§ion]; + + CGFloat position = CMTimeGetSeconds(duration) * (point.x - startX) / (endX - startX); + self.positionTimeLabel.text = [NSString stringWithFormat:@"%3.1f\"", fabs(position)]; +} + +// 对collectionview的section进行 self.collectionView.bounds.size.width/2 的 inset 之后,位置和时长的换算要加上或减去这个值 +- (CGFloat)positionOffset { + return self.collectionView.bounds.size.width / 2 + 20;//20的宽度用于插入片头或者片尾 +} + +// 对外方法,根据播放时间点设置collecview的contentoffset,保证self.positionLine在collectionView的位置始终在当前播放点 +- (void)setPlayPosition:(CMTime)playPositon{ + //防止循环调用 + if (self.isDragging) return; + if (0 == CMTimeCompare(playPositon, kCMTimeZero)) return; + + int index = 0; + for (index = 0 ; index < self.clipMediaArray.count; index ++) { + PLSRangeMedia *media = self.clipMediaArray[index]; + CMTime duration = CMTimeSubtract(media.endTime, media.startTime); + + if (-1 == CMTimeCompare(playPositon, duration)) break; + + playPositon = CMTimeSubtract(playPositon, duration); + } + + if (index >= self.clipMediaArray.count) return; + + PLSRangeMedia *media = self.clipMediaArray[index]; + NSInteger itemCount = [self.collectionView numberOfItemsInSection:index]; + NSIndexPath *startPath = [NSIndexPath indexPathForRow:0 inSection:index]; + NSIndexPath *endIndexPath = [NSIndexPath indexPathForRow:itemCount - 1 inSection:index]; + + UICollectionViewLayoutAttributes *startAttributes = [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:startPath]; + UICollectionViewLayoutAttributes *endAttributes = [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:endIndexPath]; + + CGFloat startX = startAttributes.frame.origin.x; + CGFloat endX = endAttributes.frame.origin.x + endAttributes.frame.size.width; + + CGFloat position = CMTimeGetSeconds(playPositon); + CGFloat duration = CMTimeGetSeconds(CMTimeSubtract(media.endTime, media.startTime)); + CGFloat frontWidth = (endX - startX) * position / duration; + + CGFloat seekOriginX = startX + frontWidth; + [self.collectionView setContentOffset:CGPointMake(seekOriginX - self.collectionView.bounds.size.width/2, 0)]; +} + +// 获取positionline在collectionview中的frame和所在section +- (void)getCenterSectionPosition:(CGFloat *)startX endX:(CGFloat *)endX section:(NSInteger *)section { + + CGPoint point = [self convertPoint:self.positionLine.center toView:self.collectionView]; + NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:point]; + if (!indexPath) return; + + NSInteger itemCount = [self.collectionView numberOfItemsInSection:indexPath.section]; + NSIndexPath *startPath = [NSIndexPath indexPathForRow:0 inSection:indexPath.section]; + NSIndexPath *endIndexPath = [NSIndexPath indexPathForRow:itemCount - 1 inSection:indexPath.section]; + + UICollectionViewLayoutAttributes *startAttributes = [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:startPath]; + UICollectionViewLayoutAttributes *endAttributes = [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:endIndexPath]; + *startX = startAttributes.frame.origin.x; + *endX = endAttributes.frame.origin.x + endAttributes.frame.size.width; + *section = indexPath.section; +} + +// 每次编辑的视频变化之后、重新获取thumbImage,Demo为了方便,每次更新都重新获取缩率图,有点浪费资源,开发者可以自己优化 +- (void)refreshThumbImage:(AVAsset *)asset { + + [self.lock lock]; + + for (AVAssetImageGenerator *generator in self.imageGeneratorArray) { + [generator cancelAllCGImageGeneration]; + } + [self.imageGeneratorArray removeAllObjects]; + [self.thumbCountArray removeAllObjects]; + [self.thumbImageArray removeAllObjects]; + + dispatch_main_async_safe(^{ + [self.collectionView reloadData]; + }); + + for (int i = 0; i < _clipMediaArray.count; i ++) { + NSMutableArray *timeArray = [[NSMutableArray alloc] init]; + + float duration = CMTimeGetSeconds(_clipMediaArray[i].endTime) - CMTimeGetSeconds(_clipMediaArray[i].startTime); + float spaceTime = 1;//默认 1s 取一帧, 可以根据实际需要随时改变值 + for (int j = 0; j * spaceTime <= duration; j ++) { + CMTime time = CMTimeMake(j * spaceTime * 1000, 1000); + time = CMTimeAdd(time, _clipMediaArray[i].startTime); + [timeArray addObject:[NSValue valueWithCMTime:time]]; + } + [self.thumbCountArray addObject:[NSNumber numberWithInteger:timeArray.count]]; + + AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:_clipMediaArray[i].asset]; + imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; + imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; + imageGenerator.appliesPreferredTrackTransform = YES; + CGFloat scale = [UIScreen mainScreen].scale; + imageGenerator.maximumSize = CGSizeMake(scale * 40, scale * 60); + + NSMutableArray *imageArray = [[NSMutableArray alloc] init]; + [self.thumbImageArray addObject:imageArray]; + + __weak typeof(self) wself = self; + [imageGenerator generateCGImagesAsynchronouslyForTimes:timeArray completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) { + if (image && AVAssetImageGeneratorSucceeded == result) { + [imageArray addObject:[UIImage imageWithCGImage:image]]; + dispatch_main_async_safe(^{ + [wself.collectionView reloadData]; + }); + } + }]; + } + + [self.lock unlock]; +} + +// 实现collectionView的滑动代理方法,随时将播放器的当前时间点seek到当前的collectionView的中间点位置 +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + + if (self.isDragging) { + + CGFloat position = scrollView.contentOffset.x; + if (position < 0) { + position = 0; + } + if (position > scrollView.contentSize.width - scrollView.bounds.size.width) { + position = scrollView.contentSize.width - scrollView.bounds.size.width; + } + + CGFloat startX = -1; + CGFloat endX = -1; + NSInteger section = -1; + + [self getCenterSectionPosition:&startX endX:&endX section:§ion]; + + if (-1 == startX || + -1 == endX || + -1 == section) { + return; + } + + CGPoint point = [self convertPoint:self.positionLine.center toView:self.collectionView]; + + PLSRangeMedia *media = self.clipMediaArray[section]; + CGFloat duration = CMTimeGetSeconds(CMTimeSubtract(media.endTime, media.startTime)); + CGFloat frontWidth = point.x - startX; + CGFloat frontDuration = duration * frontWidth / (endX - startX); + CMTime seekTime = CMTimeMake(frontDuration * 1000, 1000); + for (int i = 0; i < section; i ++) { + media = [self.clipMediaArray objectAtIndex:i]; + seekTime = CMTimeAdd(seekTime, CMTimeSubtract(media.endTime, media.startTime)); + } + + [self.delegate clipView:self seekToTime:seekTime]; + } +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + self.isDragging = YES; + [self.delegate clipScrollViewWillBeginDragging:self]; +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { + self.isDragging = decelerate; + if (!self.isDragging) { + [self.delegate clipScrollViewWillEndDragging:self]; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + self.isDragging = NO; + [self.delegate clipScrollViewWillEndDragging:self]; +} + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return self.thumbCountArray.count; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return [[self.thumbCountArray objectAtIndex:section] integerValue]; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + +#define IMAGE_VIEW_TAG 0x24 + UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath]; + UIImageView *imageView = [cell.contentView viewWithTag:IMAGE_VIEW_TAG]; + if (!imageView) { + imageView = [[UIImageView alloc] initWithFrame:cell.contentView.bounds]; + imageView.contentMode = UIViewContentModeScaleAspectFill; + imageView.clipsToBounds = YES; + imageView.tag = IMAGE_VIEW_TAG; + [cell.contentView addSubview:imageView]; + } + + if (indexPath.section < self.thumbImageArray.count && + indexPath.row < [self.thumbImageArray objectAtIndex:indexPath.section].count) { + imageView.image = [[self.thumbImageArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]; + } else { + imageView.image = [UIImage imageNamed:@"mv4"]; + } + return cell; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + return CGSizeMake(40, collectionView.bounds.size.height); +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { + if (0 == section) { + return CGSizeMake(self.positionOffset, collectionView.bounds.size.height); + } + return CGSizeZero; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { + if (section == self.clipMediaArray.count - 1) { + return CGSizeMake(self.positionOffset, collectionView.bounds.size.height); + } + return CGSizeMake(20, collectionView.bounds.size.height);; +} + +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/PLSPlayerView.h b/Example/PLShortVideoKitDemo/SegmentEffects/PLSPlayerView.h new file mode 100644 index 00000000..a9f8c80a --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/PLSPlayerView.h @@ -0,0 +1,16 @@ +// +// PLSPlayerView.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/2. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +@import AVFoundation; + +@interface PLSPlayerView : UIView +@property AVPlayer *player; +@property (readonly) AVPlayerLayer *playerLayer; +@end diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/PLSPlayerView.m b/Example/PLShortVideoKitDemo/SegmentEffects/PLSPlayerView.m new file mode 100644 index 00000000..d622da62 --- /dev/null +++ b/Example/PLShortVideoKitDemo/SegmentEffects/PLSPlayerView.m @@ -0,0 +1,30 @@ +// +// PLSPlayerView.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/2. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "PLSPlayerView.h" + +@implementation PLSPlayerView + +- (AVPlayer *)player { + return self.playerLayer.player; +} + +- (void)setPlayer:(AVPlayer *)player { + self.playerLayer.player = player; +} + ++ (Class)layerClass { + return [AVPlayerLayer class]; +} + +- (AVPlayerLayer *)playerLayer { + return (AVPlayerLayer *)self.layer; +} + + +@end diff --git a/Example/PLShortVideoKitDemo/Transition/TransitionModelMaker.h b/Example/PLShortVideoKitDemo/Transition/TransitionModelMaker.h new file mode 100644 index 00000000..26888a08 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Transition/TransitionModelMaker.h @@ -0,0 +1,106 @@ +// +// TransitionModelView.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/1/25. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import +#import + + +@interface TransitionModelMaker : NSObject + +@property (nonatomic, strong) NSString *title; +@property (nonatomic, strong) NSString *detailTitle; + +@property (nonatomic, strong) UIColor *titleColor; +@property (nonatomic, strong) UIFont *titleFont; + +@property (nonatomic, strong)UIColor *detailTitleColor; +@property (nonatomic, strong)UIFont *detailTitleFont; + +/** +@abstract 根据配置的参数,返回一个CAAnimation对象,预览view的尺寸和导出视频的尺寸不一样的时候,为了能让预览效果达到和导出视频一样效果,需要对动画的位置等做比例缩放 +@param videoSize 最终生成的文字转mp4视频的width、heigh + +@return 包含imageSetting和textSetting + */ +- (NSDictionary *)settingsWithVideoSize:(CGSize)videoSize; +@end + +// 大标题 +@interface TransitionModelMakerBigTitle : TransitionModelMaker + +@property (nonatomic, assign) NSInteger bigTitleSettingID; + +- (NSArray *)bigSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +@end + +// 章节 +@interface TransitionModelMakerChapter : TransitionModelMaker + +@property (nonatomic, assign) NSInteger chapterSettingID; +@property (nonatomic, assign) NSInteger textSettingID; + +- (NSArray *)textSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +- (NSArray *)chapterSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +@end + +// 简约 +@interface TransitionModelMakerSimple : TransitionModelMaker + +@property (nonatomic, assign) NSInteger imageSettingID; +@property (nonatomic, assign) NSInteger textSettingID; + +- (NSArray *)textSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +- (NSArray *)imageSettingTranstionWithImageSetting:(PLSImageSetting *)imageSetting; + +@end + +// 引用 +@interface TransitionModelMakerQuote : TransitionModelMaker + +@property (nonatomic, assign) NSInteger imageSettingID; +@property (nonatomic, assign) NSInteger textSettingID; + +- (NSArray *)textSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +- (NSArray *)imageSettingTranstionWithImageSetting:(PLSImageSetting *)imageSetting; + +@end + +// 标题和副标题 +@interface TransitionModelMakerDetail : TransitionModelMaker + +@property (nonatomic, assign) NSInteger detailSettingID; +@property (nonatomic, assign )NSInteger titleSettingID; + +- (NSArray *)titleSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +- (NSArray *)detailSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +@end + +// 片尾 +@interface TransitionModelMakerTail : TransitionModelMaker + +@property (nonatomic, assign) NSInteger directorNameSettingID; +@property (nonatomic, assign) NSInteger dateLocationValueSettingID; +@property (nonatomic, assign) NSInteger directorSettingID; +@property (nonatomic, assign) NSInteger dateLocationSettingID; + +- (NSArray *)directorSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +- (NSArray *)directorNameSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +- (NSArray *)dateLocationSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +- (NSArray *)dateLocationValueSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting; + +@end diff --git a/Example/PLShortVideoKitDemo/Transition/TransitionModelMaker.m b/Example/PLShortVideoKitDemo/Transition/TransitionModelMaker.m new file mode 100644 index 00000000..162bb719 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Transition/TransitionModelMaker.m @@ -0,0 +1,578 @@ +// +// TransitionModelView.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/1/25. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "TransitionModelMaker.h" +#import + + +@implementation TransitionModelMaker + +- (CGFloat)edagSpace { + return 30; +} + +- (CGSize)sizeWithFont:(UIFont *)font andMaxSize:(CGSize)size text:(NSString *)text { + NSDictionary*attrs =@{NSFontAttributeName: font}; + CGSize textSize = [text boundingRectWithSize:size options:NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size; + return CGSizeMake(textSize.width + 10, textSize.height); +} + +- (NSDictionary *)settingsWithVideoSize:(CGSize)videoSize { + return nil; +} + +- (UIColor *)colorWithHexString:(NSString *)hexString{ + return [self colorWithHexString:hexString alpha:1]; +} + +- (UIColor *)colorWithHexString:(NSString *)hexString alpha:(float)alpha{ + + if ([hexString hasPrefix:@"#"]) { + hexString = [hexString stringByReplacingOccurrencesOfString:@"#" withString:@""]; + } + + unsigned int red, green, blue; + NSRange range; + range.length = 2; + range.location = 0; + [[NSScanner scannerWithString:[hexString substringWithRange:range]] scanHexInt:&red]; + range.location = 2; + [[NSScanner scannerWithString:[hexString substringWithRange:range]] scanHexInt:&green]; + range.location = 4; + [[NSScanner scannerWithString:[hexString substringWithRange:range]] scanHexInt:&blue]; + + return [UIColor colorWithRed:(float)(red/255.0f) green:(float)(green/255.0f) blue:(float)(blue/255.0f) alpha:(float)(alpha*1.0f)]; +} + +- (PLSFadeTranstion *)fadeTransitionWithStartTime:(NSTimeInterval)startTime + duration:(NSTimeInterval)duration + fromOpacity:(CGFloat)fromOpacity + toOpacity:(CGFloat)toOpacity { + + PLSFadeTranstion *fadeTransition = [[PLSFadeTranstion alloc] init]; + fadeTransition.startTimeInMs = startTime; + fadeTransition.durationInMs = duration; + fadeTransition.fromOpacity = fromOpacity; + fadeTransition.toOpacity = toOpacity; + + return fadeTransition; +} + +- (PLSPositionTransition *)positionTransitionWithStartTime:(NSTimeInterval)startTime + duration:(NSTimeInterval)duration + fromPoint:(CGPoint)fromPoint + toPoint:(CGPoint)toPoint { + + PLSPositionTransition *positionTransition = [[PLSPositionTransition alloc] init]; + positionTransition.startTimeInMs = startTime; + positionTransition.durationInMs = duration; + positionTransition.fromPoint = fromPoint; + positionTransition.toPoint = toPoint; + + return positionTransition; +} + +- (PLSRotateTransition *)rotateTransitionWithStartTime:(NSTimeInterval)startTime + duration:(NSTimeInterval)duration + fromAngle:(CGFloat)fromAngle + toAngle:(CGFloat)toAngle { + + PLSRotateTransition *rotateTransition = [[PLSRotateTransition alloc] init]; + rotateTransition.startTimeInMs = startTime; + rotateTransition.durationInMs = duration; + rotateTransition.fromAngle = fromAngle; + rotateTransition.toAngle = toAngle; + + return rotateTransition; +} + +- (PLSScaleTransition *)scaleTransitionWithStartTime:(NSTimeInterval)startTime + duration:(NSTimeInterval)duration + fromScale:(CGFloat)fromScale + toScale:(CGFloat)toScale { + + PLSScaleTransition *scaleTransition = [[PLSScaleTransition alloc] init]; + scaleTransition.startTimeInMs = startTime; + scaleTransition.durationInMs = duration; + scaleTransition.fromScale = fromScale; + scaleTransition.toScale = toScale; + + return scaleTransition; +} + +@end + + +@implementation TransitionModelMakerBigTitle + +- (NSDictionary *)settingsWithVideoSize:(CGSize)videoSize { + + CGFloat sizeScale = videoSize.width / 375.0; + + if (!self.title.length) { + self.title = @"七月与安生"; + } + if (!self.titleFont) { + // PingFangSC iOS9之后才加入的字体,如果iOS9之前的需要自己导入PingFangSC字体 + if (@available(iOS 9, *)) { + self.titleFont = [UIFont fontWithName:@"PingFangSC-Semibold" size:38*sizeScale]; + } else { +// self.titleFont = [UIFont fontWithName:@"PingFangSC-Semibold" size:38*sizeScale]; + self.titleFont = [UIFont systemFontOfSize:38 * sizeScale]; + } + + } + if (!self.titleColor) { + self.titleColor = [self colorWithHexString:@"#FFFFFF"]; + } + + CGSize textSize = [self sizeWithFont:self.titleFont andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:self.title]; + + PLSTextSetting *textSetting = [[PLSTextSetting alloc] init]; + textSetting.textFont = self.titleFont; + textSetting.textColor = self.titleColor; + textSetting.startX = (videoSize.width - textSize.width)/2; + textSetting.startY = (videoSize.height - textSize.height)/2; + textSetting.text = self.title; + textSetting.textSize = textSize; + + return [NSDictionary dictionaryWithObjectsAndKeys:textSetting ,@"titleSetting", nil]; +} + +- (NSArray *)bigSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0.0f duration:1250.0f fromOpacity:0.0f toOpacity:1.0f]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + return @[fadeTransition, positionTransition]; +} + +@end + + + +@implementation TransitionModelMakerChapter + +- (NSDictionary *)settingsWithVideoSize:(CGSize)videoSize { + + CGFloat sizeScale = videoSize.width / 375.0; + + if (!self.title.length) { + self.title = @"第一章 七年"; + } + + if (!self.titleFont) { + if (@available(iOS 9, *)) { + self.titleFont = [UIFont fontWithName:@"PingFangSC-Regular" size:28 * sizeScale]; + } else { + self.titleFont = [UIFont systemFontOfSize:28 * sizeScale]; + } + } + + if (!self.titleColor) { + self.titleColor = [self colorWithHexString:@"#FFFFFF"]; + } + + CGSize chapterSize = [self sizeWithFont:self.titleFont andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:self.title]; + + PLSTextSetting *chapterTextSetting = [[PLSTextSetting alloc] init]; + chapterTextSetting.textFont = self.titleFont; + chapterTextSetting.textColor = self.titleColor; + chapterTextSetting.startX = videoSize.width - chapterSize.width - [self edagSpace]; + chapterTextSetting.startY = (videoSize.height - chapterSize.height) / 2; + chapterTextSetting.text = self.title; + chapterTextSetting.textSize = chapterSize; + + UIFont *font = nil; + if (@available(iOS 9, *)) { + font = [UIFont fontWithName:@"PingFangSC-Thin" size:16 * sizeScale]; + } else { + font = [UIFont systemFontOfSize:16 * sizeScale]; + } + + chapterSize = [self sizeWithFont:font andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:@"CHAPTER"]; + + PLSTextSetting *chapterSetting = [[PLSTextSetting alloc] init]; + chapterSetting.textFont = font; + chapterSetting.textColor = [self colorWithHexString:@"#FFCC99"]; + chapterSetting.startX = videoSize.width - chapterSize.width - [self edagSpace]; + chapterSetting.startY = chapterTextSetting.startY - chapterSize.height - 10; + chapterSetting.text = @"CHAPTER"; + chapterSetting.textSize = chapterSize; + + return [NSDictionary dictionaryWithObjectsAndKeys: + chapterTextSetting, @"textSetting", + chapterSetting, @"chapterSetting", + nil]; +} + +- (NSArray *)textSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(2 * textSetting.startX + textSetting.textSize.width, center.y) + toPoint:center]; + return @[fadeTransition, positionTransition]; +} + +- (NSArray *)chapterSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + return @[fadeTransition]; +} + +@end + + +@implementation TransitionModelMakerSimple + +- (NSDictionary *)settingsWithVideoSize:(CGSize)videoSize { + + CGFloat sizeScale = videoSize.width / 375.0; + + if (!self.title.length) { + self.title = @"第二章 暖暖"; + } + + if (!self.titleFont) { + self.titleFont = [UIFont systemFontOfSize:28 * sizeScale];//default + } + + if (!self.titleColor) { + self.titleColor = [self colorWithHexString:@"#FFFFFF"]; + } + + CGSize textSize = [self sizeWithFont:self.titleFont andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:self.title]; + + PLSTextSetting *textSetting = [[PLSTextSetting alloc] init]; + textSetting.textFont = self.titleFont; + textSetting.textColor = self.titleColor; + textSetting.startX = [self edagSpace]; + textSetting.startY = (videoSize.height - textSize.height)/2; + textSetting.text = self.title; + textSetting.textSize = textSize; + + PLSImageSetting *imageSetting = [[PLSImageSetting alloc] init]; + imageSetting.image = [UIImage imageNamed:@"pink_line"]; + imageSetting.imageSize = CGSizeMake(imageSetting.image.size.width * sizeScale, imageSetting.image.size.height * sizeScale); + imageSetting.startY = textSetting.startY - imageSetting.imageSize.height - 20; + imageSetting.startX = [self edagSpace]; + + return [NSDictionary dictionaryWithObjectsAndKeys: + textSetting, @"textSetting", + imageSetting, @"imageSetting", + nil]; +} + +- (NSArray *)textSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(-textSetting.textSize.width, center.y) + toPoint:center]; + return @[fadeTransition, positionTransition]; +} + +- (NSArray *)imageSettingTranstionWithImageSetting:(PLSImageSetting *)imageSetting { + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + return @[fadeTransition]; +} + + +@end + + +@implementation TransitionModelMakerQuote + +- (NSDictionary *)settingsWithVideoSize:(CGSize)videoSize { + + CGFloat sizeScale = videoSize.width / 375.0; + + if (!self.title.length) { + self.title = @"村上春树于1949年1月12日出生在日本京都市伏见区,为国语教师村上千秋、村上美幸夫妇的长子。出生不久,家迁至兵库县西宫市夙川。村上春树于1949年1月12日出生在日本京都市伏见区,为国语教师村上千秋、村上美幸夫妇的长子。出生不久,家迁至兵库县西宫市夙川。"; + } + + if (!self.titleFont) { + self.titleFont = [UIFont systemFontOfSize:20 * sizeScale]; + } + + if (!self.titleColor) { + self.titleColor = [self colorWithHexString:@"#339900"]; + } + + CGSize textSize = [self sizeWithFont:self.titleFont andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:self.title]; + + PLSTextSetting *textSetting = [[PLSTextSetting alloc] init]; + textSetting.textFont = self.titleFont; + textSetting.textColor = self.titleColor; + textSetting.startX = [self edagSpace]; + textSetting.startY = (videoSize.height - textSize.height)/2; + textSetting.text = self.title; + textSetting.textSize = textSize; + + PLSImageSetting *imageSetting = [[PLSImageSetting alloc] init]; + imageSetting.image = [UIImage imageNamed:@"green_quot"]; + imageSetting.imageSize = CGSizeMake(imageSetting.image.size.width * sizeScale, imageSetting.image.size.height * sizeScale); + imageSetting.startY = textSetting.startY - imageSetting.imageSize.height - 30; + imageSetting.startX = [self edagSpace]; + + return [NSDictionary dictionaryWithObjectsAndKeys: + textSetting, @"quoteSetting", + imageSetting, @"imageSetting", + nil]; +} + +- (NSArray *)textSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + return @[fadeTransition, positionTransition]; + +} + +- (NSArray *)imageSettingTranstionWithImageSetting:(PLSImageSetting *)imageSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(imageSetting.startX + imageSetting.imageSize.width / 2, imageSetting.startY + imageSetting.imageSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + + return @[fadeTransition, positionTransition]; +} + +@end + + +@implementation TransitionModelMakerDetail + +- (NSDictionary *)settingsWithVideoSize:(CGSize)videoSize { + + CGFloat sizeScale = videoSize.width / 375.0; + + if (!self.title.length) { + self.title = @"挪威的森林"; + } + + if (!self.titleFont) { + self.titleFont = [UIFont systemFontOfSize:36 * sizeScale]; + } + + if (!self.titleColor) { + self.titleColor = [self colorWithHexString:@"#FFFFFF"]; + } + CGSize textSize = [self sizeWithFont:self.titleFont andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:self.title]; + + PLSTextSetting *titleSetting = [[PLSTextSetting alloc] init]; + titleSetting.textFont = self.titleFont; + titleSetting.textColor = self.titleColor; + titleSetting.startX = (videoSize.width - textSize.width)/2; + titleSetting.startY = (videoSize.height - textSize.height)/2; + titleSetting.text = self.title; + titleSetting.textSize = textSize; + + if (!self.detailTitle.length) { + self.detailTitle = @"- 村上春树 -"; + } + + if (!self.detailTitleFont) { + self.detailTitleFont = [UIFont systemFontOfSize:20 * sizeScale]; + } + + if (!self.detailTitleColor) { + self.detailTitleColor = [self colorWithHexString:@"#FFCC99"]; + } + + textSize = [self sizeWithFont:self.detailTitleFont andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:self.detailTitle]; + + PLSTextSetting *detailSetting = [[PLSTextSetting alloc] init]; + detailSetting.textFont = self.detailTitleFont; + detailSetting.textColor = self.detailTitleColor; + detailSetting.startX = (videoSize.width - textSize.width)/2; + detailSetting.startY = titleSetting.startY + titleSetting.textSize.height + 10; + detailSetting.text = self.detailTitle; + detailSetting.textSize = textSize; + + return [NSDictionary dictionaryWithObjectsAndKeys: + titleSetting, @"titleSetting", + detailSetting, @"detailSetting", + nil]; +} + +- (NSArray *)titleSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + + return @[fadeTransition, positionTransition]; +} + +- (NSArray *)detailSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + return @[fadeTransition, positionTransition]; +} + +@end + + +@implementation TransitionModelMakerTail + +- (NSDictionary *)settingsWithVideoSize:(CGSize)videoSize { + + CGFloat sizeScale = videoSize.width / 375.0; + + if (!self.title.length) { + self.title = @"七牛"; + } + + if (!self.titleFont) { + self.titleFont = [UIFont systemFontOfSize:18 * sizeScale]; + } + + if (!self.titleColor) { + self.titleColor = [self colorWithHexString:@"#FFCC99"]; + } + + if (!self.detailTitle.length) { + self.detailTitle = @"2018.1.1 上海"; + } + + CGSize textSize = [self sizeWithFont:self.titleFont andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:self.title]; + + PLSTextSetting *directorNameSetting = [[PLSTextSetting alloc] init]; + directorNameSetting.textFont = self.titleFont; + directorNameSetting.textColor = self.titleColor; + directorNameSetting.startX = (videoSize.width - textSize.width ) / 2; + directorNameSetting.startY = videoSize.height / 2 - 10 - textSize.height; + directorNameSetting.text = self.title; + directorNameSetting.textSize = textSize; + + UIFont *font = [UIFont systemFontOfSize:18 * sizeScale]; + NSString *director = @"DIRECTOR"; + textSize = [self sizeWithFont:font andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:director]; + PLSTextSetting *directorSetting = [[PLSTextSetting alloc] init]; + directorSetting.textFont = font; + directorSetting.textColor = [UIColor whiteColor]; + directorSetting.startX = (videoSize.width - textSize.width ) / 2; + directorSetting.startY = directorNameSetting.startY - textSize.height - 10; + directorSetting.text = director; + directorSetting.textSize = textSize; + + NSString *dateLocation = @"DATE & LOCATION"; + textSize = [self sizeWithFont:font andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:dateLocation]; + PLSTextSetting *dateLocationSetting = [[PLSTextSetting alloc] init]; + dateLocationSetting.textFont = font; + dateLocationSetting.textColor = [UIColor whiteColor]; + dateLocationSetting.startX = (videoSize.width - textSize.width ) / 2; + dateLocationSetting.startY = videoSize.height / 2 + 10; + dateLocationSetting.text = dateLocation; + dateLocationSetting.textSize = textSize; + + if (!self.detailTitleFont) { + self.detailTitleFont = [UIFont systemFontOfSize:18 * sizeScale]; + } + if (!self.detailTitleColor) { + self.detailTitleColor = [self colorWithHexString:@"#FFCC99"]; + } + textSize = [self sizeWithFont:self.detailTitleFont andMaxSize:CGSizeMake(videoSize.width - 2 * [self edagSpace], videoSize.height - 2 * [self edagSpace]) text:self.detailTitle]; + PLSTextSetting *dateLocationValueSetting = [[PLSTextSetting alloc] init]; + dateLocationValueSetting.textFont = self.detailTitleFont; + dateLocationValueSetting.textColor = self.detailTitleColor; + dateLocationValueSetting.startX = (videoSize.width - textSize.width ) / 2; + dateLocationValueSetting.startY = dateLocationSetting.startY + dateLocationSetting.textSize.height + 10; + dateLocationValueSetting.text = self.detailTitle; + dateLocationValueSetting.textSize = textSize; + + return [NSDictionary dictionaryWithObjectsAndKeys: + directorNameSetting, @"directorNameSetting", + directorSetting, @"directorSetting", + dateLocationValueSetting, @"dateLocationValueSetting", + dateLocationSetting, @"dateLocationSetting", + nil]; +} + +- (NSArray *)directorSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + return @[fadeTransition, positionTransition]; + +} + +- (NSArray *)directorNameSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + return @[fadeTransition, positionTransition]; +} + +- (NSArray *)dateLocationSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + return @[fadeTransition, positionTransition]; +} + +- (NSArray *)dateLocationValueSettingTranstionWithTextSetting:(PLSTextSetting *)textSetting { + + PLSFadeTranstion *fadeTransition = [self fadeTransitionWithStartTime:0 duration:1250 fromOpacity:0 toOpacity:1]; + + CGPoint center = CGPointMake(textSetting.startX + textSetting.textSize.width / 2, textSetting.startY + textSetting.textSize.height/2); + PLSPositionTransition *positionTransition = [self positionTransitionWithStartTime:0 + duration:1250 + fromPoint:CGPointMake(center.x, center.y + 50) + toPoint:center]; + return @[fadeTransition, positionTransition]; +} + +@end diff --git a/Example/PLShortVideoKitDemo/Transition/TransitionModelSelectView.h b/Example/PLShortVideoKitDemo/Transition/TransitionModelSelectView.h new file mode 100644 index 00000000..70089ee2 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Transition/TransitionModelSelectView.h @@ -0,0 +1,47 @@ +// +// TransitionModelSelectView.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/1/24. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +typedef NS_ENUM(NSInteger, PLSTextModel) { + PLSTextModelBigTitle, // 大标题 + PLSTextModelchapter, // 章节 + PLSTextModelSimple, // 简约 + PLSTextModelQuote, // 引用 + PLSTextModelDetail, // 标题和副标题 + PLSTextModelTail, // 片尾 +}; + +@interface TextModeCollectionViewCell : UICollectionViewCell + +@property (nonatomic, strong) UILabel *label; + +@property (nonatomic, assign) PLSTextModel model; + +@end + + +@class TransitionModelSelectView; +@protocol TransitionModelSelectViewDelegate +< +NSObject +> + +- (void)modelSelectedView:(TransitionModelSelectView *)selectView selectModel:(PLSTextModel)model; + +- (void)modelSelectedViewEditButtonAction:(TransitionModelSelectView *)selectView; + +- (void)modelSelectedViewSureButtonAction:(TransitionModelSelectView *)selectView; + +@end + +@interface TransitionModelSelectView : UIView + +@property (nonatomic, weak)iddelegate; + +@end diff --git a/Example/PLShortVideoKitDemo/Transition/TransitionModelSelectView.m b/Example/PLShortVideoKitDemo/Transition/TransitionModelSelectView.m new file mode 100644 index 00000000..0b0e2d4c --- /dev/null +++ b/Example/PLShortVideoKitDemo/Transition/TransitionModelSelectView.m @@ -0,0 +1,189 @@ +// +// TransitionModelSelectView.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/1/24. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "TransitionModelSelectView.h" +#import + + +@implementation TextModeCollectionViewCell + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.label = [[UILabel alloc] init]; + self.label.textColor = [UIColor darkGrayColor]; + self.label.textAlignment = NSTextAlignmentCenter; + self.label.numberOfLines = 0; + self.label.font = [UIFont systemFontOfSize:12]; + [self.contentView addSubview:self.label]; + [self.label mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.contentView).insets(UIEdgeInsetsMake(2, 2, 2, 2)); + }]; + } + return self; +} + +- (void)setModel:(PLSTextModel)model { + _model = model; + static NSString *labelTexts[] = { + @"标题", + @"章节", + @"简约", + @"引用", + @"标题与副标题", + @"片尾", + }; + self.label.text = labelTexts[model]; +} + +- (void)setSelected:(BOOL)selected { + [super setSelected:selected]; + if (selected) { + + } else { + + } +} + +@end + + + + +static NSString *collectionCellIdentifier = @"collectionCellIdentifier"; + +@interface TransitionModelSelectView () +< +UICollectionViewDataSource, +UICollectionViewDelegate +> + +@property (nonatomic, strong) UICollectionView *collectionView; + +@end + + +@implementation TransitionModelSelectView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + + self.backgroundColor = [UIColor darkGrayColor]; + + UILabel *label = [[UILabel alloc] init]; + label.font = [UIFont systemFontOfSize:14]; + label.text = @"过场字幕"; + label.textColor = [UIColor colorWithWhite:.8 alpha:1.0]; + + UIButton *sureButton = [UIButton buttonWithType:(UIButtonTypeSystem)]; + [sureButton setTintColor:[UIColor redColor]]; + [sureButton setTitle:@"确定" forState:(UIControlStateNormal)]; + [sureButton addTarget:self action:@selector(clickSureButton:) forControlEvents:(UIControlEventTouchUpInside)]; + + UIButton *editButton = [UIButton buttonWithType:(UIButtonTypeSystem)]; + [editButton setTintColor:[UIColor redColor]]; + [editButton setTitle:@"编辑" forState:(UIControlStateNormal)]; + [editButton addTarget:self action:@selector(clickEditButton:) forControlEvents:(UIControlEventTouchUpInside)]; + + [label sizeToFit]; + [sureButton sizeToFit]; + [editButton sizeToFit]; + [self addSubview:label]; + [self addSubview:sureButton]; + [self addSubview:editButton]; + + [label mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self).offset(20); + make.top.equalTo(self).offset(15); + make.size.equalTo(@(label.bounds.size)); + }]; + + [sureButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self).offset(-20); + make.centerY.equalTo(label); + make.size.equalTo(@(sureButton.bounds.size)); + }]; + + [editButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(sureButton.mas_left).offset(-20); + make.centerY.equalTo(label); + make.size.equalTo(@(editButton.bounds.size)); + }]; + + CGFloat collectionViewHeight = 60; + UICollectionViewFlowLayout* layout = [[UICollectionViewFlowLayout alloc] init]; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + layout.itemSize = CGSizeMake(collectionViewHeight, collectionViewHeight); + layout.minimumLineSpacing = 4; + + self.collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:layout]; + [self.collectionView registerClass:[TextModeCollectionViewCell class] forCellWithReuseIdentifier:collectionCellIdentifier]; + self.collectionView.delegate = self; + self.collectionView.dataSource = self; + self.collectionView.backgroundColor = [UIColor clearColor]; + self.collectionView.showsHorizontalScrollIndicator = NO; + + [self addSubview:self.collectionView]; + + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(label); + make.right.equalTo(self).offset(-20); + make.top.equalTo(label.mas_bottom).offset(20); + make.height.equalTo(@(collectionViewHeight)); + }]; + } + return self; +} + +- (void)clickSureButton:(UIButton *)button { + [self.delegate modelSelectedViewSureButtonAction:self]; +} + +- (void)clickEditButton:(UIButton *)button { + [self.delegate modelSelectedViewEditButtonAction:self]; +} + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return 1; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return PLSTextModelTail - PLSTextModelBigTitle + 1; +} + +// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath: +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + + TextModeCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:collectionCellIdentifier forIndexPath:indexPath]; + if (cell) { + cell.model = PLSTextModelBigTitle + indexPath.row; + } + if (!cell.selectedBackgroundView) { + cell.backgroundColor = [UIColor whiteColor]; + cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds]; + cell.selectedBackgroundView.layer.borderWidth = 2; + cell.selectedBackgroundView.layer.borderColor = [UIColor redColor].CGColor; + } + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + TextModeCollectionViewCell *cell = (TextModeCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath]; + [self.delegate modelSelectedView:self selectModel:cell.model]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + if (!self.collectionView.indexPathsForSelectedItems.count) { + [self.collectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] animated:YES scrollPosition:(UICollectionViewScrollPositionNone)]; + } +} + +@end diff --git a/Example/PLShortVideoKitDemo/Transition/TransitionTextEditViewController.h b/Example/PLShortVideoKitDemo/Transition/TransitionTextEditViewController.h new file mode 100644 index 00000000..9632ad71 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Transition/TransitionTextEditViewController.h @@ -0,0 +1,55 @@ +// +// TransitionTextEditViewController.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/1/23. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import +#import "TransitionModelSelectView.h" + +@class TransitionTextEditViewController; +@protocol TransitionTextEditViewControllerDelegate +< +NSObject +> + +- (void)editViewController:(TransitionTextEditViewController *)editController completeWithModel:(PLSTextModel)model textInfo:(NSDictionary *)textDics; + +@end + +@interface TransitionTextEditViewController : UITableViewController + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, assign) CGFloat scale; + +- (id)initWithDic:(NSDictionary *)dics model:(PLSTextModel)model; + +@end + + + +@class PropertyPickerView; +@protocol PropertyPickerViewDelegate +< +NSObject +> + +- (void)pickerView:(PropertyPickerView *)pickerView disSelectedIndex:(NSInteger)index; + +@end + +@interface PropertyPickerView : UIView + +@property (nonatomic, weak) iddelegate; + +@property (nonatomic, strong) UIPickerView *pickerView; + +- (id)initWithItem:(NSArray *)item; + +- (void)show; +- (void)hide; + +@end diff --git a/Example/PLShortVideoKitDemo/Transition/TransitionTextEditViewController.m b/Example/PLShortVideoKitDemo/Transition/TransitionTextEditViewController.m new file mode 100644 index 00000000..17ef325d --- /dev/null +++ b/Example/PLShortVideoKitDemo/Transition/TransitionTextEditViewController.m @@ -0,0 +1,525 @@ +// +// TransitionTextEditViewController.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/1/23. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "TransitionTextEditViewController.h" +#import + +typedef enum : NSUInteger { + PLSTextProperyFont, + PLSTextProperyColor, + PLSTextProperySize, +} PLSTextPropery; + +@interface TransitionTextEditViewController () +< +UITextFieldDelegate, +PropertyPickerViewDelegate +> + +@property (nonatomic, assign)PLSTextModel model; + +@property (nonatomic, strong) UITextField *titleTextFiled; + +@property (nonatomic, strong) UITextField *detailTextFiled; + +@property (nonatomic, assign) BOOL isTwoTextField; + +@property (nonatomic, strong) NSMutableDictionary *dics; + +@property (nonatomic, assign) BOOL isSelectTitle; + +@property (nonatomic, assign) PLSTextPropery textProperty; + +@property (nonatomic, strong) NSMutableArray *fontArray; + +@property (nonatomic, strong) NSMutableArray *colorArray; + +@property (nonatomic, strong) NSMutableArray *sizeArray; + +@end + +@implementation TransitionTextEditViewController + +- (id)initWithDic:(NSDictionary *)dics model:(PLSTextModel)model { + + self = [super initWithStyle:(UITableViewStyleGrouped)]; + if (self) { + self.isSelectTitle = YES; + self.dics = [[NSMutableDictionary alloc] initWithDictionary:dics]; + self.model = model; + self.isTwoTextField = PLSTextModelDetail == model || PLSTextModelTail == model; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; + self.tableView.separatorColor = [UIColor clearColor]; + self.view.backgroundColor = [UIColor blackColor]; +} + +NSString *fonts[] = {@"zcool-gdh", @"HappyZcool-2016"}; +- (NSArray *)fontArray { + if (nil == _fontArray) { + _fontArray = [[NSMutableArray alloc] initWithObjects:fonts count:sizeof(fonts)/sizeof(fonts[0])]; + NSArray *familyNames = [UIFont familyNames]; + for (NSString* familyName in familyNames) { + NSArray *fontNames = [UIFont fontNamesForFamilyName:familyName]; + if (fontNames.count) { + [_fontArray addObjectsFromArray:fontNames]; + } else { + [_fontArray addObject:familyName]; + } + } + } + return _fontArray; +} + +NSString *colors[] = {@"#FFFFFF", @"#FF3D49", @"#FFEE00", @"#00C6FF", @"#EACFD4", @"#F8EADA", @"#CEFFC6", @"#C3CADA", @"#000000"}; +- (NSMutableArray *)colorArray { + if (nil == _colorArray) { + _colorArray = [[NSMutableArray alloc] initWithObjects:colors count:sizeof(colors)/sizeof(colors[0])]; + } + return _colorArray; +} + +- (NSMutableArray *)sizeArray { + if (nil == _sizeArray) { + _sizeArray = [[NSMutableArray alloc] init]; + for (int i = 0; i < 20; i ++) { + [_sizeArray addObject:[NSString stringWithFormat:@"%d", 14 + 2 * i]]; + } + } + return _sizeArray; +} + +- (UITextField *)titleTextFiled { + + if (nil == _titleTextFiled) { + _titleTextFiled = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width - 30, 80)]; + _titleTextFiled.font = [self.dics objectForKey:@"titleFont"]; + _titleTextFiled.textColor = [self.dics objectForKey:@"titleColor"]; + _titleTextFiled.text = [self.dics objectForKey:@"title"]; + _titleTextFiled.delegate = self; + if (self.isTwoTextField) { + _titleTextFiled.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"输入第一行文字" attributes:@{NSForegroundColorAttributeName : [UIColor lightGrayColor]}]; + } else { + _titleTextFiled.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"在此输入文字" attributes:@{NSForegroundColorAttributeName : [UIColor lightGrayColor]}]; + } + UIView *line = [[UIView alloc] init]; + line.backgroundColor = [UIColor colorWithRed:222.0/255 green:63.0/255 blue:98.0/255 alpha:1]; + [_titleTextFiled addSubview:line]; + line.frame = CGRectMake(0, _titleTextFiled.bounds.size.height - 2, _titleTextFiled.bounds.size.width, 2); + } + return _titleTextFiled; +} + +- (UITextField *)detailTextFiled { + if (nil == _detailTextFiled) { + _detailTextFiled = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width - 30, 80)]; + _detailTextFiled.font = [self.dics objectForKey:@"detailFont"]; + _detailTextFiled.textColor = [self.dics objectForKey:@"detailColor"]; + _detailTextFiled.text = [self.dics objectForKey:@"detailTitle"]; + _detailTextFiled.delegate = self; + _detailTextFiled.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"输入第二行文字" attributes:@{NSForegroundColorAttributeName : [UIColor lightGrayColor]}]; + UIView *line = [[UIView alloc] init]; + line.backgroundColor = [UIColor colorWithRed:222.0/255 green:63.0/255 blue:98.0/255 alpha:1]; + [_detailTextFiled addSubview:line]; + line.frame = CGRectMake(0, _detailTextFiled.bounds.size.height - 2, _detailTextFiled.bounds.size.width, 2); + } + return _detailTextFiled; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)viewDidDisappear:(BOOL)animated { + [self.delegate editViewController:self completeWithModel:self.model textInfo:self.dics]; + + [super viewDidDisappear:animated]; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.isTwoTextField ? 5 : 4; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + NSString *uniqueCellID = [NSString stringWithFormat:@"row%ld", (long)indexPath.row]; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:uniqueCellID]; + if (cell) return cell; + + cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:uniqueCellID]; + cell.backgroundColor = [UIColor blackColor]; + + cell.textLabel.textColor = [UIColor lightGrayColor]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + if (self.isTwoTextField) { + switch (indexPath.row) { + case 0: { + cell.accessoryView = self.titleTextFiled; + } break; + + case 1: { + cell.accessoryView = self.detailTextFiled; + } break; + + case 2: { + cell.textLabel.text = @"颜色"; + } break; + + case 3: { + cell.textLabel.text = @"字体"; + } break; + + case 4: { + cell.textLabel.text = @"大小"; + } break; + } + } else { + switch (indexPath.row) { + case 0: { + cell.accessoryView = self.titleTextFiled; + } break; + + case 1: { + cell.textLabel.text = @"颜色"; + } break; + + case 2: { + cell.textLabel.text = @"字体"; + } break; + + case 3: { + cell.textLabel.text = @"大小"; + } break; + } + } + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + if (self.isTwoTextField) { + switch (indexPath.row) { + case 0: + break; + case 1: + + break; + case 2: { + self.textProperty = PLSTextProperyColor; + [self selectedProperty:self.colorArray]; + } + break; + + case 3: { + self.textProperty = PLSTextProperyFont; + [self selectedProperty:self.fontArray]; + } + break; + + case 4: { + self.textProperty = PLSTextProperySize; + [self selectedProperty:self.sizeArray]; + } + break; + + default: + break; + } + } else { + switch (indexPath.row) { + case 0: + + break; + case 1: { + self.textProperty = PLSTextProperyColor; + [self selectedProperty:self.colorArray]; + } + break; + + case 2: { + self.textProperty = PLSTextProperyFont; + [self selectedProperty:self.fontArray]; + } + break; + + case 3: { + self.textProperty = PLSTextProperySize; + [self selectedProperty:self.sizeArray]; + } + break; + default: + break; + } + } +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.row > 1) { + return 44; + } + if (0 == indexPath.row) { + return 90; + } else {// 1 + return self.isTwoTextField ? 90 : 44; + } +} + +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + return 1; +} + +- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + return nil; +} + +- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { + if (_detailTextFiled == textField) { + self.isSelectTitle = NO; + } else { + self.isSelectTitle = YES; + } + return YES; +} + +- (void)textFieldDidEndEditing:(UITextField *)textField { + if (textField.text.length) { + if (_titleTextFiled == textField) { + [self.dics setObject:textField.text forKey:@"title"]; + } else { + [self.dics setObject:textField.text forKey:@"detailTitle"]; + } + } +} + +- (void) selectedProperty:(NSArray *)array { + + if (self.titleTextFiled.isFirstResponder) { + [self.titleTextFiled resignFirstResponder]; + } + if (self.detailTextFiled.isFirstResponder) { + [self.detailTextFiled resignFirstResponder]; + } + + PropertyPickerView *pickerView = [[PropertyPickerView alloc] initWithItem:array]; + pickerView.delegate = self; + [self.view addSubview:pickerView]; + [pickerView show]; +} + +- (void)pickerView:(PropertyPickerView *)pickerView disSelectedIndex:(NSInteger)index { + switch (_textProperty) { + case PLSTextProperyFont: { + if (self.isSelectTitle) { + UIFont *oldFont = [self.dics objectForKey:@"titleFont"]; + UIFont *newfont = [UIFont fontWithName:_fontArray[index] size:oldFont.pointSize]; + [self.dics setObject:newfont forKey:@"titleFont"]; + } else { + UIFont *oldFont = [self.dics objectForKey:@"detailFont"]; + UIFont *newfont = [UIFont fontWithName:_fontArray[index] size:oldFont.pointSize]; + [self.dics setObject:newfont forKey:@"detailFont"]; + } + } + break; + + case PLSTextProperySize: { + if (self.isSelectTitle) { + UIFont *oldFont = [self.dics objectForKey:@"titleFont"]; + UIFont *newfont = [UIFont fontWithName:oldFont.fontName size:[self.sizeArray[index] integerValue]]; + [self.dics setObject:newfont forKey:@"titleFont"]; + } else { + UIFont *oldFont = [self.dics objectForKey:@"detailFont"]; + UIFont *newfont = [UIFont fontWithName:oldFont.fontName size:[self.sizeArray[index] integerValue]]; + [self.dics setObject:newfont forKey:@"detailFont"]; + } + } + break; + + case PLSTextProperyColor: { + UIColor *newcolor = [self colorWithHexString:self.colorArray[index]]; + if (self.isSelectTitle) { + [self.dics setObject:newcolor forKey:@"titleColor"]; + } else { + [self.dics setObject:newcolor forKey:@"detailColor"]; + } + } + break; + } + + _detailTextFiled.font = [self.dics objectForKey:@"detailFont"]; + _detailTextFiled.textColor = [self.dics objectForKey:@"detailColor"]; + _detailTextFiled.text = [self.dics objectForKey:@"detailTitle"]; + + _titleTextFiled.font = [self.dics objectForKey:@"titleFont"]; + _titleTextFiled.textColor = [self.dics objectForKey:@"titleColor"]; + _titleTextFiled.text = [self.dics objectForKey:@"title"]; + +} + +- (UIColor *)colorWithHexString:(NSString *)hexString{ + + if ([hexString hasPrefix:@"#"]) { + hexString = [hexString stringByReplacingOccurrencesOfString:@"#" withString:@""]; + } + + unsigned int red, green, blue; + NSRange range; + range.length = 2; + range.location = 0; + [[NSScanner scannerWithString:[hexString substringWithRange:range]] scanHexInt:&red]; + range.location = 2; + [[NSScanner scannerWithString:[hexString substringWithRange:range]] scanHexInt:&green]; + range.location = 4; + [[NSScanner scannerWithString:[hexString substringWithRange:range]] scanHexInt:&blue]; + + return [UIColor colorWithRed:(float)(red/255.0f) green:(float)(green/255.0f) blue:(float)(blue/255.0f) alpha:1]; +} + +@end + + + + + +@interface PropertyPickerView () + +@property (nonatomic, strong) NSArray *items; + +@property (nonatomic, strong) UIView *backgroundView; + +@end + +@implementation PropertyPickerView + +- (id)initWithItem:(NSArray *)item { + self = [super initWithFrame:[UIScreen mainScreen].bounds]; + if (self) { + self.items = item; + + UIButton *dismissButton = [UIButton buttonWithType:(UIButtonTypeSystem)]; + [dismissButton addTarget:self action:@selector(hide) forControlEvents:(UIControlEventTouchUpInside)]; + [self addSubview:dismissButton]; + + UIButton *saveButton = [UIButton buttonWithType:(UIButtonTypeSystem)]; + [saveButton setTintColor:[UIColor redColor]]; + [saveButton setTitle:@"确定" forState:(UIControlStateNormal)]; + [saveButton sizeToFit]; + [saveButton addTarget:self action:@selector(clickSaveButton) forControlEvents:(UIControlEventTouchUpInside)]; + + self.pickerView = [[UIPickerView alloc] init]; + self.pickerView.delegate = self; + + self.backgroundView = [[UIView alloc] init]; + self.backgroundView.backgroundColor = [UIColor darkGrayColor]; + [self addSubview:self.backgroundView]; + + [dismissButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.equalTo(self); + make.bottom.equalTo(self.backgroundView.mas_top); + }]; + + [self.backgroundView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self.mas_bottom); + make.height.equalTo(@(250)); + }]; + + [self.backgroundView addSubview:self.pickerView]; + [self.backgroundView addSubview:saveButton]; + + [saveButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.top.equalTo(self.backgroundView); + make.size.equalTo(@(CGSizeMake(60, 44))); + }]; + [self.pickerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.equalTo(self.backgroundView); + make.top.equalTo(saveButton.mas_bottom); + }]; + } + return self; +} + +- (void)show { + + [self layoutIfNeeded]; + + [self.backgroundView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.equalTo(self); + make.height.equalTo(@(250)); + }]; + [self setNeedsUpdateConstraints]; + [self updateConstraintsIfNeeded]; + + [UIView animateWithDuration:.3 animations:^{ + [self layoutIfNeeded]; + }]; + + [self.pickerView selectRow:0 inComponent:0 animated:YES]; + [self.delegate pickerView:self disSelectedIndex:0]; +} + +- (void)hide { + + [self.backgroundView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self.mas_bottom); + make.height.equalTo(@(250)); + }]; + [self setNeedsUpdateConstraints]; + [self updateConstraintsIfNeeded]; + + [UIView animateWithDuration:.3 animations:^{ + [self layoutIfNeeded]; + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + +- (void) clickSaveButton { + [self hide]; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + return self.items.count; +} + +- (NSInteger)numberOfComponentsInPickerView:(nonnull UIPickerView *)pickerView { + return 1; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view { + if (!view) { + view = [[UILabel alloc] init]; + [(UILabel*)view setTextAlignment:NSTextAlignmentCenter]; + } + UILabel *label = (UILabel *)view; + label.text = self.items[row]; + return label; +} + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + if (row >= 0 && row < _items.count) { + [self.delegate pickerView:self disSelectedIndex:row]; + } +} + +@end + + diff --git a/Example/PLShortVideoKitDemo/Transition/TransitionViewController.h b/Example/PLShortVideoKitDemo/Transition/TransitionViewController.h new file mode 100644 index 00000000..f2395308 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Transition/TransitionViewController.h @@ -0,0 +1,27 @@ +// +// TransitionViewController.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/1/23. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +@class TransitionViewController; +@protocol TransitionViewControllerDelegate +< +NSObject +> + +- (void)transitionViewController:(TransitionViewController *)transitionController transitionMedia:(NSURL *)transitionURL; + +@end + +@interface TransitionViewController : UIViewController + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, strong) NSURL *backgroundVideoURL; + +@end diff --git a/Example/PLShortVideoKitDemo/Transition/TransitionViewController.m b/Example/PLShortVideoKitDemo/Transition/TransitionViewController.m new file mode 100644 index 00000000..09742ef8 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Transition/TransitionViewController.m @@ -0,0 +1,487 @@ +// +// TransitionViewController.m +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/1/23. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "TransitionViewController.h" +#import +#import +#import "TransitionModelSelectView.h" +#import "TransitionTextEditViewController.h" +#import "TransitionModelMaker.h" + +@interface TransitionViewController () +< +TransitionModelSelectViewDelegate, +TransitionTextEditViewControllerDelegate, +PLSTransitionMakerDelegate +> + +@property (nonatomic, assign) CGFloat collectionViewHeight; + +@property (nonatomic, strong) PLSTransitionMaker *transitionMaker; + +@property (nonatomic, strong) UIView *waitingView; + +@property (nonatomic, strong) UIActivityIndicatorView *indicatorView; + +@property (nonatomic, strong) TransitionModelSelectView *modelSelectView; + +@property (nonatomic, assign) PLSTextModel textModel; + +@property (nonatomic, strong) TransitionModelMakerBigTitle *makerBigTitle; +@property (nonatomic, strong) TransitionModelMakerChapter *makerChapter; +@property (nonatomic, strong) TransitionModelMakerSimple *makerSimple; +@property (nonatomic, strong) TransitionModelMakerQuote *makerQuote; +@property (nonatomic, strong) TransitionModelMakerDetail *makerDetail; +@property (nonatomic, strong) TransitionModelMakerTail *makerTail; + +@end + +@implementation TransitionViewController + +- (void)dealloc { + NSLog(@"dealloc self.class = %@", NSStringFromClass(self.class)); +} + +- (void)setBackgroundVideoURL:(NSURL *)backgroundVideoURL { + _backgroundVideoURL = backgroundVideoURL; + [self resetBackgroundURL:backgroundVideoURL]; +} + +- (void)resetBackgroundURL:(NSURL *)backgroundURL { + + self.transitionMaker.backgroundVideoURL = backgroundURL; + + // 设置输出视频的时候,根据视频方向校正一下宽高,避免预览和输出的视频宽高对换的问题出现 + AVAsset *asset = [AVAsset assetWithURL:backgroundURL]; + AVAssetTrack *videoAssetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; + self.transitionMaker.totalDuration = 2.55; + CGSize outSize = videoAssetTrack.naturalSize; + + if ([self checkForPortrait:videoAssetTrack.preferredTransform]) { + outSize = CGSizeMake(videoAssetTrack.naturalSize.height, videoAssetTrack.naturalSize.width); + } + self.transitionMaker.outPixelSize = outSize; +} + +- (BOOL)checkForPortrait:(CGAffineTransform)transform { + BOOL assetPortrait = NO; +// (CGAffineTransform) transform = (a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) + + if(transform.a == 0 && transform.b == 1.0 && transform.c == -1.0 && transform.d == 0) { + //is portrait + assetPortrait = YES; + } + else if(transform.a == 0 && transform.b == -1.0 && transform.c == 1.0 && transform.d == 0) { + //is portrait + assetPortrait = YES; + } + else if(transform.a == 1.0 && transform.b == 0 && transform.c == 0 && transform.d == 1.0) { + //is landscape + } + else if(transform.a == -1.0 && transform.b == 0 && transform.c == 0 && transform.d == -1.0) { + //is landscape + } + + return assetPortrait; +} + +- (void)viewDidLoad { + + [super viewDidLoad]; + + self.view.backgroundColor = [UIColor blackColor]; + [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:(UIBarMetricsDefault)]; + [self.navigationController.navigationBar setTintColor:[UIColor whiteColor]]; + self.automaticallyAdjustsScrollViewInsets = NO; + + UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"back" style:(UIBarButtonItemStylePlain) target:self action:@selector(clickBackItem:)]; + self.navigationItem.leftBarButtonItem = backItem; + +// UIBarButtonItem *trashItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:(UIBarButtonSystemItemTrash) target:self action:@selector(clickTrashItem:)]; +// self.navigationItem.rightBarButtonItem = trashItem; + + NSURL *outURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingString:@"/transition_out.mp4"]]; + if ([[NSFileManager defaultManager] fileExistsAtPath:outURL.path]) { + [[NSFileManager defaultManager] removeItemAtURL:outURL error:nil]; + } + + self.transitionMaker = [[PLSTransitionMaker alloc] init]; + if (nil == _backgroundVideoURL) { + _backgroundVideoURL = [[NSBundle mainBundle] URLForResource:@"transition_black" withExtension:@"mp4"]; + } + [self resetBackgroundURL:_backgroundVideoURL]; + + self.transitionMaker.outputVideoURL = outURL; + self.transitionMaker.delegate = self; + self.transitionMaker.backgroundColor = [UIColor blackColor]; + + [self.view addSubview:self.transitionMaker.preview]; + + self.modelSelectView = [[TransitionModelSelectView alloc] init]; + self.modelSelectView.delegate = self; + [self.view addSubview:self.modelSelectView]; + + [self.modelSelectView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.equalTo(self.view); + make.height.equalTo(@(120)); + }]; + [self.transitionMaker.preview mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self.view); + make.top.equalTo(self.mas_topLayoutGuide); + make.bottom.equalTo(self.modelSelectView.mas_top); + }]; + + self.makerBigTitle = [[TransitionModelMakerBigTitle alloc] init]; + self.makerChapter = [[TransitionModelMakerChapter alloc] init]; + self.makerSimple = [[TransitionModelMakerSimple alloc] init]; + self.makerQuote = [[TransitionModelMakerQuote alloc] init]; + self.makerDetail = [[TransitionModelMakerDetail alloc] init]; + self.makerTail = [[TransitionModelMakerTail alloc] init]; + + self.textModel = PLSTextModelBigTitle; + [self resetTransitionWithWithTitle:nil titleFont:nil titleColor:nil detailTitle:nil detailFont:nil detailColor:nil update:NO]; +} + +- (void)showWaitingInView:(UIView*)view { + + if (nil == self.waitingView) { + self.waitingView = [[UIView alloc] init]; + self.waitingView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:.5]; + self.indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleWhite)]; + [self.waitingView addSubview:self.indicatorView]; + [self.indicatorView mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.equalTo(@(CGSizeMake(32, 32))); + make.center.equalTo(self.waitingView); + }]; + } + + [view addSubview:self.waitingView]; + [self.waitingView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(view); + }]; + [self.indicatorView startAnimating]; +} + +- (void)hideWaiting { + [self.indicatorView stopAnimating]; + [self.waitingView removeFromSuperview]; +} + +- (void)clickBackItem:(UIBarButtonItem *)item { + [self.transitionMaker cancelMaking]; + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)clickTrashItem:(UIBarButtonItem *)item { + +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +- (TransitionModelMaker *)selectModelMaker { + switch (_textModel) { + case PLSTextModelBigTitle: + return self.makerBigTitle; + case PLSTextModelchapter: + return self.makerChapter; + case PLSTextModelSimple: + return self.makerSimple; + case PLSTextModelQuote: + return self.makerQuote; + case PLSTextModelDetail: + return self.makerDetail; + case PLSTextModelTail: + return self.makerTail; + } + return nil; +} + +- (void)setTextModel:(PLSTextModel)textModel { + if (textModel != _textModel) { + _textModel = textModel; + + [self.transitionMaker removeAllResource]; + + TransitionModelMaker *selecteMaker = [self selectModelMaker]; + + [self resetTransitionWithWithTitle:selecteMaker.title + titleFont:selecteMaker.titleFont + titleColor:selecteMaker.titleColor + detailTitle:selecteMaker.detailTitle + detailFont:selecteMaker.detailTitleFont + detailColor:selecteMaker.detailTitleColor + update:NO]; + } +} + +- (void)resetTransitionWithWithTitle:(NSString *)title + titleFont:(UIFont *)titleFont + titleColor:(UIColor *)titleColor + detailTitle:(NSString *)detail + detailFont:(UIFont *)detailFont + detailColor:(UIColor *)detailColor + update:(BOOL)update { + + TransitionModelMaker *modelMaker = [self selectModelMaker]; + modelMaker.title = title; + modelMaker.detailTitle = detail; + modelMaker.titleFont = titleFont; + modelMaker.detailTitleFont= detailFont; + modelMaker.titleColor = titleColor; + modelMaker.detailTitleColor = detailColor; + + CGSize videoSize = CGSizeMake(self.transitionMaker.outPixelSize.width, self.transitionMaker.outPixelSize.height); + + switch (_textModel) { + // 大标题 + case PLSTextModelBigTitle: { + NSDictionary *dic = [self.makerBigTitle settingsWithVideoSize:videoSize]; + PLSTextSetting *textSetting = [dic objectForKey:@"titleSetting"]; + NSArray *transitions = [self.makerBigTitle bigSettingTranstionWithTextSetting:textSetting]; + if (update) { + [self.transitionMaker updateTextWithResourceID:self.makerBigTitle.bigTitleSettingID newTextSetting:textSetting]; + } else { + self.makerBigTitle.bigTitleSettingID = [self.transitionMaker addText:textSetting]; + } + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerBigTitle.bigTitleSettingID]; + } + } + break; + + // 章节 + case PLSTextModelchapter: { + NSDictionary *dic = [self.makerChapter settingsWithVideoSize:videoSize]; + + PLSTextSetting *textSetting = [dic objectForKey:@"textSetting"]; + PLSTextSetting *chapterSetting = [dic objectForKey:@"chapterSetting"]; + + if (update) { + [self.transitionMaker updateTextWithResourceID:self.makerChapter.textSettingID newTextSetting:textSetting]; + [self.transitionMaker updateTextWithResourceID:self.makerChapter.chapterSettingID newTextSetting:chapterSetting]; + } else { + self.makerChapter.textSettingID = [self.transitionMaker addText:textSetting]; + self.makerChapter.chapterSettingID = [self.transitionMaker addText:chapterSetting]; + } + + NSArray *transitions = [self.makerChapter textSettingTranstionWithTextSetting:textSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerChapter.textSettingID]; + } + + transitions = [self.makerChapter chapterSettingTranstionWithTextSetting:chapterSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerChapter.chapterSettingID]; + } + } + break; + + // 简约 + case PLSTextModelSimple: { + NSDictionary *dic = [self.makerSimple settingsWithVideoSize:videoSize]; + PLSTextSetting *textSetting = [dic objectForKey:@"textSetting"]; + PLSImageSetting *imageSetting = [dic objectForKey:@"imageSetting"]; + + if (update) { + [self.transitionMaker updateTextWithResourceID:self.makerSimple.textSettingID newTextSetting:textSetting]; + [self.transitionMaker updateImageWithResourceID:self.makerSimple.imageSettingID newImageSetting:imageSetting]; + } else { + self.makerSimple.textSettingID = [self.transitionMaker addText:textSetting]; + self.makerSimple.imageSettingID = [self.transitionMaker addImage:imageSetting]; + } + NSArray *transitions = [self.makerSimple textSettingTranstionWithTextSetting:textSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerSimple.textSettingID]; + } + + transitions = [self.makerSimple imageSettingTranstionWithImageSetting:imageSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerSimple.imageSettingID]; + } + } + break; + + // 引用 + case PLSTextModelQuote: { + NSDictionary *dic = [self.makerQuote settingsWithVideoSize:videoSize]; + PLSTextSetting *textSetting = [dic objectForKey:@"quoteSetting"]; + PLSImageSetting *imageSetting = [dic objectForKey:@"imageSetting"]; + + if (update) { + [self.transitionMaker updateTextWithResourceID:self.makerQuote.textSettingID newTextSetting:textSetting]; + [self.transitionMaker updateImageWithResourceID:self.makerQuote.imageSettingID newImageSetting:imageSetting]; + } else { + self.makerQuote.textSettingID = [self.transitionMaker addText:textSetting]; + self.makerQuote.imageSettingID = [self.transitionMaker addImage:imageSetting]; + } + + NSArray *transitions = [self.makerQuote textSettingTranstionWithTextSetting:textSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerQuote.textSettingID]; + } + + transitions = [self.makerQuote imageSettingTranstionWithImageSetting:imageSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerQuote.imageSettingID]; + } + } + break; + + // 标题和副标题 + case PLSTextModelDetail: { + + NSDictionary *dic = [self.makerDetail settingsWithVideoSize:videoSize]; + + PLSTextSetting *titleTextSetting = [dic objectForKey:@"titleSetting"]; + PLSTextSetting *detailTextSetting = [dic objectForKey:@"detailSetting"]; + + if (update) { + [self.transitionMaker updateTextWithResourceID:self.makerDetail.titleSettingID newTextSetting:titleTextSetting]; + [self.transitionMaker updateTextWithResourceID:self.makerDetail.detailSettingID newTextSetting:detailTextSetting]; + } else { + self.makerDetail.titleSettingID = [self.transitionMaker addText:titleTextSetting]; + self.makerDetail.detailSettingID = [self.transitionMaker addText:detailTextSetting]; + } + + NSArray *transitions = [self.makerDetail titleSettingTranstionWithTextSetting:titleTextSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerDetail.titleSettingID]; + } + + transitions = [self.makerDetail detailSettingTranstionWithTextSetting:detailTextSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerDetail.detailSettingID]; + } + } + break; + + // 片尾 + case PLSTextModelTail: { + NSDictionary *dic = [self.makerTail settingsWithVideoSize:videoSize]; + + PLSTextSetting *directorNameSetting = [dic objectForKey:@"directorNameSetting"]; + PLSTextSetting *directorSetting = [dic objectForKey:@"directorSetting"]; + PLSTextSetting *dateLocationSetting = [dic objectForKey:@"dateLocationSetting"]; + PLSTextSetting *dateLocationValueSetting = [dic objectForKey:@"dateLocationValueSetting"]; + + if (update) { + [self.transitionMaker updateTextWithResourceID:self.makerTail.directorNameSettingID newTextSetting:directorNameSetting]; + [self.transitionMaker updateTextWithResourceID:self.makerTail.directorSettingID newTextSetting:directorSetting]; + [self.transitionMaker updateTextWithResourceID:self.makerTail.dateLocationSettingID newTextSetting:dateLocationSetting]; + [self.transitionMaker updateTextWithResourceID:self.makerTail.dateLocationValueSettingID newTextSetting:dateLocationValueSetting]; + } else { + self.makerTail.directorNameSettingID = [self.transitionMaker addText:directorNameSetting]; + self.makerTail.directorSettingID = [self.transitionMaker addText:directorSetting]; + self.makerTail.dateLocationSettingID = [self.transitionMaker addText:dateLocationSetting]; + self.makerTail.dateLocationValueSettingID = [self.transitionMaker addText:dateLocationValueSetting]; + } + + NSArray *transitions = [self.makerTail directorSettingTranstionWithTextSetting:directorSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerTail.directorSettingID]; + } + + transitions = [self.makerTail directorNameSettingTranstionWithTextSetting:directorNameSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerTail.directorNameSettingID]; + } + + transitions = [self.makerTail dateLocationSettingTranstionWithTextSetting:dateLocationSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerTail.dateLocationSettingID]; + } + + transitions = [self.makerTail dateLocationValueSettingTranstionWithTextSetting:dateLocationValueSetting]; + for (PLSTransition *transition in transitions) { + [self.transitionMaker addTransition:transition resourceID:self.makerTail.dateLocationValueSettingID]; + } + } + break; + default: + break; + } + + [self.transitionMaker play]; +} + +// PLSTransitionMakerDelegate +- (void)transitionMakerPreviewEnd:(PLSTransitionMaker *)transitionMaker { + [self hideWaiting]; +} + +- (void)transitionMaker:(PLSTransitionMaker *)transitionMaker exportMediaSucceed:(NSURL *)outURL { + + [self hideWaiting]; + + if (self.delegate) { + [self.delegate transitionViewController:self transitionMedia:outURL]; + } else { + UISaveVideoAtPathToSavedPhotosAlbum([outURL path], nil, nil, nil); + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"保存视频成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil]; + [alert show]; + } +} + +- (void)transitionMaker:(PLSTransitionMaker *)transitionMaker exportMediaFailed:(NSError *)error { + + [self hideWaiting]; + + NSLog(@"error = %@", error); +} + +// TransitionModelSelectViewDelegate +- (void)modelSelectedView:(TransitionModelSelectView *)selectView selectModel:(PLSTextModel)model { + self.textModel = model; +} + +- (void)modelSelectedViewEditButtonAction:(TransitionModelSelectView *)selectView { + TransitionModelMaker *modelMaker = [self selectModelMaker]; + NSMutableDictionary *dics = [[NSMutableDictionary alloc] init]; + + [dics setObject:modelMaker.title forKey:@"title"]; + [dics setObject:modelMaker.titleFont forKey:@"titleFont"]; + [dics setObject:modelMaker.titleColor forKey:@"titleColor"]; + if (modelMaker.detailTitle) { + [dics setObject:modelMaker.detailTitle forKey:@"detailTitle"]; + [dics setObject:modelMaker.detailTitleFont forKey:@"detailFont"]; + [dics setObject:modelMaker.detailTitleColor forKey:@"detailColor"]; + } + + TransitionTextEditViewController *editViewController = [[TransitionTextEditViewController alloc] initWithDic:dics model:_textModel]; + editViewController.delegate = self; + [self.navigationController pushViewController:editViewController animated:YES]; +} + +- (void)modelSelectedViewSureButtonAction:(TransitionModelSelectView *)selectView { + + [self showWaitingInView:self.view]; + + if (nil == self.transitionMaker.exportProgressBlock) { + self.transitionMaker.exportProgressBlock = ^(CGFloat progress){ + NSLog(@"progress = %f", progress); + }; + } + [self.transitionMaker startMaking]; +} + +// TransitionTextEditViewControllerDelegate +- (void)editViewController:(TransitionTextEditViewController *)editController completeWithModel:(PLSTextModel)model textInfo:(NSDictionary *)textDics { + + NSString *title = [textDics objectForKey:@"title"]; + NSString *detailTitle = [textDics objectForKey:@"detailTitle"]; + UIFont *titleFont = [textDics objectForKey:@"titleFont"]; + UIFont *detailFont = [textDics objectForKey:@"detailFont"]; + UIColor *titleColor = [textDics objectForKey:@"titleColor"]; + UIColor *detailColor = [textDics objectForKey:@"detailColor"]; + + [self resetTransitionWithWithTitle:title titleFont:titleFont titleColor:titleColor detailTitle:detailTitle detailFont:detailFont detailColor:detailColor update:YES]; +} + +@end diff --git a/Example/PLShortVideoKitDemo/TransitionResources/HappyZcool-2016.ttf b/Example/PLShortVideoKitDemo/TransitionResources/HappyZcool-2016.ttf new file mode 100644 index 00000000..ba2ad8a7 Binary files /dev/null and b/Example/PLShortVideoKitDemo/TransitionResources/HappyZcool-2016.ttf differ diff --git a/Example/PLShortVideoKitDemo/TransitionResources/green_quot.png b/Example/PLShortVideoKitDemo/TransitionResources/green_quot.png new file mode 100644 index 00000000..5af21d54 Binary files /dev/null and b/Example/PLShortVideoKitDemo/TransitionResources/green_quot.png differ diff --git a/Example/PLShortVideoKitDemo/TransitionResources/pink_line.png b/Example/PLShortVideoKitDemo/TransitionResources/pink_line.png new file mode 100644 index 00000000..9d023b82 Binary files /dev/null and b/Example/PLShortVideoKitDemo/TransitionResources/pink_line.png differ diff --git a/Example/PLShortVideoKitDemo/TransitionResources/transition_black.mp4 b/Example/PLShortVideoKitDemo/TransitionResources/transition_black.mp4 new file mode 100644 index 00000000..879fbd72 Binary files /dev/null and b/Example/PLShortVideoKitDemo/TransitionResources/transition_black.mp4 differ diff --git a/Example/PLShortVideoKitDemo/TransitionResources/zcool-gdh.ttf b/Example/PLShortVideoKitDemo/TransitionResources/zcool-gdh.ttf new file mode 100644 index 00000000..ee49dea6 Binary files /dev/null and b/Example/PLShortVideoKitDemo/TransitionResources/zcool-gdh.ttf differ diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSClipMovieView.m b/Example/PLShortVideoKitDemo/UI+Tools/PLSClipMovieView.m index 34b8fe56..6f1a2a9e 100644 --- a/Example/PLShortVideoKitDemo/UI+Tools/PLSClipMovieView.m +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSClipMovieView.m @@ -287,7 +287,10 @@ - (void)initData { AVAsset *asset = [AVAsset assetWithURL:self.url]; CMTime cmtime = asset.duration; self.totalSeconds = CMTimeGetSeconds(cmtime); - self.frameRate = [[asset tracksWithMediaType:AVMediaTypeVideo][0] nominalFrameRate]; + + if ([[asset tracksWithMediaType:AVMediaTypeVideo] count] != 0) { + self.frameRate = [[asset tracksWithMediaType:AVMediaTypeVideo][0] nominalFrameRate]; + } self.imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; NSUInteger imageCount = 0; diff --git a/Example/PLShortVideoKitDemo/ViewController.m b/Example/PLShortVideoKitDemo/ViewController.m index b010e363..6d69327d 100644 --- a/Example/PLShortVideoKitDemo/ViewController.m +++ b/Example/PLShortVideoKitDemo/ViewController.m @@ -9,6 +9,8 @@ #import "ViewController.h" #import "RecordViewController.h" #import "PhotoAlbumViewController.h" +#import "MulitPhotoAlbumViewController.h" +#import "H265MovieViewController.h" #define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] @@ -35,6 +37,18 @@ - (void)viewDidLoad { imagesToMovieButton.backgroundColor = [UIColor grayColor]; [imagesToMovieButton addTarget:self action:@selector(imagesToMovieButtonEvent:) forControlEvents:UIControlEventTouchDown]; [self.view addSubview:imagesToMovieButton]; + + UIButton *cutMediaButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 212, self.view.bounds.size.width, 64)]; + [cutMediaButton setTitle:@"视频切割" forState:UIControlStateNormal]; + cutMediaButton.backgroundColor = [UIColor grayColor]; + [cutMediaButton addTarget:self action:@selector(cutMediaButtonEvent:) forControlEvents:UIControlEventTouchDown]; + [self.view addSubview:cutMediaButton]; + + UIButton *importH265VideoButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 286, self.view.bounds.size.width, 64)]; + [importH265VideoButton setTitle:@"导入H.265视频" forState:UIControlStateNormal]; + importH265VideoButton.backgroundColor = [UIColor grayColor]; + [importH265VideoButton addTarget:self action:@selector(importH265VideoButtonEvent:) forControlEvents:UIControlEventTouchDown]; + [self.view addSubview:importH265VideoButton]; }; - (void)didReceiveMemoryWarning { @@ -56,6 +70,21 @@ - (void)imagesToMovieButtonEvent:(id)sender { [self presentViewController:photoAlbumViewController animated:YES completion:nil]; } +// 切割视频 +- (void)cutMediaButtonEvent:(id)sender { + MulitPhotoAlbumViewController *mulitPhotoAlbumViewController = [[MulitPhotoAlbumViewController alloc] init]; + mulitPhotoAlbumViewController.mediaType = PHAssetMediaTypeVideo; + mulitPhotoAlbumViewController.maxSelectCount = 10; + [self presentViewController:mulitPhotoAlbumViewController animated:YES completion:nil]; +} + +// 导入H.265视频 +- (void)importH265VideoButtonEvent:(id)sender { + H265MovieViewController *h265MovieViewController = [[H265MovieViewController alloc] init]; + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:h265MovieViewController]; + [self presentViewController:navigationController animated:YES completion:nil]; +} + - (void)dealloc { NSLog(@"dealloc: %@", [[self class] description]); } diff --git a/Example/PLShortVideoKitDemo/test_videos/h265_video/Tears_400_h265-hev1.mp4 b/Example/PLShortVideoKitDemo/test_videos/h265_video/Tears_400_h265-hev1.mp4 new file mode 100644 index 00000000..71edb79b Binary files /dev/null and b/Example/PLShortVideoKitDemo/test_videos/h265_video/Tears_400_h265-hev1.mp4 differ diff --git a/Example/PLShortVideoKitDemo/test_videos/h265_video/Tears_400_h265.mp4 b/Example/PLShortVideoKitDemo/test_videos/h265_video/Tears_400_h265.mp4 new file mode 100644 index 00000000..f8cbbdea Binary files /dev/null and b/Example/PLShortVideoKitDemo/test_videos/h265_video/Tears_400_h265.mp4 differ diff --git a/Example/PLShortVideoKitDemo/test_videos/h265_video/Tractor_500kbps_h265.mp4 b/Example/PLShortVideoKitDemo/test_videos/h265_video/Tractor_500kbps_h265.mp4 new file mode 100644 index 00000000..b87a879a Binary files /dev/null and b/Example/PLShortVideoKitDemo/test_videos/h265_video/Tractor_500kbps_h265.mp4 differ diff --git a/Example/PLShortVideoKitDemo/videos/video_draft_test.mp4 b/Example/PLShortVideoKitDemo/test_videos/video_draft_test.mp4 similarity index 100% rename from Example/PLShortVideoKitDemo/videos/video_draft_test.mp4 rename to Example/PLShortVideoKitDemo/test_videos/video_draft_test.mp4 diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 51529d4a..6399ec61 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -4,13 +4,13 @@ PODS: - Fabric (1.6.11) - HappyDNS (0.3.12) - Masonry (1.0.2) - - PLShortVideoKit (1.9.0): - - PLShortVideoKit/ex-libMuseProcessor (= 1.9.0) - - PLShortVideoKit/libMuseProcessor (= 1.9.0) + - PLShortVideoKit (1.10.0): + - PLShortVideoKit/ex-libMuseProcessor (= 1.10.0) + - PLShortVideoKit/libMuseProcessor (= 1.10.0) - Qiniu (~> 7.1) - - PLShortVideoKit/ex-libMuseProcessor (1.9.0): + - PLShortVideoKit/ex-libMuseProcessor (1.10.0): - Qiniu (~> 7.1) - - PLShortVideoKit/libMuseProcessor (1.9.0): + - PLShortVideoKit/libMuseProcessor (1.10.0): - Qiniu (~> 7.1) - Qiniu (7.2.3): - HappyDNS (~> 0.3) @@ -30,9 +30,9 @@ SPEC CHECKSUMS: Fabric: 5911403591946b8228ab1c51d98f1d7137e863c6 HappyDNS: 691a3041128055d09866f86e6e9ca90f24da1f18 Masonry: 7c429b56da9d4ee0bbb3ed77a5ea710d6a5df39e - PLShortVideoKit: 5b34033567a6717d3542a80e27657a42f733f9b7 + PLShortVideoKit: 19ee6def3ce596436f4fea1556ecbde4f044539a Qiniu: ae0fea1cc379fae1560d8748ac537e0fbeb8626e PODFILE CHECKSUM: 613fdf88dc45f2e01aa56061a7239bd27687cd50 -COCOAPODS: 1.4.0.rc.1 +COCOAPODS: 1.4.0 diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSFadeTranstion.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSFadeTranstion.h new file mode 120000 index 00000000..4ccfe97d --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSFadeTranstion.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSFadeTranstion.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSImageSetting.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSImageSetting.h new file mode 120000 index 00000000..5f3b0a9c --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSImageSetting.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSImageSetting.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSPositionTransition.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSPositionTransition.h new file mode 120000 index 00000000..d939aba0 --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSPositionTransition.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSPositionTransition.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMedia.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMedia.h new file mode 120000 index 00000000..8dc03581 --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMedia.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMedia.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMediaTools.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMediaTools.h new file mode 120000 index 00000000..79b82c42 --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMediaTools.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMediaTools.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMovieExport.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMovieExport.h new file mode 120000 index 00000000..1275f06d --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRangeMovieExport.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMovieExport.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRotateTransition.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRotateTransition.h new file mode 120000 index 00000000..f17116e3 --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSRotateTransition.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSRotateTransition.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSScaleTransition.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSScaleTransition.h new file mode 120000 index 00000000..c18ada24 --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSScaleTransition.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSScaleTransition.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTextSetting.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTextSetting.h new file mode 120000 index 00000000..a6227904 --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTextSetting.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSTextSetting.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTransition.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTransition.h new file mode 120000 index 00000000..28f33069 --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTransition.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSTransition.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTransitionMaker.h b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTransitionMaker.h new file mode 120000 index 00000000..c9e83cca --- /dev/null +++ b/Example/Pods/Headers/Public/PLShortVideoKit/PLShortVideoKit/PLSTransitionMaker.h @@ -0,0 +1 @@ +../../../../../../Pod/Library/PLShortVideoKit.framework/Headers/PLSTransitionMaker.h \ No newline at end of file diff --git a/Example/Pods/Local Podspecs/PLShortVideoKit.podspec.json b/Example/Pods/Local Podspecs/PLShortVideoKit.podspec.json index 05cf85f0..6b79f710 100644 --- a/Example/Pods/Local Podspecs/PLShortVideoKit.podspec.json +++ b/Example/Pods/Local Podspecs/PLShortVideoKit.podspec.json @@ -1,6 +1,6 @@ { "name": "PLShortVideoKit", - "version": "1.9.0", + "version": "1.10.0", "summary": "PILI iOS short video record SDK", "homepage": "https://github.com/pili-engineering/PLShortVideoKit", "license": "Apache License 2.0", @@ -9,7 +9,7 @@ }, "source": { "git": "https://github.com/pili-engineering/PLShortVideoKit.git", - "tag": "v1.9.0" + "tag": "v1.10.0" }, "platforms": { "ios": "8.0" diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index 51529d4a..6399ec61 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -4,13 +4,13 @@ PODS: - Fabric (1.6.11) - HappyDNS (0.3.12) - Masonry (1.0.2) - - PLShortVideoKit (1.9.0): - - PLShortVideoKit/ex-libMuseProcessor (= 1.9.0) - - PLShortVideoKit/libMuseProcessor (= 1.9.0) + - PLShortVideoKit (1.10.0): + - PLShortVideoKit/ex-libMuseProcessor (= 1.10.0) + - PLShortVideoKit/libMuseProcessor (= 1.10.0) - Qiniu (~> 7.1) - - PLShortVideoKit/ex-libMuseProcessor (1.9.0): + - PLShortVideoKit/ex-libMuseProcessor (1.10.0): - Qiniu (~> 7.1) - - PLShortVideoKit/libMuseProcessor (1.9.0): + - PLShortVideoKit/libMuseProcessor (1.10.0): - Qiniu (~> 7.1) - Qiniu (7.2.3): - HappyDNS (~> 0.3) @@ -30,9 +30,9 @@ SPEC CHECKSUMS: Fabric: 5911403591946b8228ab1c51d98f1d7137e863c6 HappyDNS: 691a3041128055d09866f86e6e9ca90f24da1f18 Masonry: 7c429b56da9d4ee0bbb3ed77a5ea710d6a5df39e - PLShortVideoKit: 5b34033567a6717d3542a80e27657a42f733f9b7 + PLShortVideoKit: 19ee6def3ce596436f4fea1556ecbde4f044539a Qiniu: ae0fea1cc379fae1560d8748ac537e0fbeb8626e PODFILE CHECKSUM: 613fdf88dc45f2e01aa56061a7239bd27687cd50 -COCOAPODS: 1.4.0.rc.1 +COCOAPODS: 1.4.0 diff --git a/PLShortVideoKit.podspec b/PLShortVideoKit.podspec index 53b6caaf..55c08177 100644 --- a/PLShortVideoKit.podspec +++ b/PLShortVideoKit.podspec @@ -9,7 +9,7 @@ Pod::Spec.new do |s| s.name = "PLShortVideoKit" - s.version = "1.9.0" + s.version = "1.10.0" s.summary = "PILI iOS short video record SDK" s.homepage = "https://github.com/pili-engineering/PLShortVideoKit" s.license = "Apache License 2.0" diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSFadeTranstion.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSFadeTranstion.h new file mode 100644 index 00000000..b1ff6a6a --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSFadeTranstion.h @@ -0,0 +1,27 @@ +// +// PLSFadeTranstion.h +// PLShortVideoKit +// +// Created by hxiongan on 2018/1/17. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "PLSTransition.h" + +@interface PLSFadeTranstion : PLSTransition + +/** + @brief 起始透明度 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat fromOpacity; + +/** + @brief 结束透明度 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat toOpacity; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSImageSetting.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSImageSetting.h new file mode 100644 index 00000000..7cfffe25 --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSImageSetting.h @@ -0,0 +1,41 @@ +// +// PLSImageSetting.h +// PLShortVideoKit +// +// Created by hxiongan on 2018/1/17. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +@interface PLSImageSetting : NSObject + +/** + @brief 图片实例 + + @since v1.10.0 + */ +@property (nonatomic, strong) UIImage *image; + +/** + @brief 图片所占区域大小 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGSize imageSize; + +/** + @brief 图片所占区域的起始x位置,相对于PLSVideoSetting中设置的width的偏移像素 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat startX; + +/** + @brief 图片所占区域的起始Y位置,相对于PLSVideoSetting中设置的height的偏移像素 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat startY; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSPositionTransition.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSPositionTransition.h new file mode 100644 index 00000000..046319c3 --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSPositionTransition.h @@ -0,0 +1,27 @@ +// +// PLSPositionTransition.h +// PLShortVideoKit +// +// Created by hxiongan on 2018/1/17. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "PLSTransition.h" + +@interface PLSPositionTransition : PLSTransition + +/** + @brief 起始位置,相对于PLSVideoSetting中设置的width、height的偏移像素 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGPoint fromPoint; + +/** + @brief 结束位置, 相对于PLSVideoSetting中设置的width、height的偏移像素 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGPoint toPoint; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMedia.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMedia.h new file mode 100644 index 00000000..48d20fda --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMedia.h @@ -0,0 +1,49 @@ +// +// PLSRangeMedia.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/2. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import +#import + +@interface PLSRangeMedia : NSObject + +/** + @brief 选取的开始时间 + + @since v1.10.0 + */ +@property (nonatomic, assign) CMTime startTime; + +/** + @brief 选取的结束时间 + + @since v1.10.0 + */ +@property (nonatomic, assign) CMTime endTime; + +/** + @brief 视频可以是AVAseet格式,也可以用url,二选一 + + @since v1.10.0 + */ +@property (nonatomic, strong) AVAsset *asset; + +/** + @brief 视频的url,也可以用AVAsset,二选一 + + @since v1.10.0 + */ +@property (nonatomic, strong) NSURL *url; + +/** + @brief 是不是转场视频 + + @since v1.10.0 + */ +@property (nonatomic, assign) BOOL isTransition; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMediaTools.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMediaTools.h new file mode 100644 index 00000000..1faf762e --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMediaTools.h @@ -0,0 +1,24 @@ +// +// PLSRangeMediaTools.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/23. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import +#import + +@class PLSRangeMedia; + + +@interface PLSRangeMediaTools : NSObject + +/** + @abstract 根据PLSRangeMedia的选段信息,生成一个AVPlayerItem,将多段视频整个在一个AVPlayerItem中。 + + @since v1.10.0 + */ ++ (AVPlayerItem *)playerItemWithRangeMedia:(NSArray *)rangeMedias; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMovieExport.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMovieExport.h new file mode 100644 index 00000000..66110097 --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSRangeMovieExport.h @@ -0,0 +1,64 @@ +// +// PLSRangeMovieExport.h +// PLShortVideoKitDemo +// +// Created by hxiongan on 2018/2/23. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +@class PLSRangeMedia; +@interface PLSRangeMovieExport : NSObject + +/** + @brief 视频存放url + + @since v1.10.0 + */ +@property (nonatomic, strong) NSURL *outURL; + + +/** + @abstract 视频合并完成的 block + + @since v1.10.0 + */ +@property (copy, nonatomic) void(^completionBlock)(NSURL *url); + +/** + @abstract 视频合并失败的 block + + @since v1.10.0 + */ +@property (copy, nonatomic) void(^failureBlock)(NSError* error); + +/** + @abstract 视频合并进度的 block,可在该 block 中刷新进度条 UI + + @since v1.10.0 + */ +@property (copy, nonatomic) void(^processingBlock)(float progress); + +/** + @brief 初始化 + + @since v1.10.0 + */ +- (instancetype)initWithRangeMedia:(NSArray *)medias; + +/** + @brief 执行视频合并 + + @since v1.10.0 + */ +- (void)startExport; + +/** + @brief 停止视频合并 + + @since v1.10.0 + */ +- (void)stopExport; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSRotateTransition.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSRotateTransition.h new file mode 100644 index 00000000..3cbe56bb --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSRotateTransition.h @@ -0,0 +1,28 @@ +// +// PLSRotateTransition.h +// PLShortVideoKit +// +// Created by hxiongan on 2018/1/17. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "PLSTransition.h" + +@interface PLSRotateTransition : PLSTransition + +/** + @brief 旋转起始角度(-2*M_PI ~ 2*M_PI) + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat fromAngle; + + +/** + @brief 旋转结束角度(-2*M_PI ~ 2*M_PI) + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat toAngle; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSScaleTransition.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSScaleTransition.h new file mode 100644 index 00000000..fbffa408 --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSScaleTransition.h @@ -0,0 +1,29 @@ +// +// PLSScaleTransition.h +// PLShortVideoKit +// +// Created by hxiongan on 2018/1/17. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "PLSTransition.h" + +@interface PLSScaleTransition : PLSTransition + +/** + @brief 放大或者缩小的起始值 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat fromScale; + +/** + @brief 放大或者缩小的结束值 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat toScale; + + + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSTextSetting.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSTextSetting.h new file mode 100644 index 00000000..ad599838 --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSTextSetting.h @@ -0,0 +1,55 @@ +// +// PLSTextSetting.h +// PLShortVideoKit +// +// Created by hxiongan on 2018/1/17. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +@interface PLSTextSetting : NSObject + +/** + @brief 内容 + + @since v1.10.0 + */ +@property (nonatomic, copy) NSString *text; + +/** + @brief 文字字体 + + @since v1.10.0 + */ +@property (nonatomic, strong) UIFont *textFont; + +/** + @brief 文字颜色 + + @since v1.10.0 + */ +@property (nonatomic, strong) UIColor *textColor; + +/** + @brief 内容所占区域大小 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGSize textSize; + +/** + @brief 文字所占区域的起始x位置,相对于PLSVideoSetting中设置的width的偏移像素 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat startX; + +/** + @brief 文字所占区域的起始Y位置,相对于PLSVideoSetting中设置的height的偏移像素 + + @since v1.10.0 + */ +@property (nonatomic, assign) CGFloat startY; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSTransition.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSTransition.h new file mode 100644 index 00000000..e9b53eee --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSTransition.h @@ -0,0 +1,37 @@ +// +// PLSTransition.h +// PLShortVideoKit +// +// Created by hxiongan on 2018/1/17. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +@interface PLSTransition : NSObject + +/** + @brief 动画时长,毫秒 + + @since v1.10.0 + */ +@property (nonatomic, assign) double durationInMs; + +/** + @brief 动画开始时间,毫秒 + + @since v1.10.0 + */ +@property (nonatomic, assign) double startTimeInMs; + +/** + @abstract 根据配置的参数,返回一个CAAnimation对象,预览view的尺寸和导出视频的尺寸不一样的时候,为了能让预览效果达到和导出视频一样效果,需要对动画的位置等做比例缩放 + @param scale 如果CAAnimation用于预览,sacel = 预览view的width / 导出视频的width + 如果CAAnimation用于生产最终视频,scale = 背景视频的width / 导出视频的width + + @since v1.10.0 + */ +- (CAAnimation *)animationWithScale:(CGFloat)scale; + + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSTransitionMaker.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSTransitionMaker.h new file mode 100644 index 00000000..e5d269e6 --- /dev/null +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSTransitionMaker.h @@ -0,0 +1,195 @@ +// +// PLSTransitionMaker.h +// PLShortVideoKit +// +// Created by hxiongan on 2018/1/17. +// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import +#import "PLSImageSetting.h" +#import "PLSTextSetting.h" +#import "PLSTransition.h" + +#define INVALID_RESOURCEID (0) + +@class PLSTransitionMaker; +@protocol PLSTransitionMakerDelegate +< +NSObject +> +@optional + +/** + @abstract 预览结束会回调 + + @since v1.10.0 + */ +- (void)transitionMakerPreviewEnd:(PLSTransitionMaker *)transitionMaker; + +/** + @abstract 文字转视频成功回调, + @param outURL 存放导出视频的url + + @since v1.10.0 + */ +- (void)transitionMaker:(PLSTransitionMaker *)transitionMaker exportMediaSucceed:(NSURL *)outURL; + +/** + @abstract 文字转视频失败回调 + @param error 导出视频错误信息 + + @since v1.10.0 + */ +- (void)transitionMaker:(PLSTransitionMaker *)transitionMaker exportMediaFailed:(NSError *)error; + +@end + + + +@interface PLSTransitionMaker : NSObject + +/** + @brief 生成视频的宽高,建议和背景视频宽高比例保持一致. must set + + @since v1.10.0 + */ +@property (nonatomic, assign) CGSize outPixelSize; + +/** + @brief 生成视频的帧率,= 0时,将使用背景视频的frameRate + + @since v1.10.0 + */ +@property (nonatomic, assign) float outFrameRate; + +/** + @brief 生成视频底色, default: nil + + @since v1.10.0 + */ +@property (nonatomic, strong) UIColor *backgroundColor; + +/** + @brief 视频总时长, default: 2.5s + + @since v1.10.0 + */ +@property (nonatomic, assign) double totalDuration; + +/** + @brief 代理 + + @since v1.10.0 + */ +@property (nonatomic, weak) id delegate; + +/** + @brief 生成视频进度 block 回调 + + @since v1.10.0 + */ +@property (copy, nonatomic) void(^exportProgressBlock)(CGFloat progress); + +/** + @brief 预览view + + @since v1.10.0 + */ +@property (nonatomic, readonly) UIView *preview; + +/** + @brief 背景视频的URL(提供一个纯白或纯黑的视频作为文字的背景) + + @since v1.10.0 + */ +@property (nonatomic, strong) NSURL *backgroundVideoURL; + +/** + @brief 最终生成的视频的存放URL + + @since v1.10.0 + */ +@property (nonatomic, strong) NSURL *outputVideoURL; + +/** + @abstract 添加PLSTextSetting + @param textSetting 要添加的实例 + + @return 返回唯一的resourceID编号,后面更新此textSetting的时候,带上返回的编号 + @since v1.10.0 + */ +- (NSInteger)addText:(PLSTextSetting *)textSetting; + +/** + @abstract 添加PLSImageSetting + @param imageSetting 要添加的实例 + + @return 返回唯一的resourceID编号,后面更新此imageSetting的时候,带上返回的编号 + @since v1.10.0 + */ +- (NSInteger)addImage:(PLSImageSetting *)imageSetting; + +/** + @abstract 添加PLSTransition到知道资源 + @param transition 要添加的动画 + @param resourceID 动画作用的资源编号 + + @since v1.10.0 + */ +- (void)addTransition:(PLSTransition *)transition resourceID:(NSInteger)resourceID; + +/** + @abstract 更新textsetting + @param resourceID 更新的PLSTextSetting编号 + @param textSetting 新的PLSTextSetting实例,如果为nil,则执行删除resourceID操作 + + @since v1.10.0 + */ +- (void)updateTextWithResourceID:(NSInteger)resourceID newTextSetting:(PLSTextSetting *)textSetting; + +/** + @abstract 更新imageSetting + @param resourceID 更新的PLSImageSetting编号 + @param imageSetting 新的PLSImageSetting实例,如果为nil,则执行删除resourceID操作 + + @since v1.10.0 + */ +- (void)updateImageWithResourceID:(NSInteger)resourceID newImageSetting:(PLSImageSetting *)imageSetting; + +/** + @abstract 删除所有文字和图片 + + @since v1.10.0 + */ +- (void)removeAllResource; + +/** + @abstract 播放 + + @since v1.10.0 + */ +- (void)play; + +/** + @abstract 停止播放 + + @since v1.10.0 + */ +- (void)stop; + +/** + @abstract 开始制作视频 + + @since v1.10.0 + */ +- (void)startMaking; + +/** + @abstract 取消视频制作 + + @since v1.10.0 + */ +- (void)cancelMaking; + +@end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLSUploaderConfiguration.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLSUploaderConfiguration.h index c4fbf1ff..d04b80b7 100644 --- a/Pod/Library/PLShortVideoKit.framework/Headers/PLSUploaderConfiguration.h +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLSUploaderConfiguration.h @@ -42,6 +42,13 @@ */ @property (nonatomic, strong)NSString * _Nullable recorder; +/** + @brief 上传视频空间设置的 key,默认为当前上传视频文件的 hash 值 + + @since v1.0.4 + */ +@property (nonatomic, strong)NSDictionary * _Nullable params; + /** @abstract PLSUploaderConfiguration 初始化方法 @warning token 必填,不能为空 @@ -60,4 +67,16 @@ */ + (instancetype _Nullable)defaultWithToken:(NSString * _Nonnull)token; +/** + @abstract PLSUploaderConfiguration 初始化方法 + @warning token 必填,不能为空 + + @since v1.0.4 + */ +- (instancetype _Nullable)initWithToken:(NSString * _Nonnull)token + videoKey:(NSString * _Nullable)videoKey + https:(BOOL)https + recorder:(NSString * _Nullable)recorder + params:(NSDictionary * _Nullable)params; + @end diff --git a/Pod/Library/PLShortVideoKit.framework/Headers/PLShortVideoKit.h b/Pod/Library/PLShortVideoKit.framework/Headers/PLShortVideoKit.h index e6fdaa01..6ac424c2 100644 --- a/Pod/Library/PLShortVideoKit.framework/Headers/PLShortVideoKit.h +++ b/Pod/Library/PLShortVideoKit.framework/Headers/PLShortVideoKit.h @@ -43,5 +43,14 @@ FOUNDATION_EXPORT const unsigned char PLShortVideoKitVersionString[]; #import #import - - +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import diff --git a/Pod/Library/PLShortVideoKit.framework/Info.plist b/Pod/Library/PLShortVideoKit.framework/Info.plist index 60747fcc..d1bc4d87 100644 Binary files a/Pod/Library/PLShortVideoKit.framework/Info.plist and b/Pod/Library/PLShortVideoKit.framework/Info.plist differ diff --git a/Pod/Library/PLShortVideoKit.framework/PLShortVideoKit b/Pod/Library/PLShortVideoKit.framework/PLShortVideoKit index 001ff5df..a5cd280a 100644 Binary files a/Pod/Library/PLShortVideoKit.framework/PLShortVideoKit and b/Pod/Library/PLShortVideoKit.framework/PLShortVideoKit differ diff --git a/README.md b/README.md index 7b49b6f2..ad188e43 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ PLShortVideoKit 是七牛推出的一款适用于 iOS 平台的短视频 SDK, | 关键帧预览 | 1.0.2(+) | | 剪辑指定区间 | 1.0.2(+) | | 截取封面 | 1.0.2(+) | +| 视频分割 | 1.10.0(+) | ### 1.2.2 视频特效 | 功能点 | 版本 | 备注 | @@ -93,6 +94,11 @@ PLShortVideoKit 是七牛推出的一款适用于 iOS 平台的短视频 SDK, | 画面剪裁 | 1.1.0(+) | | 码率变换 | 1.1.0(+) | +### 1.2.6 文字动画生成视频文件 +| 功能点 | 版本 | +| ------------------ | -------- | +| 文字动画生成视频文件 | 1.10.0(+) | + ## 1.3 视频上传 | 功能点 | 版本 | | ---- | -------- | diff --git a/ReleaseNotes/release-notes-1.10.0.md b/ReleaseNotes/release-notes-1.10.0.md new file mode 100644 index 00000000..9ed9d16a --- /dev/null +++ b/ReleaseNotes/release-notes-1.10.0.md @@ -0,0 +1,24 @@ +# PLShortVideoKit Release Notes for 1.10.0 + +### 简介 +PLShortVideoKit 是七牛推出的一款适用于 iOS 平台的短视频 SDK,提供了包括美颜、滤镜、水印、断点录制、分段回删、视频编辑、混音特效、MV 特效、本地/云端存储在内的多种功能,支持高度定制以及二次开发。 + +### 版本 +- 发布 PLShortVideoKit.framework + +### 功能 +- 支持文字动画转换为视频文件 +- 支持多个视频同时进行切割编辑 +- 对能直接 H.265 硬解码的机型支持导入 H.265 格式视频文件进行转码 +- 支持在视频任意位置插入文字转场视频编辑 +- 支持 PLSUploaderConfiguration 上传 params 设置 +- 支持倍速录制视频时以对应的倍速播放背景音乐 +- 优化 PLSEditPlayer 在暂停的时候 seek 时预览画面刷新逻辑 +- 修复录制时播放背景音乐,并在录制结束后再次合成背景音乐导致有两重背景音乐声音的问题 +- 修复多张图片合成视频时设置图片持续时间导致的最后一张图片没有被合入视频的问题 +- 更新人脸贴纸库解决了使用人脸贴纸库后反复进出录制页面导致的崩溃问题 + +### 注意事项 +- 若需要使用 PLShortVideoKit.framework 中的内置滤镜,则必须将 PLShortVideoKit.bundle 导入项目中。若需要增删、替换滤镜资源可操作 PLShortVideoKit.bundle 中的 colorFilter 文件夹。 +- 抖音特效,需要联系七牛商务获取 appkey 和资源文件。具体使用可参看 PLShortVideoKitDemo。 +