diff --git a/APIDiffs/api-diffs-3.0.0.md b/APIDiffs/api-diffs-3.0.0.md new file mode 100644 index 00000000..acc1a558 --- /dev/null +++ b/APIDiffs/api-diffs-3.0.0.md @@ -0,0 +1,4 @@ +# PLShortVideoKit 2.2.0 to 3.0.0 API Differences + +## General Headers + diff --git a/Example/PLShortVideoKitDemo.xcodeproj/project.pbxproj b/Example/PLShortVideoKitDemo.xcodeproj/project.pbxproj index 0fe0f972..a21fd37c 100644 --- a/Example/PLShortVideoKitDemo.xcodeproj/project.pbxproj +++ b/Example/PLShortVideoKitDemo.xcodeproj/project.pbxproj @@ -52,7 +52,6 @@ 0A24C5ED1EE951B900B2314E /* movie.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A24C5EC1EE951B900B2314E /* movie.png */; }; 0A26041B1FA80BC900609411 /* DubViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A26041A1FA80BC900609411 /* DubViewController.m */; }; 0A2604411FA8498B00609411 /* icon_dub.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2604401FA8498A00609411 /* icon_dub.png */; }; - 0A26A75A1FE392F9003B9691 /* file_path.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A26A7591FE392F9003B9691 /* file_path.png */; }; 0A2731EE1E75D2B0005D0CE1 /* end_disable.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2731ED1E75D2B0005D0CE1 /* end_disable.png */; }; 0A2731FF1E75E36B005D0CE1 /* progressbar_front.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2731FE1E75E36B005D0CE1 /* progressbar_front.png */; }; 0A2732311E75F99D005D0CE1 /* btn_play_bg_a.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A2732301E75F99D005D0CE1 /* btn_play_bg_a.png */; }; @@ -70,7 +69,6 @@ 0A398F9F1ED6698F00996229 /* cut_bar_progress@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A398F9C1ED6698F00996229 /* cut_bar_progress@2x.png */; }; 0A398FA01ED6698F00996229 /* cut_bar_progress@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A398F9D1ED6698F00996229 /* cut_bar_progress@3x.png */; }; 0A3CCE791FA91CC8003D766A /* dubber_stop.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A3CCE771FA91CC8003D766A /* dubber_stop.png */; }; - 0A3CCE7A1FA91CC8003D766A /* dubber_start.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A3CCE781FA91CC8003D766A /* dubber_start.png */; }; 0A41CD8920BD502900315902 /* PLSTimeLineItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A41CD8820BD502900315902 /* PLSTimeLineItem.m */; }; 0A41CD8C20BD517000315902 /* PLSTimeLineAudioItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A41CD8B20BD517000315902 /* PLSTimeLineAudioItem.m */; }; 0A4F78FC20072B80003E8218 /* btn_play_bg_a@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A4F78F920072B80003E8218 /* btn_play_bg_a@3x.png */; }; @@ -93,11 +91,7 @@ 0A94358F1E6CA2E2008845A3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0A94358D1E6CA2E2008845A3 /* LaunchScreen.storyboard */; }; 0A94DFCE1E6DF5D2007BDD0D /* end_normal.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A94DFC61E6DF5D2007BDD0D /* end_normal.png */; }; 0A94DFCF1E6DF5D2007BDD0D /* delete.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A94DFC71E6DF5D2007BDD0D /* delete.png */; }; - 0A94DFD01E6DF5D2007BDD0D /* flash_close.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A94DFC81E6DF5D2007BDD0D /* flash_close.png */; }; - 0A94DFD11E6DF5D2007BDD0D /* flash_open.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A94DFC91E6DF5D2007BDD0D /* flash_open.png */; }; 0A94DFD31E6DF5D2007BDD0D /* toggle_camera.png in Resources */ = {isa = PBXBuildFile; fileRef = 0A94DFCB1E6DF5D2007BDD0D /* toggle_camera.png */; }; - 0A9B8A7920B6822800E7C8D7 /* PLSStickerOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9B8A6920B6822800E7C8D7 /* PLSStickerOverlayView.m */; }; - 0A9B8A7A20B6822800E7C8D7 /* PLSStickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9B8A6A20B6822800E7C8D7 /* PLSStickerView.m */; }; 0A9B8A7B20B6822800E7C8D7 /* PLSTimelineMediaInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9B8A6C20B6822800E7C8D7 /* PLSTimelineMediaInfo.m */; }; 0A9B8A7C20B6822800E7C8D7 /* PLSTimelineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9B8A6D20B6822800E7C8D7 /* PLSTimelineView.m */; }; 0A9B8A7D20B6822800E7C8D7 /* PLSAssetImageGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A9B8A6F20B6822800E7C8D7 /* PLSAssetImageGenerator.m */; }; @@ -124,7 +118,6 @@ 0ACE7C391ED8B072002FF4C9 /* PLSProgressBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ACE7C321ED8B072002FF4C9 /* PLSProgressBar.m */; }; 0ACE7C3A1ED8B072002FF4C9 /* UIImage+PLSClip.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ACE7C341ED8B072002FF4C9 /* UIImage+PLSClip.m */; }; 0AD7279D20BF249C00662588 /* 胜利小旋律音效.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 0AD7279C20BF249C00662588 /* 胜利小旋律音效.m4r */; }; - 0AD7D3151EA329A400144411 /* btn_record_a.png in Resources */ = {isa = PBXBuildFile; fileRef = 0AD7D3141EA329A400144411 /* btn_record_a.png */; }; 0AD98DBE20316E33006551EC /* video_draft_test.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 0AD98DBD20316E33006551EC /* video_draft_test.mp4 */; }; 0AD98DC4203173F5006551EC /* H265MovieViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AD98DC3203173F5006551EC /* H265MovieViewController.m */; }; 0AD98DC6203188CE006551EC /* h265_video in Resources */ = {isa = PBXBuildFile; fileRef = 0AD98DC5203188CE006551EC /* h265_video */; }; @@ -170,9 +163,8 @@ 760F7706202AF92A0052F513 /* BaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 760F76FA202AF92A0052F513 /* BaseViewController.m */; }; 760F7707202AF92A0052F513 /* PLSPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 760F76FB202AF92A0052F513 /* PLSPlayerView.m */; }; 760F7709202AF92A0052F513 /* PLSClipMulitMediaView.m in Sources */ = {isa = PBXBuildFile; fileRef = 760F76FF202AF92A0052F513 /* PLSClipMulitMediaView.m */; }; - 7615EE5421835E3800F7D55D /* watermark.gif in Resources */ = {isa = PBXBuildFile; fileRef = 7615EE5321835E3800F7D55D /* watermark.gif */; }; - 76181FD721186ADE005F4F8B /* scope_image.png in Resources */ = {isa = PBXBuildFile; fileRef = 76181FD621186ADE005F4F8B /* scope_image.png */; }; 7623E9E020B5414600847998 /* ImageRotateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7623E9DF20B5414600847998 /* ImageRotateViewController.m */; }; + 762ECB80217730B000DFC18B /* watermark.gif in Resources */ = {isa = PBXBuildFile; fileRef = 762ECB7E217730B000DFC18B /* watermark.gif */; }; 7635E3E120CE494900E36027 /* 3video_template@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7635E3DB20CE494800E36027 /* 3video_template@3x.png */; }; 7635E3E220CE494900E36027 /* 2video_template@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7635E3DC20CE494800E36027 /* 2video_template@2x.png */; }; 7635E3E320CE494900E36027 /* 2video_template@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7635E3DD20CE494800E36027 /* 2video_template@3x.png */; }; @@ -186,7 +178,8 @@ 7635E40A20CE8F5900E36027 /* select_meterial@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7635E40420CE8F5900E36027 /* select_meterial@3x.png */; }; 7635E40B20CE8F5900E36027 /* select_shoot@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7635E40520CE8F5900E36027 /* select_shoot@2x.png */; }; 7636991A20871AC800626680 /* MixRecordViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7636991920871AC800626680 /* MixRecordViewController.m */; }; - 76564FCC210B2871004B62E9 /* VersionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76564FCB210B2871004B62E9 /* VersionViewController.m */; }; + 76425C9E210F48D000FB8200 /* scope_image.png in Resources */ = {isa = PBXBuildFile; fileRef = 76425C9C210F48D000FB8200 /* scope_image.png */; }; + 766423272100AF3F000F24A4 /* VersionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 766423262100AF3F000F24A4 /* VersionViewController.m */; }; 7678EE6E20C96E8300231AA8 /* VideoMixViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7678EE6D20C96E8300231AA8 /* VideoMixViewController.m */; }; 7697482C202835D2001AC847 /* TransitionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76974824202835D1001AC847 /* TransitionViewController.m */; }; 7697482D202835D2001AC847 /* TransitionModelSelectView.m in Sources */ = {isa = PBXBuildFile; fileRef = 76974826202835D1001AC847 /* TransitionModelSelectView.m */; }; @@ -197,24 +190,29 @@ 7697484720285747001AC847 /* green_quot.png in Resources */ = {isa = PBXBuildFile; fileRef = 7697484220285747001AC847 /* green_quot.png */; }; 7697484820285747001AC847 /* transition_black.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 7697484320285747001AC847 /* transition_black.mp4 */; }; 7697484920285747001AC847 /* pink_line.png in Resources */ = {isa = PBXBuildFile; fileRef = 7697484420285747001AC847 /* pink_line.png */; }; + 76B2FA01216C96C500DA9330 /* mulitRate.png in Resources */ = {isa = PBXBuildFile; fileRef = 76B2F9FF216C96C400DA9330 /* mulitRate.png */; }; 76DA9AC120CA31DB001D3002 /* MultiVideoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76DA9AC020CA31DB001D3002 /* MultiVideoViewController.m */; }; - 76F41C52219D77B40099E668 /* mulitRate.png in Resources */ = {isa = PBXBuildFile; fileRef = 76F41C51219D77B40099E668 /* mulitRate.png */; }; + 76ECAC5021880EFC00EA153E /* ImageVideoMixViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76ECAC4F21880EFC00EA153E /* ImageVideoMixViewController.m */; }; 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 */; }; - AA09EB2A22E8672C001BBA54 /* PLSDrawBar.m in Sources */ = {isa = PBXBuildFile; fileRef = AA09EB2922E8672C001BBA54 /* PLSDrawBar.m */; }; - AA09EB2F22E86856001BBA54 /* PLSDrawView.m in Sources */ = {isa = PBXBuildFile; fileRef = AA09EB2B22E86856001BBA54 /* PLSDrawView.m */; }; - AA09EB3022E86856001BBA54 /* PLSDrawModel.m in Sources */ = {isa = PBXBuildFile; fileRef = AA09EB2E22E86856001BBA54 /* PLSDrawModel.m */; }; - AA09EB3722E8787A001BBA54 /* qn_edit_delete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB3122E87879001BBA54 /* qn_edit_delete@2x.png */; }; - AA09EB3822E8787A001BBA54 /* qn_done@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB3222E8787A001BBA54 /* qn_done@2x.png */; }; - AA09EB3922E8787A001BBA54 /* qn_edit_delete@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB3322E8787A001BBA54 /* qn_edit_delete@3x.png */; }; - AA09EB3A22E8787A001BBA54 /* qn_revocation@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB3422E8787A001BBA54 /* qn_revocation@3x.png */; }; - AA09EB3B22E8787A001BBA54 /* qn_revocation@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB3522E8787A001BBA54 /* qn_revocation@2x.png */; }; - AA09EB3C22E8787A001BBA54 /* qn_done@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB3622E8787A001BBA54 /* qn_done@3x.png */; }; - BC695AF1228A8FFF005240A7 /* PLSGifStickerBar.m in Sources */ = {isa = PBXBuildFile; fileRef = BC695AF0228A8FFF005240A7 /* PLSGifStickerBar.m */; }; - BC695AF3228A9008005240A7 /* gifSticker.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BC695AF2228A9008005240A7 /* gifSticker.bundle */; }; - BC8DD6BA224E320200E05B26 /* PLScreenRecorderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BC8DD6B9224E320200E05B26 /* PLScreenRecorderManager.m */; }; - BCCF75E121C3884500BF9BA2 /* ImageVideoMixViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCCF75DF21C3884500BF9BA2 /* ImageVideoMixViewController.m */; }; - C35043641FB3152600F9633D /* draft_video.png in Resources */ = {isa = PBXBuildFile; fileRef = C35043631FB3121E00F9633D /* draft_video.png */; }; + AA09EB0322E7F71E001BBA54 /* PLSDrawView.m in Sources */ = {isa = PBXBuildFile; fileRef = AA09EB0222E7F71E001BBA54 /* PLSDrawView.m */; }; + AA09EB0D22E7FD2F001BBA54 /* PLSDrawBar.m in Sources */ = {isa = PBXBuildFile; fileRef = AA09EB0C22E7FD2F001BBA54 /* PLSDrawBar.m */; }; + AA09EB1022E80583001BBA54 /* PLSDrawModel.m in Sources */ = {isa = PBXBuildFile; fileRef = AA09EB0F22E80583001BBA54 /* PLSDrawModel.m */; }; + AA09EB1322E83C22001BBA54 /* qn_done@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB1122E83C22001BBA54 /* qn_done@2x.png */; }; + AA09EB1422E83C22001BBA54 /* qn_done@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB1222E83C22001BBA54 /* qn_done@3x.png */; }; + AA09EB1722E83C3C001BBA54 /* qn_edit_delete@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB1522E83C3C001BBA54 /* qn_edit_delete@3x.png */; }; + AA09EB1822E83C3C001BBA54 /* qn_edit_delete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB1622E83C3C001BBA54 /* qn_edit_delete@2x.png */; }; + AA09EB1B22E83C62001BBA54 /* qn_revocation@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB1922E83C62001BBA54 /* qn_revocation@2x.png */; }; + AA09EB1C22E83C62001BBA54 /* qn_revocation@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA09EB1A22E83C62001BBA54 /* qn_revocation@3x.png */; }; + AA1F816E2330B85000AFC7A8 /* PLSListFunctionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = AA1F816D2330B85000AFC7A8 /* PLSListFunctionTableViewCell.m */; }; + AA1F81712330C37800AFC7A8 /* MatterImportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA1F81702330C37800AFC7A8 /* MatterImportViewController.m */; }; + AA1F817F2332324200AFC7A8 /* MoiveClipViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA1F817E2332324200AFC7A8 /* MoiveClipViewController.m */; }; + AAAEB866230A480A00584B30 /* PLSStickerOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = AAAEB865230A480A00584B30 /* PLSStickerOverlayView.m */; }; + AAAEB87C230BFC8400584B30 /* PLSStickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = AAAEB87B230BFC8400584B30 /* PLSStickerView.m */; }; + BC281BF8225212C700CC7584 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC281BF0225212C700CC7584 /* ReplayKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + BC570E552254A4DB008FF508 /* PLSGifStickerBar.m in Sources */ = {isa = PBXBuildFile; fileRef = BC570E542254A4DB008FF508 /* PLSGifStickerBar.m */; }; + BC570E692255D55A008FF508 /* gifSticker.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BC570E682255D55A008FF508 /* gifSticker.bundle */; }; + BCAE1D88224C727100062455 /* PLScreenRecorderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BCAE1D87224C727100062455 /* PLScreenRecorderManager.m */; }; C35043971FBED6B900F9633D /* music_no_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = C35043941FBED11C00F9633D /* music_no_selected.png */; }; C35043981FBED6B900F9633D /* music_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = C35043961FBED11C00F9633D /* music_selected.png */; }; C39EA3D71F4E753D0007D1C3 /* PLSRateButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = C39EA3D61F4E753D0007D1C3 /* PLSRateButtonView.m */; }; @@ -234,7 +232,6 @@ C3A791401FA076E000C3F2D6 /* back_white.png in Resources */ = {isa = PBXBuildFile; fileRef = C3A7913F1FA076E000C3F2D6 /* back_white.png */; }; C3A791421FA076F300C3F2D6 /* scroll_image.png in Resources */ = {isa = PBXBuildFile; fileRef = C3A791411FA076F300C3F2D6 /* scroll_image.png */; }; C3A791441FA0772D00C3F2D6 /* scan_line.png in Resources */ = {isa = PBXBuildFile; fileRef = C3A791431FA0772D00C3F2D6 /* scan_line.png */; }; - C3A7916B1FA1D4ED00C3F2D6 /* easyar_AR.png in Resources */ = {isa = PBXBuildFile; fileRef = C3A7916A1FA1D4ED00C3F2D6 /* easyar_AR.png */; }; C3FCBFCB1F305B21007EBB10 /* GifFormatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C3FCBFCA1F305B21007EBB10 /* GifFormatViewController.m */; }; C3FCBFCF1F305B37007EBB10 /* PLSFormatGifView.m in Sources */ = {isa = PBXBuildFile; fileRef = C3FCBFCE1F305B37007EBB10 /* PLSFormatGifView.m */; }; C3FCBFD41F305B70007EBB10 /* btn_no_selected_pic@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C3FCBFD01F305B70007EBB10 /* btn_no_selected_pic@2x.png */; }; @@ -294,7 +291,6 @@ 0A2604181FA80BC900609411 /* DubViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DubViewController.h; sourceTree = ""; }; 0A26041A1FA80BC900609411 /* DubViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DubViewController.m; sourceTree = ""; }; 0A2604401FA8498A00609411 /* icon_dub.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon_dub.png; path = images/icon_dub.png; sourceTree = ""; }; - 0A26A7591FE392F9003B9691 /* file_path.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = file_path.png; path = images/file_path.png; sourceTree = ""; }; 0A2731ED1E75D2B0005D0CE1 /* end_disable.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = end_disable.png; path = images/end_disable.png; sourceTree = ""; }; 0A2731FE1E75E36B005D0CE1 /* progressbar_front.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = progressbar_front.png; path = images/progressbar_front.png; sourceTree = ""; }; 0A2732301E75F99D005D0CE1 /* btn_play_bg_a.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = btn_play_bg_a.png; path = images/btn_play_bg_a.png; sourceTree = ""; }; @@ -313,7 +309,6 @@ 0A398F9C1ED6698F00996229 /* cut_bar_progress@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "cut_bar_progress@2x.png"; path = "images/cut_bar_progress@2x.png"; sourceTree = ""; }; 0A398F9D1ED6698F00996229 /* cut_bar_progress@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "cut_bar_progress@3x.png"; path = "images/cut_bar_progress@3x.png"; sourceTree = ""; }; 0A3CCE771FA91CC8003D766A /* dubber_stop.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dubber_stop.png; path = images/dubber_stop.png; sourceTree = ""; }; - 0A3CCE781FA91CC8003D766A /* dubber_start.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dubber_start.png; path = images/dubber_start.png; sourceTree = ""; }; 0A41CD8720BD502900315902 /* PLSTimeLineItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLSTimeLineItem.h; sourceTree = ""; }; 0A41CD8820BD502900315902 /* PLSTimeLineItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PLSTimeLineItem.m; sourceTree = ""; }; 0A41CD8A20BD516F00315902 /* PLSTimeLineAudioItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSTimeLineAudioItem.h; sourceTree = ""; }; @@ -347,13 +342,7 @@ 0A9435901E6CA2E2008845A3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 0A94DFC61E6DF5D2007BDD0D /* end_normal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = end_normal.png; path = images/end_normal.png; sourceTree = ""; }; 0A94DFC71E6DF5D2007BDD0D /* delete.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = delete.png; path = images/delete.png; sourceTree = ""; }; - 0A94DFC81E6DF5D2007BDD0D /* flash_close.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = flash_close.png; path = images/flash_close.png; sourceTree = ""; }; - 0A94DFC91E6DF5D2007BDD0D /* flash_open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = flash_open.png; path = images/flash_open.png; sourceTree = ""; }; 0A94DFCB1E6DF5D2007BDD0D /* toggle_camera.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = toggle_camera.png; path = images/toggle_camera.png; sourceTree = ""; }; - 0A9B8A6720B6822800E7C8D7 /* PLSStickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSStickerView.h; sourceTree = ""; }; - 0A9B8A6820B6822800E7C8D7 /* PLSStickerOverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSStickerOverlayView.h; sourceTree = ""; }; - 0A9B8A6920B6822800E7C8D7 /* PLSStickerOverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSStickerOverlayView.m; sourceTree = ""; }; - 0A9B8A6A20B6822800E7C8D7 /* PLSStickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSStickerView.m; sourceTree = ""; }; 0A9B8A6C20B6822800E7C8D7 /* PLSTimelineMediaInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSTimelineMediaInfo.m; sourceTree = ""; }; 0A9B8A6D20B6822800E7C8D7 /* PLSTimelineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSTimelineView.m; sourceTree = ""; }; 0A9B8A6E20B6822800E7C8D7 /* PLSTimelineItemCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSTimelineItemCell.h; sourceTree = ""; }; @@ -392,7 +381,6 @@ 0ACE7C341ED8B072002FF4C9 /* UIImage+PLSClip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+PLSClip.m"; sourceTree = ""; }; 0AD526211EADE2EB00CE4B90 /* libMuseProcessor.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libMuseProcessor.a; sourceTree = ""; }; 0AD7279C20BF249C00662588 /* 胜利小旋律音效.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; name = "胜利小旋律音效.m4r"; path = "musics/胜利小旋律音效.m4r"; sourceTree = ""; }; - 0AD7D3141EA329A400144411 /* btn_record_a.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = btn_record_a.png; path = images/btn_record_a.png; sourceTree = ""; }; 0AD98DBD20316E33006551EC /* video_draft_test.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; name = video_draft_test.mp4; path = test_videos/video_draft_test.mp4; sourceTree = ""; }; 0AD98DC2203173F5006551EC /* H265MovieViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = H265MovieViewController.h; sourceTree = ""; }; 0AD98DC3203173F5006551EC /* H265MovieViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = H265MovieViewController.m; sourceTree = ""; }; @@ -451,10 +439,9 @@ 760F7700202AF92A0052F513 /* MulitPhotoAlbumViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MulitPhotoAlbumViewController.h; sourceTree = ""; }; 760F7701202AF92A0052F513 /* BaseViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseViewController.h; sourceTree = ""; }; 760F7702202AF92A0052F513 /* PLSPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSPlayerView.h; sourceTree = ""; }; - 7615EE5321835E3800F7D55D /* watermark.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = watermark.gif; sourceTree = ""; }; - 76181FD621186ADE005F4F8B /* scope_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = scope_image.png; sourceTree = ""; }; 7623E9DE20B5414600847998 /* ImageRotateViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageRotateViewController.h; sourceTree = ""; }; 7623E9DF20B5414600847998 /* ImageRotateViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImageRotateViewController.m; sourceTree = ""; }; + 762ECB7E217730B000DFC18B /* watermark.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = watermark.gif; sourceTree = ""; }; 7635E3DB20CE494800E36027 /* 3video_template@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "3video_template@3x.png"; path = "images/3video_template@3x.png"; sourceTree = ""; }; 7635E3DC20CE494800E36027 /* 2video_template@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "2video_template@2x.png"; path = "images/2video_template@2x.png"; sourceTree = ""; }; 7635E3DD20CE494800E36027 /* 2video_template@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "2video_template@3x.png"; path = "images/2video_template@3x.png"; sourceTree = ""; }; @@ -469,8 +456,9 @@ 7635E40520CE8F5900E36027 /* select_shoot@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "select_shoot@2x.png"; path = "images/select_shoot@2x.png"; sourceTree = ""; }; 7636991820871AC800626680 /* MixRecordViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MixRecordViewController.h; sourceTree = ""; }; 7636991920871AC800626680 /* MixRecordViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MixRecordViewController.m; sourceTree = ""; }; - 76564FCA210B2871004B62E9 /* VersionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionViewController.h; sourceTree = ""; }; - 76564FCB210B2871004B62E9 /* VersionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VersionViewController.m; sourceTree = ""; }; + 76425C9C210F48D000FB8200 /* scope_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = scope_image.png; sourceTree = ""; }; + 766423252100AF3F000F24A4 /* VersionViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VersionViewController.h; sourceTree = ""; }; + 766423262100AF3F000F24A4 /* VersionViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VersionViewController.m; sourceTree = ""; }; 7678EE6C20C96E8300231AA8 /* VideoMixViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VideoMixViewController.h; sourceTree = ""; }; 7678EE6D20C96E8300231AA8 /* VideoMixViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VideoMixViewController.m; sourceTree = ""; }; 76974824202835D1001AC847 /* TransitionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TransitionViewController.m; sourceTree = ""; }; @@ -487,32 +475,42 @@ 7697484320285747001AC847 /* transition_black.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = transition_black.mp4; sourceTree = ""; }; 7697484420285747001AC847 /* pink_line.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pink_line.png; sourceTree = ""; }; 7697484F20294D92001AC847 /* PrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrefixHeader.pch; sourceTree = ""; }; + 76B2F9FF216C96C400DA9330 /* mulitRate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = mulitRate.png; path = images/mulitRate.png; sourceTree = ""; }; 76DA9ABF20CA31DB001D3002 /* MultiVideoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MultiVideoViewController.h; sourceTree = ""; }; 76DA9AC020CA31DB001D3002 /* MultiVideoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MultiVideoViewController.m; sourceTree = ""; }; - 76F41C51219D77B40099E668 /* mulitRate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = mulitRate.png; path = images/mulitRate.png; sourceTree = ""; }; + 76ECAC4E21880EFC00EA153E /* ImageVideoMixViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageVideoMixViewController.h; sourceTree = ""; }; + 76ECAC4F21880EFC00EA153E /* ImageVideoMixViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImageVideoMixViewController.m; 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 = ""; }; - AA09EB2822E8672B001BBA54 /* PLSDrawBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSDrawBar.h; sourceTree = ""; }; - AA09EB2922E8672C001BBA54 /* PLSDrawBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSDrawBar.m; sourceTree = ""; }; - AA09EB2B22E86856001BBA54 /* PLSDrawView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSDrawView.m; sourceTree = ""; }; - AA09EB2C22E86856001BBA54 /* PLSDrawView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSDrawView.h; sourceTree = ""; }; - AA09EB2D22E86856001BBA54 /* PLSDrawModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSDrawModel.h; sourceTree = ""; }; - AA09EB2E22E86856001BBA54 /* PLSDrawModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSDrawModel.m; sourceTree = ""; }; - AA09EB3122E87879001BBA54 /* qn_edit_delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_edit_delete@2x.png"; sourceTree = ""; }; - AA09EB3222E8787A001BBA54 /* qn_done@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_done@2x.png"; sourceTree = ""; }; - AA09EB3322E8787A001BBA54 /* qn_edit_delete@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_edit_delete@3x.png"; sourceTree = ""; }; - AA09EB3422E8787A001BBA54 /* qn_revocation@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_revocation@3x.png"; sourceTree = ""; }; - AA09EB3522E8787A001BBA54 /* qn_revocation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_revocation@2x.png"; sourceTree = ""; }; - AA09EB3622E8787A001BBA54 /* qn_done@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_done@3x.png"; sourceTree = ""; }; - BC695AEF228A8FFF005240A7 /* PLSGifStickerBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSGifStickerBar.h; sourceTree = ""; }; - BC695AF0228A8FFF005240A7 /* PLSGifStickerBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSGifStickerBar.m; sourceTree = ""; }; - BC695AF2228A9008005240A7 /* gifSticker.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = gifSticker.bundle; sourceTree = ""; }; - BC8DD6B8224E320200E05B26 /* PLScreenRecorderManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLScreenRecorderManager.h; sourceTree = ""; }; - BC8DD6B9224E320200E05B26 /* PLScreenRecorderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLScreenRecorderManager.m; sourceTree = ""; }; - BCCF75DF21C3884500BF9BA2 /* ImageVideoMixViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageVideoMixViewController.m; sourceTree = ""; }; - BCCF75E021C3884500BF9BA2 /* ImageVideoMixViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageVideoMixViewController.h; sourceTree = ""; }; - C35043631FB3121E00F9633D /* draft_video.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = draft_video.png; path = images/draft_video.png; sourceTree = ""; }; + AA09EB0122E7F71E001BBA54 /* PLSDrawView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLSDrawView.h; sourceTree = ""; }; + AA09EB0222E7F71E001BBA54 /* PLSDrawView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PLSDrawView.m; sourceTree = ""; }; + AA09EB0B22E7FD2F001BBA54 /* PLSDrawBar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLSDrawBar.h; sourceTree = ""; }; + AA09EB0C22E7FD2F001BBA54 /* PLSDrawBar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PLSDrawBar.m; sourceTree = ""; }; + AA09EB0E22E80583001BBA54 /* PLSDrawModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLSDrawModel.h; sourceTree = ""; }; + AA09EB0F22E80583001BBA54 /* PLSDrawModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PLSDrawModel.m; sourceTree = ""; }; + AA09EB1122E83C22001BBA54 /* qn_done@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_done@2x.png"; sourceTree = ""; }; + AA09EB1222E83C22001BBA54 /* qn_done@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_done@3x.png"; sourceTree = ""; }; + AA09EB1522E83C3C001BBA54 /* qn_edit_delete@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_edit_delete@3x.png"; sourceTree = ""; }; + AA09EB1622E83C3C001BBA54 /* qn_edit_delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_edit_delete@2x.png"; sourceTree = ""; }; + AA09EB1922E83C62001BBA54 /* qn_revocation@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_revocation@2x.png"; sourceTree = ""; }; + AA09EB1A22E83C62001BBA54 /* qn_revocation@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qn_revocation@3x.png"; sourceTree = ""; }; + AA1F816C2330B85000AFC7A8 /* PLSListFunctionTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLSListFunctionTableViewCell.h; sourceTree = ""; }; + AA1F816D2330B85000AFC7A8 /* PLSListFunctionTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PLSListFunctionTableViewCell.m; sourceTree = ""; }; + AA1F816F2330C37800AFC7A8 /* MatterImportViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MatterImportViewController.h; sourceTree = ""; }; + AA1F81702330C37800AFC7A8 /* MatterImportViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MatterImportViewController.m; sourceTree = ""; }; + AA1F817D2332324200AFC7A8 /* MoiveClipViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoiveClipViewController.h; sourceTree = ""; }; + AA1F817E2332324200AFC7A8 /* MoiveClipViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MoiveClipViewController.m; sourceTree = ""; }; + AAAEB864230A480A00584B30 /* PLSStickerOverlayView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLSStickerOverlayView.h; sourceTree = ""; }; + AAAEB865230A480A00584B30 /* PLSStickerOverlayView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PLSStickerOverlayView.m; sourceTree = ""; }; + AAAEB87A230BFC8400584B30 /* PLSStickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSStickerView.h; sourceTree = ""; }; + AAAEB87B230BFC8400584B30 /* PLSStickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLSStickerView.m; sourceTree = ""; }; + BC281BF0225212C700CC7584 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; }; + BC570E532254A4DB008FF508 /* PLSGifStickerBar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLSGifStickerBar.h; sourceTree = ""; }; + BC570E542254A4DB008FF508 /* PLSGifStickerBar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PLSGifStickerBar.m; sourceTree = ""; }; + BC570E682255D55A008FF508 /* gifSticker.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = gifSticker.bundle; sourceTree = ""; }; + BCAE1D86224C727100062455 /* PLScreenRecorderManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLScreenRecorderManager.h; sourceTree = ""; }; + BCAE1D87224C727100062455 /* PLScreenRecorderManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PLScreenRecorderManager.m; sourceTree = ""; }; C35043941FBED11C00F9633D /* music_no_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = music_no_selected.png; path = images/music_no_selected.png; sourceTree = ""; }; C35043961FBED11C00F9633D /* music_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = music_selected.png; path = images/music_selected.png; sourceTree = ""; }; C39EA3D51F4E753D0007D1C3 /* PLSRateButtonView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSRateButtonView.h; sourceTree = ""; }; @@ -534,7 +532,6 @@ C3A7913F1FA076E000C3F2D6 /* back_white.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = back_white.png; path = images/back_white.png; sourceTree = ""; }; C3A791411FA076F300C3F2D6 /* scroll_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = scroll_image.png; path = images/scroll_image.png; sourceTree = ""; }; C3A791431FA0772D00C3F2D6 /* scan_line.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = scan_line.png; path = images/scan_line.png; sourceTree = ""; }; - C3A7916A1FA1D4ED00C3F2D6 /* easyar_AR.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = easyar_AR.png; path = images/easyar_AR.png; sourceTree = ""; }; C3FCBFC91F305B21007EBB10 /* GifFormatViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GifFormatViewController.h; sourceTree = ""; }; C3FCBFCA1F305B21007EBB10 /* GifFormatViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GifFormatViewController.m; sourceTree = ""; }; C3FCBFCD1F305B37007EBB10 /* PLSFormatGifView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLSFormatGifView.h; sourceTree = ""; }; @@ -551,6 +548,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + BC281BF8225212C700CC7584 /* ReplayKit.framework in Frameworks */, 0A0DCA2A1FB0715100F1446F /* Accelerate.framework in Frameworks */, C3A78FB71F95F67500C3F2D6 /* libc++.tbd in Frameworks */, C3A78FB51F95F66800C3F2D6 /* JavaScriptCore.framework in Frameworks */, @@ -606,6 +604,8 @@ 0A9435831E6CA2E2008845A3 /* AppDelegate.m */, 0A9435851E6CA2E2008845A3 /* ViewController.h */, 0A9435861E6CA2E2008845A3 /* ViewController.m */, + AA1F816F2330C37800AFC7A8 /* MatterImportViewController.h */, + AA1F81702330C37800AFC7A8 /* MatterImportViewController.m */, 0AECA4BE1E88258100AF2931 /* RecordViewController.h */, 0AECA4FF1E88A60C00AF2931 /* RecordViewController.m */, 76DA9ABF20CA31DB001D3002 /* MultiVideoViewController.h */, @@ -626,8 +626,10 @@ 0AE93A712093F7C50096286E /* ViewRecordViewController.m */, 0A6340281F15C9C9005ADF6C /* MovieTransCodeViewController.h */, 0A6340291F15C9C9005ADF6C /* MovieTransCodeViewController.m */, - BCCF75E021C3884500BF9BA2 /* ImageVideoMixViewController.h */, - BCCF75DF21C3884500BF9BA2 /* ImageVideoMixViewController.m */, + AA1F817D2332324200AFC7A8 /* MoiveClipViewController.h */, + AA1F817E2332324200AFC7A8 /* MoiveClipViewController.m */, + 76ECAC4E21880EFC00EA153E /* ImageVideoMixViewController.h */, + 76ECAC4F21880EFC00EA153E /* ImageVideoMixViewController.m */, 0A52C1911E9C987900561F37 /* EditViewController.h */, 0A52C1921E9C987900561F37 /* EditViewController.m */, C3FCBFC91F305B21007EBB10 /* GifFormatViewController.h */, @@ -636,12 +638,13 @@ 0A26041A1FA80BC900609411 /* DubViewController.m */, 0AECA4F01E88466300AF2931 /* PlayViewController.h */, 0AECA4F11E88466300AF2931 /* PlayViewController.m */, - 76564FCA210B2871004B62E9 /* VersionViewController.h */, - 76564FCB210B2871004B62E9 /* VersionViewController.m */, + 766423252100AF3F000F24A4 /* VersionViewController.h */, + 766423262100AF3F000F24A4 /* VersionViewController.m */, 0A9435881E6CA2E2008845A3 /* Main.storyboard */, 0A94358B1E6CA2E2008845A3 /* Assets.xcassets */, 0A94358D1E6CA2E2008845A3 /* LaunchScreen.storyboard */, 0A9435901E6CA2E2008845A3 /* Info.plist */, + 7697484F20294D92001AC847 /* PrefixHeader.pch */, 0A94357F1E6CA2E2008845A3 /* Supporting Files */, ); path = PLShortVideoKitDemo; @@ -650,117 +653,18 @@ 0A94357F1E6CA2E2008845A3 /* Supporting Files */ = { isa = PBXGroup; children = ( - 76F41C51219D77B40099E668 /* mulitRate.png */, - 0AD98DC5203188CE006551EC /* h265_video */, - 7697483F20285747001AC847 /* TransitionResources */, - 0AF33BF41F7180D100CCFB42 /* 爱马仕.mp4 */, - 0AF33BF51F7180D100CCFB42 /* 爱马仕轨迹.mp4 */, - 0AF33BF61F7180D100CCFB42 /* 川久保玲.mp4 */, - 0AF33BF71F7180D100CCFB42 /* 川久保玲轨迹.mp4 */, - 0AF33BF81F7180D200CCFB42 /* 芬迪.mp4 */, - 0AF33BF91F7180D200CCFB42 /* 芬迪轨迹.mp4 */, - 0AF33BFA1F7180D200CCFB42 /* co.mp4 */, - 0AF33BFB1F7180D200CCFB42 /* co轨迹.mp4 */, - 0AF33BFC1F7180D200CCFB42 /* mv.png */, - 0AF33BFD1F7180D200CCFB42 /* mv1.png */, - 0AF33BFE1F7180D200CCFB42 /* mv2.png */, - 0AF33BFF1F7180D200CCFB42 /* mv3.png */, - 0AF33C001F7180D200CCFB42 /* mv4.png */, - 0AF33C011F7180D200CCFB42 /* plsMVs.json */, - 0AD98DBD20316E33006551EC /* video_draft_test.mp4 */, - 0A1DDC7E20BBE0CA00DF53B6 /* rotate_background.png */, - 0A1DDC8020BBE0CA00DF53B6 /* rotate_image.png */, - 7615EE5321835E3800F7D55D /* watermark.gif */, - 76181FD621186ADE005F4F8B /* scope_image.png */, - 0A5DF89020BE834A00F79CE0 /* pls_multi_musics.json */, - 0AE93A74209424420096286E /* 古代韵味音效.m4r */, - 0AE93A75209424420096286E /* 天使简约音效.m4r */, - 0AE93A76209424430096286E /* 清新鸟鸣音效.m4r */, - 0AD7279C20BF249C00662588 /* 胜利小旋律音效.m4r */, - 7635E40220CE8F5900E36027 /* select_meterial@2x.png */, - 7635E40420CE8F5900E36027 /* select_meterial@3x.png */, - 7635E40320CE8F5900E36027 /* select_pintu@2x.png */, - 7635E40120CE8F5800E36027 /* select_pintu@3x.png */, - 7635E40520CE8F5900E36027 /* select_shoot@2x.png */, - 7635E40020CE8F5800E36027 /* select_shoot@3x.png */, 7635E3DC20CE494800E36027 /* 2video_template@2x.png */, 7635E3DD20CE494800E36027 /* 2video_template@3x.png */, 7635E3DE20CE494800E36027 /* 3video_template@2x.png */, 7635E3DB20CE494800E36027 /* 3video_template@3x.png */, 7635E3DF20CE494900E36027 /* 4video_template@2x.png */, 7635E3E020CE494900E36027 /* 4video_template@3x.png */, - 0AE8ACA31F065F42006166E2 /* If_I_Had_a_Chicken.m4a */, - 0A9E5F721FC7E2380002FB8B /* counter-6s.m4a */, - 0A9E5F741FC7F4340002FB8B /* counter-35s.m4a */, - 0AE8AC9A1F065DCD006166E2 /* Fire_Breather.m4a */, - 0AE8AC9B1F065DCD006166E2 /* Greenery.m4a */, - 0AE8AC9D1F065DCD006166E2 /* Whistling_Down_the_Road.m4a */, - 0AEE565A20AD765C00FBA0D1 /* jikuai.png */, - 0AEE565920AD765B00FBA0D1 /* jiman.png */, - 0AEE565D20AD765D00FBA0D1 /* kuai.png */, - 0AEE565B20AD765C00FBA0D1 /* man.png */, - 0AEE565C20AD765D00FBA0D1 /* zhengchang.png */, - 0A09F0AE201ABE4E00B585D9 /* btn_revocation@2x.png */, - 0A09F0AC201ABE4E00B585D9 /* btn_revocation@3x.png */, - 0A20C1B71FBED24C00E98B07 /* btn_add_text.png */, - C35043941FBED11C00F9633D /* music_no_selected.png */, - C35043961FBED11C00F9633D /* music_selected.png */, - C35043631FB3121E00F9633D /* draft_video.png */, - 0AE538931FB2294700DDF5B9 /* rotate.png */, - C3A7916A1FA1D4ED00C3F2D6 /* easyar_AR.png */, - C3A791431FA0772D00C3F2D6 /* scan_line.png */, - C3A791411FA076F300C3F2D6 /* scroll_image.png */, C3A7913F1FA076E000C3F2D6 /* back_white.png */, - 0AE8AC971F06443A006166E2 /* icon_trim.png */, - C3FCBFD81F305B8A007EBB10 /* icon_gif.png */, - 0A9CB4E81EF042FB00EABA76 /* btn_close_sound@2x.png */, - 0A9CB4E91EF042FB00EABA76 /* btn_close_sound@3x.png */, - 0A9CB4EA1EF042FB00EABA76 /* btn_sound@2x.png */, - 0A9CB4EB1EF042FB00EABA76 /* btn_sound@3x.png */, - C3FCBFD01F305B70007EBB10 /* btn_no_selected_pic@2x.png */, - C3FCBFD11F305B70007EBB10 /* btn_no_selected_pic@3x.png */, - C3FCBFD21F305B70007EBB10 /* btn_selected_pic@2x.png */, - C3FCBFD31F305B70007EBB10 /* btn_selected_pic@3x.png */, - 9343A8BE1F66763A007213BD /* Time_Machine_No_Reverser.png */, - 9343A8BF1F66763A007213BD /* Time_Machine_Reverser.png */, - 0A24C5EC1EE951B900B2314E /* movie.png */, - 0A24C5D81EE912E500B2314E /* plsmusics.json */, - 0A24C5D91EE912E500B2314E /* Road_to_Moscow.mp3 */, - AA09EB3222E8787A001BBA54 /* qn_done@2x.png */, - AA09EB3622E8787A001BBA54 /* qn_done@3x.png */, - AA09EB3122E87879001BBA54 /* qn_edit_delete@2x.png */, - AA09EB3322E8787A001BBA54 /* qn_edit_delete@3x.png */, - AA09EB3522E8787A001BBA54 /* qn_revocation@2x.png */, - AA09EB3422E8787A001BBA54 /* qn_revocation@3x.png */, - 0A4F78FB20072B80003E8218 /* btn_play_bg_a@2x.png */, - 0A4F78F920072B80003E8218 /* btn_play_bg_a@3x.png */, - 0A928BE51EE75ECB007D2250 /* icon_volume.png */, - 0AE85A5C1EE6F5E900EE8E6D /* music.png */, - 0A398F9B1ED6698F00996229 /* cut_bar_progress.png */, - 0A398F9C1ED6698F00996229 /* cut_bar_progress@2x.png */, - 0A398F9D1ED6698F00996229 /* cut_bar_progress@3x.png */, - 0A398F951ED662A000996229 /* cut_bar_right.png */, - 0A398F961ED662A000996229 /* cut_bar_right@2x.png */, - 0A398F971ED662A000996229 /* cut_bar_right@3x.png */, - 0A398F8E1ED6628500996229 /* cut_bar_left.png */, - 0A398F8F1ED6628500996229 /* cut_bar_left@2x.png */, - 0A398F901ED6628500996229 /* cut_bar_left@3x.png */, + 0A20C1B71FBED24C00E98B07 /* btn_add_text.png */, + 0AECA4F31E884CD200AF2931 /* btn_back.png */, 0A398F711ED62A1500996229 /* btn_banner_a.png */, 0A398F721ED62A1500996229 /* btn_banner_a@2x.png */, 0A398F731ED62A1500996229 /* btn_banner_a@3x.png */, - 0AD7D3141EA329A400144411 /* btn_record_a.png */, - 0A1E326E1E8CDED8002C9296 /* Effects4.png */, - 0A1E2CCF1E8CAF8C002C9296 /* btn_makeface_flipcamera@2x.png */, - 0A1E2CD01E8CAF8C002C9296 /* btn_makeface_flipcamera@3x.png */, - 0A1E2CD11E8CAF8C002C9296 /* btn_record_shine_big@2x.png */, - 0A1E2CD21E8CAF8C002C9296 /* btn_record_shine_big@3x.png */, - 0A1E2CD31E8CAF8C002C9296 /* btn_record_shine.png */, - 0A1E2CD41E8CAF8C002C9296 /* btn_record_shine@2x.png */, - 0A1E2CE11E8CAF8C002C9296 /* qiniu_logo.png */, - 0A0692551E8A3C720035CB7B /* btn_del_a@2x.png */, - 0A0692561E8A3C720035CB7B /* btn_del_a@3x.png */, - 0A0692571E8A3C720035CB7B /* btn_del_active_a@2x.png */, - 0A0692581E8A3C720035CB7B /* btn_del_active_a@3x.png */, 0A0692311E8A3B590035CB7B /* btn_bar_back_a@2x.png */, 0A0692321E8A3B590035CB7B /* btn_bar_back_a@3x.png */, 0A0692331E8A3B590035CB7B /* btn_bar_back_b@2x.png */, @@ -779,23 +683,114 @@ 0A0692401E8A3B590035CB7B /* btn_camera_done_b@3x.png */, 0A0692411E8A3B590035CB7B /* btn_camera_done_c@2x.png */, 0A0692421E8A3B590035CB7B /* btn_camera_done_c@3x.png */, - 0AECA4F51E884D0900AF2931 /* video_play.png */, - 0AECA4F31E884CD200AF2931 /* btn_back.png */, + 0A9CB4E81EF042FB00EABA76 /* btn_close_sound@2x.png */, + 0A9CB4E91EF042FB00EABA76 /* btn_close_sound@3x.png */, + 0A0692551E8A3C720035CB7B /* btn_del_a@2x.png */, + 0A0692561E8A3C720035CB7B /* btn_del_a@3x.png */, + 0A0692571E8A3C720035CB7B /* btn_del_active_a@2x.png */, + 0A0692581E8A3C720035CB7B /* btn_del_active_a@3x.png */, + 0A1E2CCF1E8CAF8C002C9296 /* btn_makeface_flipcamera@2x.png */, + 0A1E2CD01E8CAF8C002C9296 /* btn_makeface_flipcamera@3x.png */, + C3FCBFD01F305B70007EBB10 /* btn_no_selected_pic@2x.png */, + C3FCBFD11F305B70007EBB10 /* btn_no_selected_pic@3x.png */, 0A2732301E75F99D005D0CE1 /* btn_play_bg_a.png */, - 0A2731FE1E75E36B005D0CE1 /* progressbar_front.png */, + 0A4F78FB20072B80003E8218 /* btn_play_bg_a@2x.png */, + 0A4F78F920072B80003E8218 /* btn_play_bg_a@3x.png */, + 0A1E2CD11E8CAF8C002C9296 /* btn_record_shine_big@2x.png */, + 0A1E2CD21E8CAF8C002C9296 /* btn_record_shine_big@3x.png */, + 0A1E2CD31E8CAF8C002C9296 /* btn_record_shine.png */, + 0A1E2CD41E8CAF8C002C9296 /* btn_record_shine@2x.png */, + 0A09F0AE201ABE4E00B585D9 /* btn_revocation@2x.png */, + 0A09F0AC201ABE4E00B585D9 /* btn_revocation@3x.png */, + C3FCBFD21F305B70007EBB10 /* btn_selected_pic@2x.png */, + C3FCBFD31F305B70007EBB10 /* btn_selected_pic@3x.png */, + 0A9CB4EA1EF042FB00EABA76 /* btn_sound@2x.png */, + 0A9CB4EB1EF042FB00EABA76 /* btn_sound@3x.png */, + 0AF33BFA1F7180D200CCFB42 /* co.mp4 */, + 0A9E5F721FC7E2380002FB8B /* counter-6s.m4a */, + 0A9E5F741FC7F4340002FB8B /* counter-35s.m4a */, + 0AF33BFB1F7180D200CCFB42 /* co轨迹.mp4 */, + 0A398F8E1ED6628500996229 /* cut_bar_left.png */, + 0A398F8F1ED6628500996229 /* cut_bar_left@2x.png */, + 0A398F901ED6628500996229 /* cut_bar_left@3x.png */, + 0A398F9B1ED6698F00996229 /* cut_bar_progress.png */, + 0A398F9C1ED6698F00996229 /* cut_bar_progress@2x.png */, + 0A398F9D1ED6698F00996229 /* cut_bar_progress@3x.png */, + 0A398F951ED662A000996229 /* cut_bar_right.png */, + 0A398F961ED662A000996229 /* cut_bar_right@2x.png */, + 0A398F971ED662A000996229 /* cut_bar_right@3x.png */, + 0A94DFC71E6DF5D2007BDD0D /* delete.png */, + 0A3CCE771FA91CC8003D766A /* dubber_stop.png */, + 0A1E326E1E8CDED8002C9296 /* Effects4.png */, 0A2731ED1E75D2B0005D0CE1 /* end_disable.png */, 0A94DFC61E6DF5D2007BDD0D /* end_normal.png */, - 0A57EBB31E7596CC00FC5BF8 /* record_close_normal.png */, - 0A94DFC71E6DF5D2007BDD0D /* delete.png */, - 0A94DFC81E6DF5D2007BDD0D /* flash_close.png */, - 0A94DFC91E6DF5D2007BDD0D /* flash_open.png */, - 0A94DFCB1E6DF5D2007BDD0D /* toggle_camera.png */, + 0AE8AC9A1F065DCD006166E2 /* Fire_Breather.m4a */, + 0AE8AC9B1F065DCD006166E2 /* Greenery.m4a */, + 0AD98DC5203188CE006551EC /* h265_video */, 0A2604401FA8498A00609411 /* icon_dub.png */, - 0A3CCE781FA91CC8003D766A /* dubber_start.png */, - 0A3CCE771FA91CC8003D766A /* dubber_stop.png */, - 0A26A7591FE392F9003B9691 /* file_path.png */, + C3FCBFD81F305B8A007EBB10 /* icon_gif.png */, + 0AE8AC971F06443A006166E2 /* icon_trim.png */, + 0A928BE51EE75ECB007D2250 /* icon_volume.png */, + 0AE8ACA31F065F42006166E2 /* If_I_Had_a_Chicken.m4a */, + 0AEE565A20AD765C00FBA0D1 /* jikuai.png */, + 0AEE565920AD765B00FBA0D1 /* jiman.png */, + 0AEE565D20AD765D00FBA0D1 /* kuai.png */, 0A9435801E6CA2E2008845A3 /* main.m */, - 7697484F20294D92001AC847 /* PrefixHeader.pch */, + 0AEE565B20AD765C00FBA0D1 /* man.png */, + 0A24C5EC1EE951B900B2314E /* movie.png */, + 76B2F9FF216C96C400DA9330 /* mulitRate.png */, + C35043941FBED11C00F9633D /* music_no_selected.png */, + C35043961FBED11C00F9633D /* music_selected.png */, + 0AE85A5C1EE6F5E900EE8E6D /* music.png */, + 0AF33BFC1F7180D200CCFB42 /* mv.png */, + 0AF33BFD1F7180D200CCFB42 /* mv1.png */, + 0AF33BFE1F7180D200CCFB42 /* mv2.png */, + 0AF33BFF1F7180D200CCFB42 /* mv3.png */, + 0AF33C001F7180D200CCFB42 /* mv4.png */, + 0A5DF89020BE834A00F79CE0 /* pls_multi_musics.json */, + 0A24C5D81EE912E500B2314E /* plsmusics.json */, + 0AF33C011F7180D200CCFB42 /* plsMVs.json */, + 0A2731FE1E75E36B005D0CE1 /* progressbar_front.png */, + 0A1E2CE11E8CAF8C002C9296 /* qiniu_logo.png */, + AA09EB1122E83C22001BBA54 /* qn_done@2x.png */, + AA09EB1222E83C22001BBA54 /* qn_done@3x.png */, + AA09EB1622E83C3C001BBA54 /* qn_edit_delete@2x.png */, + AA09EB1522E83C3C001BBA54 /* qn_edit_delete@3x.png */, + AA09EB1922E83C62001BBA54 /* qn_revocation@2x.png */, + AA09EB1A22E83C62001BBA54 /* qn_revocation@3x.png */, + 0A57EBB31E7596CC00FC5BF8 /* record_close_normal.png */, + 0A24C5D91EE912E500B2314E /* Road_to_Moscow.mp3 */, + 0A1DDC7E20BBE0CA00DF53B6 /* rotate_background.png */, + 0A1DDC8020BBE0CA00DF53B6 /* rotate_image.png */, + 0AE538931FB2294700DDF5B9 /* rotate.png */, + C3A791431FA0772D00C3F2D6 /* scan_line.png */, + 76425C9C210F48D000FB8200 /* scope_image.png */, + C3A791411FA076F300C3F2D6 /* scroll_image.png */, + 7635E40220CE8F5900E36027 /* select_meterial@2x.png */, + 7635E40420CE8F5900E36027 /* select_meterial@3x.png */, + 7635E40320CE8F5900E36027 /* select_pintu@2x.png */, + 7635E40120CE8F5800E36027 /* select_pintu@3x.png */, + 7635E40520CE8F5900E36027 /* select_shoot@2x.png */, + 7635E40020CE8F5800E36027 /* select_shoot@3x.png */, + 9343A8BE1F66763A007213BD /* Time_Machine_No_Reverser.png */, + 9343A8BF1F66763A007213BD /* Time_Machine_Reverser.png */, + 0A94DFCB1E6DF5D2007BDD0D /* toggle_camera.png */, + 7697483F20285747001AC847 /* TransitionResources */, + 0AD98DBD20316E33006551EC /* video_draft_test.mp4 */, + 0AECA4F51E884D0900AF2931 /* video_play.png */, + 762ECB7E217730B000DFC18B /* watermark.gif */, + 0AE8AC9D1F065DCD006166E2 /* Whistling_Down_the_Road.m4a */, + 0AEE565C20AD765D00FBA0D1 /* zhengchang.png */, + 0AE93A74209424420096286E /* 古代韵味音效.m4r */, + 0AE93A75209424420096286E /* 天使简约音效.m4r */, + 0AF33BF61F7180D100CCFB42 /* 川久保玲.mp4 */, + 0AF33BF71F7180D100CCFB42 /* 川久保玲轨迹.mp4 */, + 0AE93A76209424430096286E /* 清新鸟鸣音效.m4r */, + 0AF33BF41F7180D100CCFB42 /* 爱马仕.mp4 */, + 0AF33BF51F7180D100CCFB42 /* 爱马仕轨迹.mp4 */, + 0AD7279C20BF249C00662588 /* 胜利小旋律音效.m4r */, + 0AF33BF81F7180D200CCFB42 /* 芬迪.mp4 */, + 0AF33BF91F7180D200CCFB42 /* 芬迪轨迹.mp4 */, ); name = "Supporting Files"; sourceTree = ""; @@ -814,14 +809,14 @@ 0A9B8A6620B6822800E7C8D7 /* StickerView */ = { isa = PBXGroup; children = ( - 0A9B8A6720B6822800E7C8D7 /* PLSStickerView.h */, - 0A9B8A6A20B6822800E7C8D7 /* PLSStickerView.m */, - AA09EB2D22E86856001BBA54 /* PLSDrawModel.h */, - AA09EB2E22E86856001BBA54 /* PLSDrawModel.m */, - AA09EB2C22E86856001BBA54 /* PLSDrawView.h */, - AA09EB2B22E86856001BBA54 /* PLSDrawView.m */, - 0A9B8A6820B6822800E7C8D7 /* PLSStickerOverlayView.h */, - 0A9B8A6920B6822800E7C8D7 /* PLSStickerOverlayView.m */, + AA09EB0E22E80583001BBA54 /* PLSDrawModel.h */, + AA09EB0F22E80583001BBA54 /* PLSDrawModel.m */, + AA09EB0122E7F71E001BBA54 /* PLSDrawView.h */, + AA09EB0222E7F71E001BBA54 /* PLSDrawView.m */, + AAAEB864230A480A00584B30 /* PLSStickerOverlayView.h */, + AAAEB865230A480A00584B30 /* PLSStickerOverlayView.m */, + AAAEB87A230BFC8400584B30 /* PLSStickerView.h */, + AAAEB87B230BFC8400584B30 /* PLSStickerView.m */, ); path = StickerView; sourceTree = ""; @@ -831,16 +826,16 @@ children = ( 0A9B8A7220B6822800E7C8D7 /* PLSAssetImageGenerator.h */, 0A9B8A6F20B6822800E7C8D7 /* PLSAssetImageGenerator.m */, + 0A41CD8A20BD516F00315902 /* PLSTimeLineAudioItem.h */, + 0A41CD8B20BD517000315902 /* PLSTimeLineAudioItem.m */, + 0A41CD8720BD502900315902 /* PLSTimeLineItem.h */, + 0A41CD8820BD502900315902 /* PLSTimeLineItem.m */, + 0A9B8A6E20B6822800E7C8D7 /* PLSTimelineItemCell.h */, + 0A9B8A7320B6822800E7C8D7 /* PLSTimelineItemCell.m */, 0A9B8A7120B6822800E7C8D7 /* PLSTimelineMediaInfo.h */, 0A9B8A6C20B6822800E7C8D7 /* PLSTimelineMediaInfo.m */, 0A9B8A7020B6822800E7C8D7 /* PLSTimelineView.h */, 0A9B8A6D20B6822800E7C8D7 /* PLSTimelineView.m */, - 0A9B8A6E20B6822800E7C8D7 /* PLSTimelineItemCell.h */, - 0A9B8A7320B6822800E7C8D7 /* PLSTimelineItemCell.m */, - 0A41CD8720BD502900315902 /* PLSTimeLineItem.h */, - 0A41CD8820BD502900315902 /* PLSTimeLineItem.m */, - 0A41CD8A20BD516F00315902 /* PLSTimeLineAudioItem.h */, - 0A41CD8B20BD517000315902 /* PLSTimeLineAudioItem.m */, ); path = TimelineView; sourceTree = ""; @@ -848,12 +843,12 @@ 0A9B8A7420B6822800E7C8D7 /* ToolBar */ = { isa = PBXGroup; children = ( - BC695AEF228A8FFF005240A7 /* PLSGifStickerBar.h */, - BC695AF0228A8FFF005240A7 /* PLSGifStickerBar.m */, 0A9B8A7620B6822800E7C8D7 /* PLSStickerBar.h */, 0A9B8A7820B6822800E7C8D7 /* PLSStickerBar.m */, - AA09EB2822E8672B001BBA54 /* PLSDrawBar.h */, - AA09EB2922E8672C001BBA54 /* PLSDrawBar.m */, + BC570E532254A4DB008FF508 /* PLSGifStickerBar.h */, + BC570E542254A4DB008FF508 /* PLSGifStickerBar.m */, + AA09EB0B22E7FD2F001BBA54 /* PLSDrawBar.h */, + AA09EB0C22E7FD2F001BBA54 /* PLSDrawBar.m */, 0A9B8A7720B6822800E7C8D7 /* UIView+PLSLightFrame.h */, 0A9B8A7520B6822800E7C8D7 /* UIView+PLSLightFrame.m */, ); @@ -863,7 +858,7 @@ 0A9B8A8120B6868200E7C8D7 /* Source */ = { isa = PBXGroup; children = ( - BC695AF2228A9008005240A7 /* gifSticker.bundle */, + BC570E682255D55A008FF508 /* gifSticker.bundle */, 0A9B8A8920B6868200E7C8D7 /* sticker.bundle */, 0A9B8A8220B6868200E7C8D7 /* paster_time_edit_slider_bg@2x.png */, 0A9B8A8320B6868200E7C8D7 /* video_edit_trim_slider@3x.png */, @@ -908,8 +903,10 @@ 0A6340301F15E8CC005ADF6C /* PLSSelectionView.m */, 0A534EA8200E27F00032A981 /* PLSViewRecorderManager.h */, 0A534EAA200E27F10032A981 /* PLSViewRecorderManager.m */, - BC8DD6B8224E320200E05B26 /* PLScreenRecorderManager.h */, - BC8DD6B9224E320200E05B26 /* PLScreenRecorderManager.m */, + BCAE1D86224C727100062455 /* PLScreenRecorderManager.h */, + BCAE1D87224C727100062455 /* PLScreenRecorderManager.m */, + AA1F816C2330B85000AFC7A8 /* PLSListFunctionTableViewCell.h */, + AA1F816D2330B85000AFC7A8 /* PLSListFunctionTableViewCell.m */, ); path = "UI+Tools"; sourceTree = ""; @@ -978,6 +975,7 @@ 897018225EF668D16731032B /* Frameworks */ = { isa = PBXGroup; children = ( + BC281BF0225212C700CC7584 /* ReplayKit.framework */, 0A0DCA291FB0713700F1446F /* Accelerate.framework */, 0A0DCA271FB070F600F1446F /* libiconv.2.4.0.tbd */, 0A0DCA251FB070E400F1446F /* libz.1.1.3.tbd */, @@ -1065,7 +1063,6 @@ files = ( C35043971FBED6B900F9633D /* music_no_selected.png in Resources */, C35043981FBED6B900F9633D /* music_selected.png in Resources */, - C35043641FB3152600F9633D /* draft_video.png in Resources */, 0A398F921ED6628500996229 /* cut_bar_left@2x.png in Resources */, 0A9B8A9120B6868200E7C8D7 /* video_edit_trim_slider@2x.png in Resources */, 0AEE566020AD765D00FBA0D1 /* man.png in Resources */, @@ -1080,12 +1077,10 @@ 0A9B8A8D20B6868200E7C8D7 /* paster_time_edit_slider_bg@2x.png in Resources */, 0AF33C031F7180D200CCFB42 /* 爱马仕轨迹.mp4 in Resources */, 0AF33C0D1F7180D200CCFB42 /* mv3.png in Resources */, - AA09EB3822E8787A001BBA54 /* qn_done@2x.png in Resources */, 0A9CB4EC1EF042FB00EABA76 /* btn_close_sound@2x.png in Resources */, 0AF33C091F7180D200CCFB42 /* co轨迹.mp4 in Resources */, 0AF33C021F7180D200CCFB42 /* 爱马仕.mp4 in Resources */, 0AE8AC981F06443A006166E2 /* icon_trim.png in Resources */, - 0A26A75A1FE392F9003B9691 /* file_path.png in Resources */, 0A398F9F1ED6698F00996229 /* cut_bar_progress@2x.png in Resources */, 0A9B8A9520B6868200E7C8D7 /* sticker_delete@2x.png in Resources */, C3FCBFD41F305B70007EBB10 /* btn_no_selected_pic@2x.png in Resources */, @@ -1103,7 +1098,7 @@ 0A09F0AF201ABE4F00B585D9 /* btn_revocation@3x.png in Resources */, 0A398F9E1ED6698F00996229 /* cut_bar_progress.png in Resources */, 7697484820285747001AC847 /* transition_black.mp4 in Resources */, - 0A94DFD11E6DF5D2007BDD0D /* flash_open.png in Resources */, + AA09EB1822E83C3C001BBA54 /* qn_edit_delete@2x.png in Resources */, 0A398F751ED62A1500996229 /* btn_banner_a@2x.png in Resources */, 0A9B8A9220B6868200E7C8D7 /* sticker_rotate@2x.png in Resources */, 0A06925C1E8A3C720035CB7B /* btn_del_active_a@3x.png in Resources */, @@ -1126,17 +1121,16 @@ 0A06925A1E8A3C720035CB7B /* btn_del_a@3x.png in Resources */, 0A5DF89220BE834B00F79CE0 /* pls_multi_musics.json in Resources */, 0A94DFCE1E6DF5D2007BDD0D /* end_normal.png in Resources */, - 7615EE5421835E3800F7D55D /* watermark.gif in Resources */, + 762ECB80217730B000DFC18B /* watermark.gif in Resources */, 0A06924F1E8A3B590035CB7B /* btn_camera_done_a@2x.png in Resources */, + BC570E692255D55A008FF508 /* gifSticker.bundle in Resources */, 0A24C5E21EE912E500B2314E /* Road_to_Moscow.mp3 in Resources */, - BC695AF3228A9008005240A7 /* gifSticker.bundle in Resources */, 0A0692431E8A3B590035CB7B /* btn_bar_back_a@2x.png in Resources */, 0A928BE61EE75ECB007D2250 /* icon_volume.png in Resources */, 0A398F981ED662A000996229 /* cut_bar_right.png in Resources */, 0A57EBB41E7596CC00FC5BF8 /* record_close_normal.png in Resources */, 0A1E2CE31E8CAF8C002C9296 /* btn_makeface_flipcamera@3x.png in Resources */, 0A94DFCF1E6DF5D2007BDD0D /* delete.png in Resources */, - 0A94DFD01E6DF5D2007BDD0D /* flash_close.png in Resources */, 7635E3E520CE494900E36027 /* 4video_template@2x.png in Resources */, 0AF33C0C1F7180D200CCFB42 /* mv2.png in Resources */, 0AEE565E20AD765D00FBA0D1 /* jiman.png in Resources */, @@ -1150,15 +1144,13 @@ 0A0692541E8A3B590035CB7B /* btn_camera_done_c@3x.png in Resources */, 0A2604411FA8498B00609411 /* icon_dub.png in Resources */, 7635E40620CE8F5900E36027 /* select_shoot@3x.png in Resources */, + AA09EB1322E83C22001BBA54 /* qn_done@2x.png in Resources */, 0A1E2CE51E8CAF8C002C9296 /* btn_record_shine_big@3x.png in Resources */, 0A9CB4EF1EF042FB00EABA76 /* btn_sound@3x.png in Resources */, 0AE538951FB2294700DDF5B9 /* rotate.png in Resources */, 0AF33C061F7180D200CCFB42 /* 芬迪.mp4 in Resources */, 0A1DDC8220BBE0CB00DF53B6 /* rotate_image.png in Resources */, 0A4F78FC20072B80003E8218 /* btn_play_bg_a@3x.png in Resources */, - 76F41C52219D77B40099E668 /* mulitRate.png in Resources */, - 0A3CCE7A1FA91CC8003D766A /* dubber_start.png in Resources */, - 0AD7D3151EA329A400144411 /* btn_record_a.png in Resources */, 0AE93A78209424430096286E /* 古代韵味音效.m4r in Resources */, 0AE8AC9F1F065DCD006166E2 /* Fire_Breather.m4a in Resources */, 9343A8C11F66763A007213BD /* Time_Machine_Reverser.png in Resources */, @@ -1169,7 +1161,6 @@ 0AF33C0B1F7180D200CCFB42 /* mv1.png in Resources */, 0A0692471E8A3B590035CB7B /* btn_bar_next_a@2x.png in Resources */, 0AF33C041F7180D200CCFB42 /* 川久保玲.mp4 in Resources */, - AA09EB3A22E8787A001BBA54 /* qn_revocation@3x.png in Resources */, 0AF33C0A1F7180D200CCFB42 /* mv.png in Resources */, 0AD7279D20BF249C00662588 /* 胜利小旋律音效.m4r in Resources */, 0A0692471E8A3B590035CB7B /* btn_bar_next_a@2x.png in Resources */, @@ -1181,30 +1172,32 @@ 7635E3E120CE494900E36027 /* 3video_template@3x.png in Resources */, 0A9B8A9420B6868200E7C8D7 /* sticker.bundle in Resources */, 7697484720285747001AC847 /* green_quot.png in Resources */, + 76B2FA01216C96C500DA9330 /* mulitRate.png in Resources */, 0A06924D1E8A3B590035CB7B /* btn_camera_cancel_b@2x.png in Resources */, 0A06924B1E8A3B590035CB7B /* btn_camera_cancel_a@2x.png in Resources */, 0A398FA01ED6698F00996229 /* cut_bar_progress@3x.png in Resources */, 0AEE565F20AD765D00FBA0D1 /* jikuai.png in Resources */, 0AD98DC6203188CE006551EC /* h265_video in Resources */, 0A2732311E75F99D005D0CE1 /* btn_play_bg_a.png in Resources */, + AA09EB1C22E83C62001BBA54 /* qn_revocation@3x.png in Resources */, 0AF33C0F1F7180D200CCFB42 /* plsMVs.json in Resources */, 0A398F761ED62A1500996229 /* btn_banner_a@3x.png in Resources */, 0A24C5ED1EE951B900B2314E /* movie.png in Resources */, 0A1DDC8120BBE0CB00DF53B6 /* rotate_background.png in Resources */, - 76181FD721186ADE005F4F8B /* scope_image.png in Resources */, + 76425C9E210F48D000FB8200 /* scope_image.png in Resources */, 0AECA4F41E884CD200AF2931 /* btn_back.png in Resources */, 7635E40820CE8F5900E36027 /* select_meterial@2x.png in Resources */, 0AE8ACA01F065DCD006166E2 /* Greenery.m4a in Resources */, 0A9CB4ED1EF042FB00EABA76 /* btn_close_sound@3x.png in Resources */, C3FCBFD71F305B70007EBB10 /* btn_selected_pic@3x.png in Resources */, 7635E3E620CE494900E36027 /* 4video_template@3x.png in Resources */, - AA09EB3B22E8787A001BBA54 /* qn_revocation@2x.png in Resources */, + AA09EB1B22E83C62001BBA54 /* qn_revocation@2x.png in Resources */, 0AECA4F61E884D0900AF2931 /* video_play.png in Resources */, 0AF33C071F7180D200CCFB42 /* 芬迪轨迹.mp4 in Resources */, 0A0692451E8A3B590035CB7B /* btn_bar_back_b@2x.png in Resources */, C3FCBFD51F305B70007EBB10 /* btn_no_selected_pic@3x.png in Resources */, + AA09EB1422E83C22001BBA54 /* qn_done@3x.png in Resources */, 0A3CCE791FA91CC8003D766A /* dubber_stop.png in Resources */, - AA09EB3722E8787A001BBA54 /* qn_edit_delete@2x.png in Resources */, 0A06925B1E8A3C720035CB7B /* btn_del_active_a@2x.png in Resources */, 0AF33C0E1F7180D200CCFB42 /* mv4.png in Resources */, 0A9E5F751FC7F4350002FB8B /* counter-35s.m4a in Resources */, @@ -1217,11 +1210,9 @@ 0A24C5E11EE912E500B2314E /* plsmusics.json in Resources */, 0A0692531E8A3B590035CB7B /* btn_camera_done_c@2x.png in Resources */, 0A398F741ED62A1500996229 /* btn_banner_a.png in Resources */, - C3A7916B1FA1D4ED00C3F2D6 /* easyar_AR.png in Resources */, - AA09EB3922E8787A001BBA54 /* qn_edit_delete@3x.png in Resources */, + AA09EB1722E83C3C001BBA54 /* qn_edit_delete@3x.png in Resources */, C3A791441FA0772D00C3F2D6 /* scan_line.png in Resources */, 7697484520285747001AC847 /* zcool-gdh.ttf in Resources */, - AA09EB3C22E8787A001BBA54 /* qn_done@3x.png in Resources */, 0A398F9A1ED662A000996229 /* cut_bar_right@3x.png in Resources */, 0A0692521E8A3B590035CB7B /* btn_camera_done_b@3x.png in Resources */, 7635E3E420CE494900E36027 /* 3video_template@2x.png in Resources */, @@ -1269,24 +1260,26 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - AA09EB2F22E86856001BBA54 /* PLSDrawView.m in Sources */, 7697482D202835D2001AC847 /* TransitionModelSelectView.m in Sources */, 0A41CD8C20BD517000315902 /* PLSTimeLineAudioItem.m in Sources */, 0A9435871E6CA2E2008845A3 /* ViewController.m in Sources */, 0A52C1931E9C987900561F37 /* EditViewController.m in Sources */, + AAAEB87C230BFC8400584B30 /* PLSStickerView.m in Sources */, 0AD98DC4203173F5006551EC /* H265MovieViewController.m in Sources */, 760AE4F820B014FD00DA4EC3 /* VideoSelectViewController.m in Sources */, 760F7706202AF92A0052F513 /* BaseViewController.m in Sources */, - BC8DD6BA224E320200E05B26 /* PLScreenRecorderManager.m in Sources */, + BCAE1D88224C727100062455 /* PLScreenRecorderManager.m in Sources */, 0A398F6C1ED6259000996229 /* PhotoAlbumViewController.m in Sources */, + AA09EB0D22E7FD2F001BBA54 /* PLSDrawBar.m in Sources */, + BC570E552254A4DB008FF508 /* PLSGifStickerBar.m in Sources */, 0AE8AC951F063E3E006166E2 /* PLSClipAudioView.m in Sources */, C39EA3D71F4E753D0007D1C3 /* PLSRateButtonView.m in Sources */, 7697482E202835D2001AC847 /* TransitionTextEditViewController.m in Sources */, 7697482F202835D2001AC847 /* TransitionModelMaker.m in Sources */, 7678EE6E20C96E8300231AA8 /* VideoMixViewController.m in Sources */, - BC695AF1228A8FFF005240A7 /* PLSGifStickerBar.m in Sources */, 0A9B8A8020B6822800E7C8D7 /* PLSStickerBar.m in Sources */, 0A9B8A7E20B6822800E7C8D7 /* PLSTimelineItemCell.m in Sources */, + AA1F817F2332324200AFC7A8 /* MoiveClipViewController.m in Sources */, 0A9B8A7C20B6822800E7C8D7 /* PLSTimelineView.m in Sources */, 7636991A20871AC800626680 /* MixRecordViewController.m in Sources */, 0A9435841E6CA2E2008845A3 /* AppDelegate.m in Sources */, @@ -1295,11 +1288,14 @@ 0A9B8A7B20B6822800E7C8D7 /* PLSTimelineMediaInfo.m in Sources */, C3FCBFCB1F305B21007EBB10 /* GifFormatViewController.m in Sources */, 7623E9E020B5414600847998 /* ImageRotateViewController.m in Sources */, - AA09EB3022E86856001BBA54 /* PLSDrawModel.m in Sources */, + AA09EB1022E80583001BBA54 /* PLSDrawModel.m in Sources */, + AAAEB866230A480A00584B30 /* PLSStickerOverlayView.m in Sources */, 0AE93A722093F7C50096286E /* ViewRecordViewController.m in Sources */, 0A26041B1FA80BC900609411 /* DubViewController.m in Sources */, 0A63402A1F15C9C9005ADF6C /* MovieTransCodeViewController.m in Sources */, 0A41CD8920BD502900315902 /* PLSTimeLineItem.m in Sources */, + AA09EB0322E7F71E001BBA54 /* PLSDrawView.m in Sources */, + AA1F81712330C37800AFC7A8 /* MatterImportViewController.m in Sources */, 760F7707202AF92A0052F513 /* PLSPlayerView.m in Sources */, 0A694C571FE3774B00E2BA60 /* PLSColumnListView.m in Sources */, 760F7704202AF92A0052F513 /* MulitPhotoAlbumViewController.m in Sources */, @@ -1312,20 +1308,18 @@ 0ACE7C371ED8B072002FF4C9 /* PLSDeleteButton.m in Sources */, C3FCBFCF1F305B37007EBB10 /* PLSFormatGifView.m in Sources */, 0ACE7C391ED8B072002FF4C9 /* PLSProgressBar.m in Sources */, - BCCF75E121C3884500BF9BA2 /* ImageVideoMixViewController.m in Sources */, - AA09EB2A22E8672C001BBA54 /* PLSDrawBar.m in Sources */, + 76ECAC5021880EFC00EA153E /* ImageVideoMixViewController.m in Sources */, + AA1F816E2330B85000AFC7A8 /* PLSListFunctionTableViewCell.m in Sources */, 0AECA5001E88A60C00AF2931 /* RecordViewController.m in Sources */, - 76564FCC210B2871004B62E9 /* VersionViewController.m in Sources */, + 766423272100AF3F000F24A4 /* VersionViewController.m in Sources */, 0AECA4F21E88466300AF2931 /* PlayViewController.m in Sources */, C3A791371FA06F3A00C3F2D6 /* PLSLoadAnimationView.m in Sources */, 0A06B0BD1F123299003CA0F6 /* PLSFilterGroup.m in Sources */, - 0A9B8A7A20B6822800E7C8D7 /* PLSStickerView.m in Sources */, 0ACE7C361ED8B072002FF4C9 /* PLSClipMovieView.m in Sources */, 0ACE7C3A1ED8B072002FF4C9 /* UIImage+PLSClip.m in Sources */, 76DA9AC120CA31DB001D3002 /* MultiVideoViewController.m in Sources */, 0A6340311F15E8CC005ADF6C /* PLSSelectionView.m in Sources */, 0A9B8A7F20B6822800E7C8D7 /* UIView+PLSLightFrame.m in Sources */, - 0A9B8A7920B6822800E7C8D7 /* PLSStickerOverlayView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1446,6 +1440,7 @@ baseConfigurationReference = 29048327CD6F75BD8D75B80B /* Pods-PLShortVideoKitDemo.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "3.0.0.git-2019-09-29-62e8c159"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = GDFHW66V92; ENABLE_BITCODE = YES; @@ -1468,6 +1463,7 @@ "$(PROJECT_DIR)", "$(PROJECT_DIR)/PLShortVideoKitDemo/Librarys", ); + MARKETING_VERSION = 3.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.qbox.PLShortVideoKitDemo; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -1478,6 +1474,7 @@ baseConfigurationReference = 85B60FAE619932ED649E6840 /* Pods-PLShortVideoKitDemo.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "3.0.0.git-2019-09-29-62e8c159"; DEVELOPMENT_TEAM = GDFHW66V92; ENABLE_BITCODE = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -1499,6 +1496,7 @@ "$(PROJECT_DIR)", "$(PROJECT_DIR)/PLShortVideoKitDemo/Librarys", ); + MARKETING_VERSION = 3.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.qbox.PLShortVideoKitDemo; PRODUCT_NAME = "$(TARGET_NAME)"; }; diff --git a/Example/PLShortVideoKitDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/PLShortVideoKitDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Example/PLShortVideoKitDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example/PLShortVideoKitDemo.xcodeproj/xcshareddata/xcschemes/PLShortVideoKitDemo.xcscheme b/Example/PLShortVideoKitDemo.xcodeproj/xcshareddata/xcschemes/PLShortVideoKitDemo.xcscheme index 8cffe679..90b82c0d 100644 --- a/Example/PLShortVideoKitDemo.xcodeproj/xcshareddata/xcschemes/PLShortVideoKitDemo.xcscheme +++ b/Example/PLShortVideoKitDemo.xcodeproj/xcshareddata/xcschemes/PLShortVideoKitDemo.xcscheme @@ -1,6 +1,6 @@ #import #import "PLShortVideoKit/PLShortVideoKit.h" @@ -30,6 +32,14 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( [[AVAudioSession sharedInstance] setCategory:(AVAudioSessionCategoryPlayback) error:nil]; + ViewController *viewController = [[ViewController alloc] init]; + UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController]; + navController.modalPresentationStyle = UIModalPresentationFullScreen; + + self.window.rootViewController = navController; + self.window.backgroundColor = [UIColor whiteColor]; + + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; return YES; } diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json index c0b84642..b790c7d3 100755 --- a/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -145,8 +145,9 @@ "scale" : "2x" }, { - "idiom" : "ios-marketing", "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "appicon.png", "scale" : "1x" } ], diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/appicon.png b/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/appicon.png new file mode 100644 index 00000000..32696636 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/AppIcon.appiconset/appicon.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/Contents.json new file mode 100644 index 00000000..506dd67d --- /dev/null +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "close_back@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "close_back@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "close_back@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@1x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@1x.png new file mode 100644 index 00000000..05f0a34c Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@1x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@2x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@2x.png new file mode 100644 index 00000000..6a297893 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@2x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@3x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@3x.png new file mode 100644 index 00000000..b122fe5d Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/close_back.imageset/close_back@3x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/Contents.json new file mode 100644 index 00000000..b0538ee1 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "flash_close@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "flash_close@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "flash_close@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@1x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@1x.png new file mode 100644 index 00000000..337b47f3 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@1x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@2x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@2x.png new file mode 100644 index 00000000..b6fcf10c Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@2x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@3x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@3x.png new file mode 100644 index 00000000..55ae002e Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_close.imageset/flash_close@3x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/Contents.json new file mode 100644 index 00000000..4fd6abd6 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "flash_open@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "flash_open@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "flash_open@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@1x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@1x.png new file mode 100644 index 00000000..caed415e Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@1x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@2x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@2x.png new file mode 100644 index 00000000..2f2eda35 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@2x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@3x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@3x.png new file mode 100644 index 00000000..49cf291a Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/flash_open.imageset/flash_open@3x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/Contents.json new file mode 100644 index 00000000..c62683f9 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "get_back@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "get_back@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "get_back@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@1x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@1x.png new file mode 100644 index 00000000..9003f101 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@1x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@2x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@2x.png new file mode 100644 index 00000000..f182ad40 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@2x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@3x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@3x.png new file mode 100644 index 00000000..86428b8c Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/get_back.imageset/get_back@3x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/Contents.json new file mode 100644 index 00000000..3a7aa2c2 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "next@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "next@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "next@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@1x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@1x.png new file mode 100644 index 00000000..f8be6ed1 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@1x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@2x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@2x.png new file mode 100644 index 00000000..0e2c74b3 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@2x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@3x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@3x.png new file mode 100644 index 00000000..436d7af1 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/next.imageset/next@3x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/Contents.json b/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/Contents.json new file mode 100644 index 00000000..02e04330 --- /dev/null +++ b/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "screen_shoots@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "screen_shoots@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "screen_shoots@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@1x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@1x.png new file mode 100644 index 00000000..25cc62ad Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@1x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@2x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@2x.png new file mode 100644 index 00000000..8c626508 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@2x.png differ diff --git a/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@3x.png b/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@3x.png new file mode 100644 index 00000000..b5245fd5 Binary files /dev/null and b/Example/PLShortVideoKitDemo/Assets.xcassets/screen_shoots.imageset/screen_shoots@3x.png differ diff --git a/Example/PLShortVideoKitDemo/DubViewController.m b/Example/PLShortVideoKitDemo/DubViewController.m index a9f52a48..1af892fd 100644 --- a/Example/PLShortVideoKitDemo/DubViewController.m +++ b/Example/PLShortVideoKitDemo/DubViewController.m @@ -10,10 +10,6 @@ #import "PLSProgressBar.h" #import "PLShortVideoKit/PLShortVideoKit.h" -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) - @interface DubViewController () < diff --git a/Example/PLShortVideoKitDemo/EditViewController.h b/Example/PLShortVideoKitDemo/EditViewController.h index 6ad85283..ac452936 100644 --- a/Example/PLShortVideoKitDemo/EditViewController.h +++ b/Example/PLShortVideoKitDemo/EditViewController.h @@ -13,10 +13,8 @@ @interface EditViewController : UIViewController -@property (strong, nonatomic) NSDictionary *settings; - -@property (strong, nonatomic) NSArray *filesURLArray; - -@property (strong, nonatomic) AVPlayerItem *playerItem; +@property (nonatomic, strong) NSDictionary *settings; +@property (nonatomic, strong) NSArray *filesURLArray; +@property (nonatomic, strong) AVPlayerItem *playerItem; @end diff --git a/Example/PLShortVideoKitDemo/EditViewController.m b/Example/PLShortVideoKitDemo/EditViewController.m index fdc12dbd..ced0a8c5 100644 --- a/Example/PLShortVideoKitDemo/EditViewController.m +++ b/Example/PLShortVideoKitDemo/EditViewController.m @@ -10,31 +10,32 @@ #import "GifFormatViewController.h" #import "DubViewController.h" #import "PlayViewController.h" + #import "PLSEditVideoCell.h" #import "PLSAudioVolumeView.h" #import "PLSClipAudioView.h" #import "PLSFilterGroup.h" #import "PLSRateButtonView.h" #import "PLSColumnListView.h" + #import #import -#import "PLSTimelineView.h" -#import "PLSStickerOverlayView.h" -#import "PLSStickerView.h" -#import "PLSStickerBar.h" -#import "PLSDrawView.h" -#import "PLSDrawBar.h" -#import "PLSClipMovieView.h" +#import + #import +#import "PLSTimelineView.h" // 时间线管理 #import "PLSTimeLineAudioItem.h" -#import "PLSGifStickerBar.h" -#import -#define AlertViewShow(msg) [[[UIAlertView alloc] initWithTitle:@"warning" message:[NSString stringWithFormat:@"%@", msg] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil] show] -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] -#define PLS_RGBCOLOR_ALPHA(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)] -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) +#import "PLSDrawView.h" // 涂鸦操作视图 +#import "PLSStickerView.h" // 文字、图片/Gif 贴纸视图 +#import "PLSStickerOverlayView.h" // 蒙版操作视图,包括文字、贴纸、Gif、涂鸦等 + +#import "PLSStickerBar.h" // 贴图资源选择 +#import "PLSGifStickerBar.h" // Gif 贴图资源选择 +#import "PLSDrawBar.h" // 涂鸦o配置选择 + +#import "PLSClipMovieView.h" // 剪辑视图 + #define PLS_BaseToolboxView_HEIGHT 64 #define PLS_EditToolboxView_HEIGHT 50 @@ -43,199 +44,166 @@ @interface EditViewController () UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, +UIGestureRecognizerDelegate, + +PLShortVideoEditorDelegate, + PLSAudioVolumeViewDelegate, -PLSClipAudioViewDelegate, PLSRateButtonViewDelegate, + DubViewControllerDelegate, -PLShortVideoEditorDelegate, + PLSAVAssetExportSessionDelegate, + +PLSClipAudioViewDelegate, PLSTimelineViewDelegate, + +PLSStickerOverlayViewDelegate, PLSStickerBarDelegate, -PLSStickerViewDelegate, -UIGestureRecognizerDelegate, -PLSClipMovieViewDelegate, PLSGifStickerBarDelegate, -PLSDrawBarDelegate +PLSDrawBarDelegate, + +PLSClipMovieViewDelegate + > -@property (strong, nonatomic) UIView *baseToolboxView; -@property (strong, nonatomic) UIView *editDisplayView; -@property (strong, nonatomic) UIView *editToolboxView; -@property (strong, nonatomic) UIScrollView *buttonScrollView; +@property (nonatomic, strong) UIView *baseToolboxView; +@property (nonatomic, strong) UIView *editDisplayView; +@property (nonatomic, strong) UIView *editToolboxView; +@property (nonatomic, strong) UIScrollView *buttonScrollView; // 水印 -@property (strong, nonatomic) NSURL *watermarkURL; -@property (assign, nonatomic) CGSize watermarkSize; -@property (assign, nonatomic) CGPoint watermarkPosition1; -@property (assign, nonatomic) CGPoint watermarkPosition2; -@property (strong, nonatomic) UIButton *waterMarkButton; - -@property (assign, nonatomic) CGSize gifWatermarkSize; -@property (strong, nonatomic) NSURL *gifWatermarkURL; -@property (strong, nonatomic) UIButton *gifWaterMarkButton; +@property (nonatomic, strong) NSURL *watermarkURL; +@property (nonatomic, assign) CGSize watermarkSize; +@property (nonatomic, assign) CGPoint watermarkPosition1; +@property (nonatomic, assign) CGPoint watermarkPosition2; +@property (nonatomic, strong) UIButton *waterMarkButton; +// gif 水印 +@property (nonatomic, assign) CGSize gifWatermarkSize; +@property (nonatomic, strong) NSURL *gifWatermarkURL; +@property (nonatomic, strong) UIButton *gifWaterMarkButton; // 视频的分辨率,设置之后影响编辑时的预览分辨率、导出的视频的的分辨率 -@property (assign, nonatomic) CGSize videoSize; +@property (nonatomic, assign) CGSize videoSize; +// 原视频配置信息 +@property (nonatomic, strong) NSMutableDictionary *originMovieSettings; // 编辑 -@property (strong, nonatomic) PLShortVideoEditor *shortVideoEditor; +@property (nonatomic, strong) PLShortVideoEditor *shortVideoEditor; // 编辑信息, movieSettings, watermarkSettings, stickerSettingsArray, audioSettingsArray 为 outputSettings 的字典元素 -@property (strong, nonatomic) NSMutableDictionary *outputSettings; +@property (nonatomic, strong) NSMutableDictionary *outputSettings; // 视频文件信息 -@property (strong, nonatomic) NSMutableDictionary *movieSettings; -// 多音频文件作为背景音乐 -@property (strong, nonatomic) NSMutableArray *audioSettingsArray; -// 单一背景音乐的信息,最终要将其添加(addObject)到数组 audioSettingsArray 内 -@property (strong, nonatomic) NSMutableDictionary *backgroundAudioSettings; -// 背景音乐是否循环播放 -@property (assign, nonatomic) BOOL backgroundAudioLoopEnable; -// 水印 -@property (strong, nonatomic) NSMutableArray *watermarkSettingsArray; -@property (strong, nonatomic) UIImage *watermarkImage; -@property (strong, nonatomic) NSData *gifWatermarkData; -@property (strong, nonatomic) NSMutableDictionary *watermarkSetting1; -@property (strong, nonatomic) NSMutableDictionary *watermarkSetting2; +@property (nonatomic, strong) NSMutableDictionary *movieSettings; +// 音频文件信息(可多音频文件作为背景音乐) +@property (nonatomic, strong) NSMutableArray *audioSettingsArray; +// 单一背景音乐的信息,注意:最终要将其添加(addObject)到数组 audioSettingsArray 内 +@property (nonatomic, strong) NSMutableDictionary *backgroundAudioSettings; -// 贴纸信息 -@property (strong, nonatomic) NSMutableArray *stickerSettingsArray; +// 背景音乐是否循环播放 +@property (nonatomic, assign) BOOL backgroundAudioLoopEnable; -// 剪视频 -@property (strong, nonatomic) PLSClipMovieView *clipMovieView; +// 水印 +@property (nonatomic, strong) NSMutableArray *watermarkSettingsArray; +@property (nonatomic, strong) UIImage *watermarkImage; +@property (nonatomic, strong) NSData *gifWatermarkData; +@property (nonatomic, strong) NSMutableDictionary *watermarkSetting1; +@property (nonatomic, strong) NSMutableDictionary *watermarkSetting2; // 选取要编辑的功能点 -@property (assign, nonatomic) NSInteger selectionViewIndex; +@property (nonatomic, assign) NSInteger selectionViewIndex; // 展示所有滤镜、音乐、MV列表的集合视图 -@property (strong, nonatomic) UICollectionView *editCollectionView; +@property (nonatomic, strong) UICollectionView *editCollectionView; // 当前被选择的 cell 对应的 NSIndexPath -@property (strong, nonatomic) NSIndexPath *currentSelectedIndexPath; -@property (strong, nonatomic) NSIndexPath *lastSelectedIndexPath; +@property (nonatomic, strong) NSIndexPath *currentSelectedIndexPath; +@property (nonatomic, strong) NSIndexPath *lastSelectedIndexPath; + // 所有滤镜 -@property (strong, nonatomic) PLSFilterGroup *filterGroup; +@property (nonatomic, strong) PLSFilterGroup *filterGroup; // 滤镜信息 -@property (strong, nonatomic) NSMutableArray *filtersArray; -@property (assign, nonatomic) NSInteger filterIndex; -@property (strong, nonatomic) NSString *colorImagePath; -// 多音效信息 -@property (strong, nonatomic) NSMutableArray *multiMusicsArray; -@property (strong, nonatomic) PLSTimeLineAudioItem *processAudioItem; +@property (nonatomic, strong) NSMutableArray *filtersArray; +@property (nonatomic, assign) NSInteger filterIndex; +@property (nonatomic, strong) NSString *colorImagePath; +// 多音效信息 +@property (nonatomic, strong) NSMutableArray *multiMusicsArray; +@property (nonatomic, strong) PLSTimeLineAudioItem *processAudioItem; // 音乐信息 -@property (strong, nonatomic) NSMutableArray *musicsArray; -// MV信息 -@property (strong, nonatomic) NSMutableArray *mvArray; -@property (strong, nonatomic) NSURL *colorURL; -@property (strong, nonatomic) NSURL *alphaURL; -// 视频倍速信息 -@property (strong, nonatomic) NSMutableArray *videoSpeedArray; // 时光倒流 @property (nonatomic, strong) PLSReverserEffect *reverser; @property (nonatomic, strong) AVAsset *inputAsset; @property (nonatomic, strong) UIButton *reverserButton; +@property (nonatomic, strong) NSMutableArray *musicsArray; -// 视频合成的进度 -@property (strong, nonatomic) UILabel *progressLabel; -@property (strong, nonatomic) UIActivityIndicatorView *activityIndicatorView; +// MV信息 +@property (nonatomic, strong) NSMutableArray *mvArray; +@property (nonatomic, strong) NSURL *colorURL; +@property (nonatomic, strong) NSURL *alphaURL; +// 视频倍速信息 +@property (nonatomic, strong) NSMutableArray *videoSpeedArray; // 倍速下标 -@property (assign, nonatomic) NSInteger titleIndex; -@property (strong, nonatomic) NSArray *titleArray; -@property (strong, nonatomic) NSMutableDictionary *originMovieSettings; -@property (assign, nonatomic) PLSVideoRecoderRateType currentRateType; +@property (nonatomic, assign) NSInteger titleIndex; +@property (nonatomic, strong) NSArray *titleArray; +@property (nonatomic, assign) PLSVideoRecoderRateType currentRateType; // 视频旋转 -@property (assign, nonatomic) PLSPreviewOrientation videoLayerOrientation; +@property (nonatomic, assign) PLSPreviewOrientation videoLayerOrientation; // 视频列表 -@property (strong, nonatomic) PLSColumnListView *videoListView; +@property (nonatomic, strong) PLSColumnListView *videoListView; -// 播放/暂停按钮,点击视频预览区域实现播放/暂停功能 -@property (strong, nonatomic) UIButton *playButton; - -///-------------------------------------------- // 时间线编辑视频组件 -@property (strong, nonatomic) PLSTimelineView *timelineView; -@property (strong, nonatomic) PLSTimelineMediaInfo *mediaInfo; +@property (nonatomic, strong) PLSTimelineView *timelineView; +@property (nonatomic, strong) PLSTimelineMediaInfo *mediaInfo; -// 所有 sticker 添加到该 view 上 -@property (strong, nonatomic) PLSStickerOverlayView *stickerOverlayView; -// 当前选中的贴纸 -@property (weak, nonatomic) PLSStickerView *currentStickerView; -// 添加tap手势 -@property (nonatomic, strong) UITapGestureRecognizer *tapGes; -// 贴纸 gesture 交互相关 -@property (assign, nonatomic) CGPoint loc_in; -@property (nonatomic, nonatomic) CGPoint ori_center; -@property (nonatomic, nonatomic) CGFloat curScale; + +// 贴纸信息 +@property (nonatomic, strong) NSMutableArray *stickerSettingsArray; +// 蒙版视图 +@property (nonatomic, strong) PLSStickerOverlayView *stickerOverlayView; // 贴图工具 -@property (strong, nonatomic) PLSStickerBar *stickerBar; +@property (nonatomic, strong) PLSStickerBar *stickerBar; // 涂鸦工具 -@property (strong, nonatomic) PLSDrawView *currnetDrawView; -@property (strong, nonatomic) PLSDrawBar *drawBar; +@property (nonatomic, strong) PLSDrawView *currnetDrawView; +@property (nonatomic, strong) PLSDrawBar *drawBar; // GIF 动图工具 -@property (strong, nonatomic) PLSGifStickerBar *gifStickerBar; +@property (nonatomic, strong) PLSGifStickerBar *gifStickerBar; // 自定义贴图资源 -@property (strong, nonatomic) NSString *stickerPath; -///-------------------------------------------- +@property (nonatomic, strong) NSString *stickerPath; + +// 播放/暂停按钮,点击视频预览区域实现播放/暂停功能 +@property (nonatomic, strong) UIButton *playButton; +// 添加tap手势 +@property (nonatomic, strong) UITapGestureRecognizer *tapGes; + +// 视频合成的进度 +@property (nonatomic, strong) UILabel *progressLabel; +@property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView; @end @implementation EditViewController -// 检查视频文件中是否含有视频轨道 -- (BOOL)checkMovieHasVideoTrack:(AVAsset *)asset { - BOOL hasVideoTrack = YES; - - NSArray *videoAssetTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; - if (videoAssetTracks.count > 0) { - hasVideoTrack = YES; - } else { - hasVideoTrack = NO; - } + [self observerUIApplicationStatusForShortVideoEditor]; - return hasVideoTrack; + [self.shortVideoEditor startEditing]; + self.playButton.selected = NO; } -// 获取视频/音频文件的总时长 -- (CGFloat)getFileDuration:(NSURL*)URL { - NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]; - AVURLAsset *asset = [AVURLAsset URLAssetWithURL:URL options:opts]; - - CMTime duration = asset.duration; - float durationSeconds = CMTimeGetSeconds(duration); +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; - return durationSeconds; -} - -//类型识别:将 NSNull类型转化成 nil -- (id)checkNSNullType:(id)object { - if([object isKindOfClass:[NSNull class]]) { - return nil; - } - else { - return object; - } -} - -// 获取视频第一帧 -- (UIImage *) getVideoPreViewImage:(AVAsset *)asset { - AVAssetImageGenerator *assetGen = [[AVAssetImageGenerator alloc] initWithAsset:asset]; + [self removeObserverUIApplicationStatusForShortVideoEditor]; - assetGen.maximumSize = CGSizeMake(150, 150); - assetGen.appliesPreferredTrackTransform = YES; - CMTime time = CMTimeMakeWithSeconds(0.0, 600); - NSError *error = nil; - CMTime actualTime; - CGImageRef image = [assetGen copyCGImageAtTime:time actualTime:&actualTime error:&error]; - UIImage *videoImage = [[UIImage alloc] initWithCGImage:image]; - CGImageRelease(image); - return videoImage; + [self.shortVideoEditor stopEditing]; + self.playButton.selected = YES; } -#pragma mark - viewDidLoad - - (void)viewDidLoad { [super viewDidLoad]; @@ -261,29 +229,9 @@ - (void)viewDidLoad { [self setupMergeToolboxView]; } -- (CGFloat)bottomFixSpace { - return iPhoneX_SERIES ? 30 : 0; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self observerUIApplicationStatusForShortVideoEditor]; - - [self.shortVideoEditor startEditing]; - self.playButton.selected = NO; -} - -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - - [self removeObserverUIApplicationStatusForShortVideoEditor]; - - [self.shortVideoEditor stopEditing]; - self.playButton.selected = YES; -} +#pragma mark - set up -#pragma mark - 编辑类 +// 配置 shortVideoEditor - (void)setupShortVideoEditor { // 编辑 /* outputSettings 中的字典元素为 movieSettings, audioSettings, watermarkSettings */ @@ -373,7 +321,36 @@ - (void)setupShortVideoEditor { self.filterGroup = [[PLSFilterGroup alloc] initWithImage:coverImage]; } -#pragma mark - 配置视图 +// 编辑显示视图 +- (void)setupEditDisplayView { + self.editDisplayView = [[UIView alloc] initWithFrame:CGRectMake(0, PLS_BaseToolboxView_HEIGHT + PLS_SCREEN_WIDTH / 8, PLS_SCREEN_WIDTH, PLS_SCREEN_HEIGHT - PLS_BaseToolboxView_HEIGHT - PLS_SCREEN_WIDTH / 8 - PLS_EditToolboxView_HEIGHT - [self bottomFixSpace])]; + self.editDisplayView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + [self.view addSubview:self.editDisplayView]; + + self.shortVideoEditor.previewView.frame = self.editDisplayView.bounds; + self.shortVideoEditor.fillMode = PLSVideoFillModePreserveAspectRatio; + [self.editDisplayView addSubview:self.shortVideoEditor.previewView]; + + self.playButton = [UIButton buttonWithType:UIButtonTypeCustom]; + self.playButton.frame = self.shortVideoEditor.previewView.frame; + self.playButton.center = self.shortVideoEditor.previewView.center; + [self.playButton setImage:[UIImage imageNamed:@"btn_play_bg_a"] forState:UIControlStateSelected]; + [self.editDisplayView addSubview:self.playButton]; + [self.playButton addTarget:self action:@selector(playButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; + + self.stickerOverlayView = [[PLSStickerOverlayView alloc] initWithFrame:self.editDisplayView.bounds layoutView:self.editDisplayView]; + self.stickerOverlayView.delegate = self; + self.stickerOverlayView.backgroundColor = [UIColor clearColor]; + [self updateStickerOverlayView:self.movieSettings[PLSAssetKey]]; + + // 添加点击手势 + self.tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTouchBGView:)]; + self.tapGes.cancelsTouchesInView = NO; + self.tapGes.delegate = self; + [self.view addGestureRecognizer:self.tapGes]; +} + +// 基础工具视图 - (void)setupBaseToolboxView { self.view.backgroundColor = PLS_RGBCOLOR(25, 24, 36); @@ -388,18 +365,18 @@ - (void)setupBaseToolboxView { [backButton setTitle:@"返回" forState:UIControlStateNormal]; [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [backButton setTitleColor:PLS_RGBCOLOR(141, 141, 142) forState:UIControlStateHighlighted]; - backButton.frame = CGRectMake(0, 0, 80, 64); + backButton.frame = CGRectMake(0, 20, 80, 44); 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]; // 标题 - UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 100, 64)]; + UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 20, 100, 44)]; if (iPhoneX_SERIES) { - titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 48); + titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 58); } else { - titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 32); + titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 42); } titleLabel.text = @"编辑视频"; titleLabel.textAlignment = NSTextAlignmentCenter; @@ -414,7 +391,7 @@ - (void)setupBaseToolboxView { [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.frame = CGRectMake(PLS_SCREEN_WIDTH - 80, 20, 80, 44); nextButton.titleEdgeInsets = UIEdgeInsetsMake(0, -40, 0, 0); nextButton.imageEdgeInsets = UIEdgeInsetsMake(0, 50, 0, 0); nextButton.titleLabel.font = [UIFont systemFontOfSize:16]; @@ -422,6 +399,7 @@ - (void)setupBaseToolboxView { [self.baseToolboxView addSubview:nextButton]; } +// 时间线视图 - (void)setupTimelineView { // 时间线视图 self.timelineView = [[PLSTimelineView alloc] initWithFrame:CGRectMake(0, PLS_BaseToolboxView_HEIGHT, PLS_SCREEN_WIDTH, PLS_SCREEN_WIDTH / 8)]; @@ -438,205 +416,65 @@ - (void)setupTimelineView { [self.timelineView setMediaClips:@[self.mediaInfo] segment:8.0 photosPersegent:8.0]; } -- (void)setupEditDisplayView { - self.editDisplayView = [[UIView alloc] initWithFrame:CGRectMake(0, PLS_BaseToolboxView_HEIGHT + PLS_SCREEN_WIDTH / 8, PLS_SCREEN_WIDTH, PLS_SCREEN_HEIGHT - PLS_BaseToolboxView_HEIGHT - PLS_SCREEN_WIDTH / 8 - PLS_EditToolboxView_HEIGHT - [self bottomFixSpace])]; - self.editDisplayView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); - [self.view addSubview:self.editDisplayView]; +// 编辑工具视图 +- (void)setupEditToolboxView { + CGFloat width = PLS_EditToolboxView_HEIGHT; + CGFloat height = 50; + CGFloat startX = 177; + CGFloat space = width + 15; - self.shortVideoEditor.previewView.frame = self.editDisplayView.bounds; - self.shortVideoEditor.fillMode = PLSVideoFillModePreserveAspectRatio; - [self.editDisplayView addSubview:self.shortVideoEditor.previewView]; + self.editToolboxView = [[UIView alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT - width - [self bottomFixSpace], PLS_SCREEN_WIDTH, width)]; + self.editToolboxView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + [self.view addSubview:self.editToolboxView]; - self.playButton = [UIButton buttonWithType:UIButtonTypeCustom]; - self.playButton.frame = self.shortVideoEditor.previewView.frame; - self.playButton.center = self.shortVideoEditor.previewView.center; - [self.playButton setImage:[UIImage imageNamed:@"btn_play_bg_a"] forState:UIControlStateSelected]; - [self.editDisplayView addSubview:self.playButton]; - [self.playButton addTarget:self action:@selector(playButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; + self.buttonScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.editToolboxView.frame.size.width, height)]; + self.buttonScrollView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + self.buttonScrollView.contentSize = CGSizeMake(startX + space * 15, self.buttonScrollView.frame.size.height); + self.buttonScrollView.contentOffset = CGPointMake(0, 0); + self.buttonScrollView.bounces = YES; + self.buttonScrollView.showsHorizontalScrollIndicator = NO; + self.buttonScrollView.showsVerticalScrollIndicator = NO; + [self.editToolboxView addSubview:self.buttonScrollView]; - self.stickerOverlayView = [[PLSStickerOverlayView alloc] init]; - [self.editDisplayView addSubview:self.stickerOverlayView]; - self.stickerOverlayView.backgroundColor = [UIColor clearColor]; - [self updateStickerOverlayView:self.movieSettings[PLSAssetKey]]; + UILabel *hintLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, 162, height)]; + hintLabel.font = [UIFont systemFontOfSize:13]; + hintLabel.textAlignment = NSTextAlignmentLeft; + hintLabel.textColor = [UIColor redColor]; + hintLabel.text = @"左右滑动体验更多功能按钮"; + [self.buttonScrollView addSubview:hintLabel]; - // 添加点击手势 - self.tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTouchBGView:)]; - self.tapGes.cancelsTouchesInView = NO; - self.tapGes.delegate = self; - [self.view addGestureRecognizer:self.tapGes]; -} - -- (void)updateStickerOverlayView:(AVAsset *)asset { - // 视频分辨率 - CGSize vSize = asset.pls_videoSize; + // 水印 + UIButton *button = [self toolBoxButtonWithSelector:@selector(watermarkButtonClick:) + startX:startX + title:@"水印"]; + button.selected = YES; + self.waterMarkButton = button; - CGFloat x = 0; - CGFloat y = 0; + // gif 水印 + button = [self toolBoxButtonWithSelector:@selector(gifWatermarkButtonClick:) + startX:button.frame.origin.x + button.frame.size.width + 20 + title:@"GIF水印"]; + self.gifWaterMarkButton = button; - CGFloat displayViewWidth = self.editDisplayView.frame.size.width; - CGFloat displayViewHeight = self.editDisplayView.frame.size.height; + // 旋转水印 + button = [self toolBoxButtonWithSelector:@selector(rotateWatermarkButtonClick:) + startX:button.frame.origin.x + button.frame.size.width + 20 + title:@"旋转水印"]; - CGFloat width = displayViewWidth; - CGFloat height = displayViewHeight; + // 滤镜 + button = [self toolBoxButtonWithSelector:@selector(filterButtonClick:) + startX:button.frame.origin.x + button.frame.size.width + 20 + title:@"滤镜"]; - if (vSize.width / vSize.height < displayViewWidth / displayViewHeight) { - width = vSize.width / vSize.height * displayViewHeight; - x = (displayViewWidth - width) * 0.5; - }else if (vSize.width / vSize.height > displayViewWidth / displayViewHeight){ - height = vSize.height / vSize.width * displayViewWidth; - y = (displayViewHeight - height) * 0.5; - } - self.stickerOverlayView.frame = CGRectMake(x, y, width, height); -} - -// self.tapGes 手势的响应事件 -- (void)onTouchBGView:(UITapGestureRecognizer *)touches { - // 取消贴纸、字幕的选中状态 - if (_currentStickerView) { - _currentStickerView.select = NO; - [self.timelineView editTimelineComplete]; - } + // 多音效 + button = [self toolBoxButtonWithSelector:@selector(multiMusicButtonEvent:) + startX:button.frame.origin.x + button.frame.size.width + 20 + title:@"多音效"]; - // 回收键盘 - [self.view endEditing:YES]; - - [self hideAllBottomViews]; -} - -- (void)hideAllBottomViews { - [self hideDrawbar]; - // 隐藏显示功能面板 - [self hideStickerbar]; - // 隐藏 GIF 动图选择视频 - [self hideGIFBar]; - // 隐藏显示滤镜、音乐、MV 资源的视图 - [self hideSourceCollectionView]; - // 隐藏剪视频的视图 - [self hideClipMovieView]; - // 隐藏视频列表视图 - [self removeVideoListView]; -} - -#pragma mark - UIGestureRecognizer 手势代理 -- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { - NSMutableArray *classArray = [[NSMutableArray alloc] init]; - UIView *view = touch.view; - while (view) { - [classArray addObject:NSStringFromClass(view.class)]; - view = view.superview; - } - - // 过滤掉 PLSEditVideoCell,让 PLSEditVideoCell 响应它自身的点击事件 - if ([classArray containsObject:NSStringFromClass(PLSEditVideoCell.class)]) { - return NO; - } - - // 过滤掉 PLSDrawBar,让 PLSDrawBar 响应它自身的点击事件 - if ([classArray containsObject:NSStringFromClass(PLSDrawBar.class)]) { - return NO; - } - - // 过滤掉 PLSStickerBar,让 PLSStickerBar 响应它自身的点击事件 - if ([classArray containsObject:NSStringFromClass(PLSStickerBar.class)]) { - return NO; - } - - // 过滤掉 PLSGifStickerBar,让 PLSGifStickerBar 响应它自身的点击事件 - if ([classArray containsObject:NSStringFromClass(PLSGifStickerBar.class)]) { - return NO; - } - - // 过滤掉 UIScrollView,让 UIScrollView 响应它自身的点击事件,UIScrollView 用于展示了底部的功能按钮键 - if ([classArray containsObject:NSStringFromClass(UIScrollView.class)]) { - return NO; - } - - return YES; -} - - -- (UIButton *)toolBoxButtonWithSelector:(SEL)selector - startX:(CGFloat)startX - title:(NSString*)buttonTitle { - CGFloat height = 50; - UIButton *button = [UIButton buttonWithType:(UIButtonTypeCustom)]; - [button setTitle:buttonTitle forState:UIControlStateNormal]; - [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - button.titleLabel.font = [UIFont systemFontOfSize:16]; - [button sizeToFit]; - button.frame = CGRectMake(startX, 0, button.bounds.size.width, height); - [button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside]; - - [self.buttonScrollView addSubview:button]; - - return button; -} - -- (void)setupEditToolboxView { - CGFloat width = PLS_EditToolboxView_HEIGHT; - CGFloat height = 50; - CGFloat startX = 177; - CGFloat space = width + 15; - CGFloat fontSize = 16; - - self.editToolboxView = [[UIView alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT - width - [self bottomFixSpace], PLS_SCREEN_WIDTH, width)]; - self.editToolboxView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); - [self.view addSubview:self.editToolboxView]; - - self.buttonScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.editToolboxView.frame.size.width, height)]; - self.buttonScrollView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); - self.buttonScrollView.contentSize = CGSizeMake(startX + space * 15, self.buttonScrollView.frame.size.height); - self.buttonScrollView.contentOffset = CGPointMake(0, 0); - self.buttonScrollView.bounces = YES; - self.buttonScrollView.showsHorizontalScrollIndicator = NO; - self.buttonScrollView.showsVerticalScrollIndicator = NO; - [self.editToolboxView addSubview:self.buttonScrollView]; - - UILabel *hintLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, 162, height)]; - hintLabel.font = [UIFont systemFontOfSize:13]; - hintLabel.textAlignment = NSTextAlignmentLeft; - hintLabel.textColor = [UIColor redColor]; - hintLabel.text = @"左右滑动体验更多功能按钮"; - [self.buttonScrollView addSubview:hintLabel]; - - // 水印 - UIButton *button = [self toolBoxButtonWithSelector:@selector(watermarkButtonClick:) - startX:startX - title:@"水印"]; - button.selected = YES; - self.waterMarkButton = button; - - // gif 水印 - button = [self toolBoxButtonWithSelector:@selector(gifWatermarkButtonClick:) - startX:button.frame.origin.x + button.frame.size.width + 20 - title:@"GIF水印"]; - self.gifWaterMarkButton = button; - - - // 旋转水印 - button = [self toolBoxButtonWithSelector:@selector(rotateWatermarkButtonClick:) - startX:button.frame.origin.x + button.frame.size.width + 20 - title:@"旋转水印"]; - - // 剪视频 - button = [self toolBoxButtonWithSelector:@selector(clipVideoButtonClick:) - startX:button.frame.origin.x + button.frame.size.width + 20 - title:@"剪视频"]; - - // 滤镜 - button = [self toolBoxButtonWithSelector:@selector(filterButtonClick:) - startX:button.frame.origin.x + button.frame.size.width + 20 - title:@"滤镜"]; - - // 多音效 - button = [self toolBoxButtonWithSelector:@selector(multiMusicButtonEvent:) - startX:button.frame.origin.x + button.frame.size.width + 20 - title:@"多音效"]; - - // 背景音乐 - button = [self toolBoxButtonWithSelector:@selector(musicButtonClick:) - startX:button.frame.origin.x + button.frame.size.width + 20 - title:@"音乐"]; + // 背景音乐 + button = [self toolBoxButtonWithSelector:@selector(musicButtonClick:) + startX:button.frame.origin.x + button.frame.size.width + 20 + title:@"音乐"]; // 裁剪背景音乐 button = [self toolBoxButtonWithSelector:@selector(clipMusicButtonEvent:) @@ -717,6 +555,7 @@ - (void)setupEditToolboxView { self.buttonScrollView.contentSize = CGSizeMake(button.frame.origin.x + button.frame.size.width + 20, self.buttonScrollView.frame.size.height); } +// 拼接工具视图 - (void)setupMergeToolboxView { // 展示拼接视频的动画 self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.view.bounds]; @@ -733,21 +572,31 @@ - (void)setupMergeToolboxView { [self.activityIndicatorView addSubview:self.progressLabel]; } -// 加载拼接视频的动画 -- (void)loadActivityIndicatorView { - if ([self.activityIndicatorView isAnimating]) { - [self.activityIndicatorView stopAnimating]; - [self.activityIndicatorView removeFromSuperview]; - } - - [self.view addSubview:self.activityIndicatorView]; - [self.activityIndicatorView startAnimating]; +// 隐藏底部视图 +- (void)hideAllBottomViews { + [self hideDrawbar]; + // 隐藏显示功能面板 + [self hideStickerbar]; + // 隐藏 GIF 动图选择视频 + [self hideGIFBar]; + // 隐藏显示滤镜、音乐、MV 资源的视图 + [self hideSourceCollectionView]; + // 隐藏视频列表视图 + [self removeVideoListView]; } -// 移除拼接视频的动画 -- (void)removeActivityIndicatorView { - [self.activityIndicatorView removeFromSuperview]; - [self.activityIndicatorView stopAnimating]; +// self.tapGes 手势的响应事件 +- (void)onTouchBGView:(UITapGestureRecognizer *)touches { + // 取消贴纸、字幕的选中状态 + if (self.stickerOverlayView.currentSticker) { + self.stickerOverlayView.currentSticker.isSelected = NO; + [self.timelineView editTimelineComplete]; + } + + // 回收键盘 + [self.view endEditing:YES]; + + [self hideAllBottomViews]; } // 加载视频列表 @@ -776,6 +625,7 @@ - (void)removeVideoListView { } #pragma mark - 启动/暂停视频预览 + - (void)playButtonClicked:(UIButton *)button { if (self.shortVideoEditor.isEditing) { [self.shortVideoEditor stopEditing]; @@ -786,7 +636,9 @@ - (void)playButtonClicked:(UIButton *)button { } } -#pragma mark - 滤镜资源 +#pragma mark - 滤镜、多音效、音乐、MV、视频倍速资源数组获取 + +// 滤镜 - (NSArray *)filtersArray { NSMutableArray *array = [[NSMutableArray alloc] init]; @@ -808,7 +660,7 @@ - (void)playButtonClicked:(UIButton *)button { return array; } -#pragma mark - 多音效资源 +// 多音效 - (NSMutableArray *)multiMusicsArray { NSMutableArray *array = [[NSMutableArray alloc] init]; @@ -843,7 +695,7 @@ - (NSMutableArray *)multiMusicsArray { return array; } -#pragma mark - 音乐资源 +// 音乐 - (NSMutableArray *)musicsArray { NSMutableArray *array = [[NSMutableArray alloc] init]; @@ -878,7 +730,7 @@ - (NSMutableArray *)musicsArray { return array; } -#pragma mark - MV资源 +// MV - (NSMutableArray *)mvArray { NSMutableArray *array = [[NSMutableArray alloc] init]; @@ -923,7 +775,7 @@ - (NSMutableArray *)mvArray { return array; } -#pragma mark - 视频倍速资源 +// 视频倍速 - (NSMutableArray *)videoSpeedArray { NSMutableArray *array = [[NSMutableArray alloc] init]; @@ -944,57 +796,319 @@ - (NSMutableArray *)videoSpeedArray { return array; } -#pragma mark - 获取音乐文件的封面 -- (UIImage *)musicImageWithMusicURL:(NSURL *)url { - NSData *data = nil; - // 初始化媒体文件 - AVURLAsset *mp3Asset = [AVURLAsset URLAssetWithURL:url options:nil]; - // 读取文件中的数据 - for (NSString *format in [mp3Asset availableMetadataFormats]) { - for (AVMetadataItem *metadataItem in [mp3Asset metadataForFormat:format]) { - //artwork这个key对应的value里面存的就是封面缩略图,其它key可以取出其它摘要信息,例如title - 标题 - if ([metadataItem.commonKey isEqualToString:@"artwork"]) { - data = (NSData *)metadataItem.value; +#pragma mark - 添加/更新 MV 特效、滤镜、背景音乐 等效果 - break; - } +- (void)addMVLayerWithColor:(NSURL *)colorURL alpha:(NSURL *)alphaURL { + // 添加/移除 MV 特效 + self.colorURL = colorURL; + self.alphaURL = alphaURL; + + // 添加了 MV 特效,就需要让原视频和 MV 特效视频的分辨率相同 + if (self.colorURL && self.alphaURL) { + AVAsset *asset = [AVAsset assetWithURL:self.colorURL]; + NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; + if (videoTracks.count > 0) { + AVAssetTrack *videoTrack = videoTracks[0]; + CGSize naturalSize = videoTrack.naturalSize; + self.videoSize = CGSizeMake(naturalSize.width, naturalSize.height); + self.shortVideoEditor.videoSize = self.videoSize; + [self updateStickerOverlayView:asset]; } + } else { + self.videoSize = CGSizeZero; + self.shortVideoEditor.videoSize = self.videoSize; + [self updateStickerOverlayView:self.movieSettings[PLSAssetKey]]; } - if (!data) { - // 如果音乐没有图片,就返回默认图片 - return [UIImage imageNamed:@"music"]; + + [self.shortVideoEditor addMVLayerWithColor:self.colorURL alpha:self.alphaURL timeRange:kCMTimeRangeZero loopEnable:YES]; + if (![self.shortVideoEditor isEditing]) { + [self.shortVideoEditor startEditing]; } - return [UIImage imageWithData:data]; } -#pragma mark - UICollectionView delegate 用来展示和处理 SDK 内部自带的滤镜、音乐、MV效果 -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ - if (self.selectionViewIndex == 0) { - // 滤镜 - return self.filtersArray.count; - - } else if (self.selectionViewIndex == 1) { - // 音乐 - return self.musicsArray.count; - - } else if (self.selectionViewIndex == 2) { - // MV - return self.mvArray.count; +- (void)addFilter:(NSString *)colorImagePath { + // 添加/移除 滤镜 + self.colorImagePath = colorImagePath; - } else if (self.selectionViewIndex == 3) { - // 视频倍速 - return self.videoSpeedArray.count; + [self.shortVideoEditor addFilter:self.colorImagePath]; +} + + - (void)addMusic:(NSURL *)musicURL timeRange:(CMTimeRange)timeRange volume:(NSNumber *)volume { + if (!self.shortVideoEditor.isEditing) { + [self.shortVideoEditor startEditing]; + self.playButton.selected = NO; + } + + self.backgroundAudioLoopEnable = YES; + // 添加/移除 背景音乐 + [self.shortVideoEditor addMusic:musicURL timeRange:timeRange volume:volume loopEnable:self.backgroundAudioLoopEnable]; + + if (self.backgroundAudioLoopEnable) { + // 设置背景音乐循环插入到视频中 + self.backgroundAudioSettings[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:0.f]; + self.backgroundAudioSettings[PLSLocationDurationKey] = self.movieSettings[PLSDurationKey]; + } else { + // 设置背景音乐只插入一次到视频中 + self.backgroundAudioSettings[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:0.f]; + self.backgroundAudioSettings[PLSLocationDurationKey] = self.backgroundAudioSettings[PLSDurationKey]; + } +} + +- (void)updateMusic:(CMTimeRange)timeRange volume:(NSNumber *)volume { + // 更新 背景音乐 的 播放时间区间、音量 + [self.shortVideoEditor updateMusic:timeRange volume:volume]; - } else - // 多音效 - return self.multiMusicsArray.count; + if (self.backgroundAudioLoopEnable) { + // 设置背景音乐循环插入到视频中 + self.backgroundAudioSettings[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:0.f]; + self.backgroundAudioSettings[PLSLocationDurationKey] = self.movieSettings[PLSDurationKey]; + } else { + // 设置背景音乐只插入一次到视频中 + self.backgroundAudioSettings[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:0.f]; + self.backgroundAudioSettings[PLSLocationDurationKey] = self.backgroundAudioSettings[PLSDurationKey]; + } } -- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - PLSEditVideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([PLSEditVideoCell class]) forIndexPath:indexPath]; +- (void)updateMultiMusics:(NSMutableArray *)allAddedAudioItems { + // 多音效 + [self.audioSettingsArray removeAllObjects]; + if ([self.timelineView getAllAddedAudioItems].count != 0) { + for (int i = 0; i < [self.timelineView getAllAddedAudioItems].count; i++) { + PLSTimeLineAudioItem *audioItem = [self.timelineView getAllAddedAudioItems][i]; + + NSMutableDictionary *audioItemDictionary = [[NSMutableDictionary alloc] init]; + + audioItemDictionary[PLSURLKey] = audioItem.url; + audioItemDictionary[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f]; + audioItemDictionary[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds([[AVAsset assetWithURL:audioItem.url] duration])]; + audioItemDictionary[PLSVolumeKey] = [NSNumber numberWithFloat:audioItem.volume]; + audioItemDictionary[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:audioItem.startTime]; + audioItemDictionary[PLSLocationDurationKey] = [NSNumber numberWithFloat:(audioItem.endTime - audioItem.startTime)]; + + audioItemDictionary[PLSLocationDurationKey] = [NSNumber numberWithFloat:fabs(audioItem.endTime - audioItem.startTime)]; + [self.audioSettingsArray addObject:audioItemDictionary]; + } + [self.shortVideoEditor updateMultiMusics:self.audioSettingsArray]; + } +} + +#pragma mark - UIGestureRecognizer 手势代理 +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { + NSMutableArray *classArray = [[NSMutableArray alloc] init]; + UIView *view = touch.view; + while (view) { + [classArray addObject:NSStringFromClass(view.class)]; + view = view.superview; + } + + // 过滤掉 PLSEditVideoCell,让 PLSEditVideoCell 响应它自身的点击事件 + if ([classArray containsObject:NSStringFromClass(PLSEditVideoCell.class)]) { + return NO; + } + + // 过滤掉 PLSDrawBar,让 PLSDrawBar 响应它自身的点击事件 + if ([classArray containsObject:NSStringFromClass(PLSDrawBar.class)]) { + return NO; + } + + // 过滤掉 PLSStickerBar,让 PLSStickerBar 响应它自身的点击事件 + if ([classArray containsObject:NSStringFromClass(PLSStickerBar.class)]) { + return NO; + } + + // 过滤掉 PLSGifStickerBar,让 PLSGifStickerBar 响应它自身的点击事件 + if ([classArray containsObject:NSStringFromClass(PLSGifStickerBar.class)]) { + return NO; + } + + // 过滤掉 UIScrollView,让 UIScrollView 响应它自身的点击事件,UIScrollView 用于展示了底部的功能按钮键 + if ([classArray containsObject:NSStringFromClass(UIScrollView.class)]) { + return NO; + } + + // 过滤掉 PLSStickerOverlayView,让 PLSStickerOverlayView 响应它自身的点击事件 + if ([classArray containsObject:NSStringFromClass(PLSStickerOverlayView.class)]) { + return NO; + } + + // 过滤掉 PLSIStickerBaseView,让 PLSIStickerBaseView 响应它自身的点击事件 + if ([classArray containsObject:NSStringFromClass(PLSStickerView.class)]) { + return NO; + } + + return YES; +} + +#pragma mark - PLShortVideoEditorDelegate 编辑时处理视频数据,并将加了滤镜效果的视频数据返回 + +- (CVPixelBufferRef)shortVideoEditor:(PLShortVideoEditor *)editor didGetOriginPixelBuffer:(CVPixelBufferRef)pixelBuffer timestamp:(CMTime)timestamp { + //此处可以做美颜/滤镜等处理 +// NSLog(@"%s, line:%d, timestamp:%f", __FUNCTION__, __LINE__, CMTimeGetSeconds(timestamp)); + + CVPixelBufferRef tempPixelBuffer = pixelBuffer; + + // 更新时间线视图 + CGFloat time = CMTimeGetSeconds(timestamp); + [self.timelineView seekToTime:time]; + + if (self.timelineView.getAllAddedItems.count != 0) { + for (int i = 0; i < self.timelineView.getAllAddedItems.count; i++) { + PLSTimeLineItem *item = self.timelineView.getAllAddedItems[i]; + PLSStickerView *stickerView = (PLSStickerView *)item.target; + CGFloat itemStartTime = item.startTime; + CGFloat itemEndTime = item.endTime; + dispatch_async(dispatch_get_main_queue(), ^{ + if (CMTimeGetSeconds(timestamp) < itemStartTime || CMTimeGetSeconds(timestamp) > itemEndTime) { + stickerView.hidden = YES; + } else { + stickerView.hidden = NO; + } + }); + } + } + + // 多音效 + if (self.selectionViewIndex == 4 && self.currentSelectedIndexPath.row != 0) { + dispatch_async(dispatch_get_main_queue(), ^{ + do { + if ([self.currentSelectedIndexPath compare:self.lastSelectedIndexPath] == NSOrderedSame) { + if (self.processAudioItem) { + self.processAudioItem.endTime = CMTimeGetSeconds(timestamp); + [self.timelineView updateTimelineAudioItem:self.processAudioItem]; + + self.processAudioItem = nil; + self.currentSelectedIndexPath = nil; + self.lastSelectedIndexPath = nil; + + // 更新音效信息,并显示 + [self updateMultiMusics:[self.timelineView getAllAddedAudioItems]]; + + break; + } + } + + if (!self.processAudioItem) { + PLSEditVideoCell *editVideoCell = (PLSEditVideoCell *)[self.editCollectionView cellForItemAtIndexPath:self.currentSelectedIndexPath]; + + CGFloat startTime = CMTimeGetSeconds(timestamp); + CGFloat endTime = 1.0f; + NSString *audioName = editVideoCell.iconPromptLabel.text; + + self.processAudioItem = [[PLSTimeLineAudioItem alloc] init]; + self.processAudioItem.url = [[NSBundle mainBundle] URLForResource:audioName withExtension:nil]; + self.processAudioItem.startTime = startTime; + self.processAudioItem.endTime = endTime; + + self.processAudioItem.volume = 1.0f; + self.processAudioItem.displayColor = [self colorWithName:audioName]; + } + self.processAudioItem.endTime = CMTimeGetSeconds(timestamp); + [self.timelineView updateTimelineAudioItem:self.processAudioItem]; + } while (0); + }); + } + + return tempPixelBuffer; +} + +- (void)shortVideoEditor:(PLShortVideoEditor *)editor didReadyToPlayForAsset:(AVAsset *)asset timeRange:(CMTimeRange)timeRange { + NSLog(@"%s, line:%d", __FUNCTION__, __LINE__); + dispatch_async(dispatch_get_main_queue(), ^{ + self.playButton.selected = NO; + }); +} + +- (void)shortVideoEditor:(PLShortVideoEditor *)editor didReachEndForAsset:(AVAsset *)asset timeRange:(CMTimeRange)timeRange { + NSLog(@"%s, line:%d", __FUNCTION__, __LINE__); + + // 多音效 + if (self.selectionViewIndex == 4 && self.currentSelectedIndexPath.row != 0) { + self.processAudioItem.endTime = CMTimeGetSeconds(timeRange.duration); + [self.timelineView updateTimelineAudioItem:self.processAudioItem]; + + self.processAudioItem = nil; + self.currentSelectedIndexPath = nil; + self.lastSelectedIndexPath = nil; + + // 更新音效信息,并显示 + [self updateMultiMusics:[self.timelineView getAllAddedAudioItems]]; + } +} + +#pragma mark - PLSAVAssetExportSessionDelegate 合成视频文件给视频数据加滤镜效果的回调 + +- (CVPixelBufferRef)assetExportSession:(PLSAVAssetExportSession *)assetExportSession didOutputPixelBuffer:(CVPixelBufferRef)pixelBuffer timestamp:(CMTime)timestamp { + // 视频数据可用来做滤镜处理,将滤镜效果写入视频文件中 +// NSLog(@"%s, line:%d, timestamp:%f", __FUNCTION__, __LINE__, CMTimeGetSeconds(timestamp)); + + CVPixelBufferRef tempPixelBuffer = pixelBuffer; + + return tempPixelBuffer; +} + +#pragma mark - 显示滤镜、音乐、MV 的 CollectionView + +- (void)showSourceCollectionView { + + [self hideAllBottomViews]; + + if (!self.editCollectionView) { + // 展示滤镜、音乐、MV列表效果的 UICollectionView + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.itemSize = CGSizeMake(70, 85); + [layout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; + layout.minimumLineSpacing = 10; + layout.minimumInteritemSpacing = 10; + + CGFloat height = layout.itemSize.height; + self.editCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT - PLS_EditToolboxView_HEIGHT - height - [self bottomFixSpace], PLS_SCREEN_WIDTH, height) collectionViewLayout:layout]; + self.editCollectionView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + self.editCollectionView.showsHorizontalScrollIndicator = NO; + self.editCollectionView.showsVerticalScrollIndicator = NO; + [self.editCollectionView setExclusiveTouch:YES]; + [self.editCollectionView registerClass:[PLSEditVideoCell class] forCellWithReuseIdentifier:NSStringFromClass([PLSEditVideoCell class])]; + self.editCollectionView.delegate = self; + self.editCollectionView.dataSource = self; + [self.editCollectionView reloadData]; + } + if (!self.editCollectionView.superview) { + [self.view addSubview:self.editCollectionView]; + } +} + +- (void)hideSourceCollectionView { + [self.editCollectionView removeFromSuperview]; +} + +#pragma mark - UICollectionView delegate 用来展示和处理 SDK 内部自带的滤镜、音乐、MV效果 + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ + if (self.selectionViewIndex == 0) { + // 滤镜 + return self.filtersArray.count; + + } else if (self.selectionViewIndex == 1) { + // 音乐 + return self.musicsArray.count; + + } else if (self.selectionViewIndex == 2) { + // MV + return self.mvArray.count; + + } else if (self.selectionViewIndex == 3) { + // 视频倍速 + return self.videoSpeedArray.count; + + } else + // 多音效 + return self.multiMusicsArray.count; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + PLSEditVideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([PLSEditVideoCell class]) forIndexPath:indexPath]; UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.editCollectionView.collectionViewLayout; [cell setLabelFrame:CGRectMake(0, 0, layout.itemSize.width, 15) imageViewFrame:CGRectMake(0, 15, layout.itemSize.width, layout.itemSize.width)]; - + if (self.selectionViewIndex == 0) { // 滤镜 NSDictionary *filterInfoDic = self.filtersArray[indexPath.row]; @@ -1019,10 +1133,10 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell NSString *musicName = [dic objectForKey:@"audioName"]; NSURL *musicUrl = [dic objectForKey:@"audioUrl"]; UIImage *musicImage = [self musicImageWithMusicURL:musicUrl]; - + cell.iconPromptLabel.text = musicName; cell.iconImageView.image = musicImage; - + } else if (self.selectionViewIndex == 2) { // MV NSDictionary *dic = self.mvArray[indexPath.row]; @@ -1032,7 +1146,7 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell cell.iconPromptLabel.text = name; cell.iconImageView.image = coverImage; - + } else if (self.selectionViewIndex == 3) { // 视频倍速 NSDictionary *dic = self.videoSpeedArray[indexPath.row]; @@ -1042,7 +1156,7 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell cell.iconPromptLabel.text = name; cell.iconImageView.image = coverImage; - + } else if (self.selectionViewIndex == 4) { // 多音效 NSDictionary *dic = self.multiMusicsArray[indexPath.row]; @@ -1058,6 +1172,7 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell } #pragma mark - UICollectionView delegate 切换滤镜、背景音乐、MV 特效 + - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if (self.selectionViewIndex == 0) { // 滤镜 @@ -1077,7 +1192,7 @@ - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPa self.backgroundAudioSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f]; self.backgroundAudioSettings[PLSDurationKey] = [NSNumber numberWithFloat:0.f]; self.backgroundAudioSettings[PLSNameKey] = musicName; - + } else { NSDictionary *dic = self.musicsArray[indexPath.row]; @@ -1095,22 +1210,22 @@ - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPa CMTimeRange musicTimeRange= CMTimeRangeMake(CMTimeMake([self.backgroundAudioSettings[PLSStartTimeKey] floatValue] * 1000, 1000), CMTimeMake([self.backgroundAudioSettings[PLSDurationKey] floatValue] * 1000, 1000)); NSNumber *musicVolume = self.backgroundAudioSettings[PLSVolumeKey]; [self addMusic:musicURL timeRange:musicTimeRange volume:musicVolume]; - + } else if (self.selectionViewIndex == 2) { if (!indexPath.row) { // ****** 要特别注意此处,无MV URL ****** -// NSDictionary *dic = self.mvArray[indexPath.row]; -// NSString *name = [dic objectForKey:@"name"]; -// NSString *coverDir = [dic objectForKey:@"coverDir"]; -// NSString *colorDir = [dic objectForKey:@"colorDir"]; -// NSString *alphaDir = [dic objectForKey:@"alphaDir"]; + // NSDictionary *dic = self.mvArray[indexPath.row]; + // NSString *name = [dic objectForKey:@"name"]; + // NSString *coverDir = [dic objectForKey:@"coverDir"]; + // NSString *colorDir = [dic objectForKey:@"colorDir"]; + // NSString *alphaDir = [dic objectForKey:@"alphaDir"]; [self addMVLayerWithColor:nil alpha:nil]; } else { NSDictionary *dic = self.mvArray[indexPath.row]; -// NSString *name = [dic objectForKey:@"name"]; -// NSString *coverDir = [dic objectForKey:@"coverDir"]; + // NSString *name = [dic objectForKey:@"name"]; + // NSString *coverDir = [dic objectForKey:@"coverDir"]; NSString *colorDir = [dic objectForKey:@"colorDir"]; NSString *alphaDir = [dic objectForKey:@"alphaDir"]; @@ -1119,7 +1234,7 @@ - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPa [self addMVLayerWithColor:colorURL alpha:alphaURL]; } - + } else if (self.selectionViewIndex == 3) { // 视频倍速 NSInteger index = indexPath.row; @@ -1132,7 +1247,7 @@ - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPa self.currentSelectedIndexPath = indexPath; NSMutableDictionary *audioSettings = [[NSMutableDictionary alloc] init]; - + if (!indexPath.row) { // ****** 要特别注意此处,无音频 URL ****** NSDictionary *dic = self.multiMusicsArray[indexPath.row]; @@ -1162,218 +1277,11 @@ - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPa } } -#pragma mark - 添加/更新 MV 特效、滤镜、背景音乐 等效果 -- (void)addMVLayerWithColor:(NSURL *)colorURL alpha:(NSURL *)alphaURL { - // 添加/移除 MV 特效 - self.colorURL = colorURL; - self.alphaURL = alphaURL; - - // 添加了 MV 特效,就需要让原视频和 MV 特效视频的分辨率相同 - if (self.colorURL && self.alphaURL) { - AVAsset *asset = [AVAsset assetWithURL:self.colorURL]; - NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; - if (videoTracks.count > 0) { - AVAssetTrack *videoTrack = videoTracks[0]; - CGSize naturalSize = videoTrack.naturalSize; - self.videoSize = CGSizeMake(naturalSize.width, naturalSize.height); - self.shortVideoEditor.videoSize = self.videoSize; - [self updateStickerOverlayView:asset]; - } - } else { - self.videoSize = CGSizeZero; - self.shortVideoEditor.videoSize = self.videoSize; - [self updateStickerOverlayView:self.movieSettings[PLSAssetKey]]; - } - - [self.shortVideoEditor addMVLayerWithColor:self.colorURL alpha:self.alphaURL timeRange:kCMTimeRangeZero loopEnable:YES]; - if (![self.shortVideoEditor isEditing]) { - [self.shortVideoEditor startEditing]; - } -} - -- (void)addFilter:(NSString *)colorImagePath { - // 添加/移除 滤镜 - self.colorImagePath = colorImagePath; - - [self.shortVideoEditor addFilter:self.colorImagePath]; -} - - - (void)addMusic:(NSURL *)musicURL timeRange:(CMTimeRange)timeRange volume:(NSNumber *)volume { - if (!self.shortVideoEditor.isEditing) { - [self.shortVideoEditor startEditing]; - self.playButton.selected = NO; - } - - self.backgroundAudioLoopEnable = YES; - // 添加/移除 背景音乐 - [self.shortVideoEditor addMusic:musicURL timeRange:timeRange volume:volume loopEnable:self.backgroundAudioLoopEnable]; - - if (self.backgroundAudioLoopEnable) { - // 设置背景音乐循环插入到视频中 - self.backgroundAudioSettings[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:0.f]; - self.backgroundAudioSettings[PLSLocationDurationKey] = self.movieSettings[PLSDurationKey]; - } else { - // 设置背景音乐只插入一次到视频中 - self.backgroundAudioSettings[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:0.f]; - self.backgroundAudioSettings[PLSLocationDurationKey] = self.backgroundAudioSettings[PLSDurationKey]; - } -} - -- (void)updateMusic:(CMTimeRange)timeRange volume:(NSNumber *)volume { - // 更新 背景音乐 的 播放时间区间、音量 - [self.shortVideoEditor updateMusic:timeRange volume:volume]; - - if (self.backgroundAudioLoopEnable) { - // 设置背景音乐循环插入到视频中 - self.backgroundAudioSettings[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:0.f]; - self.backgroundAudioSettings[PLSLocationDurationKey] = self.movieSettings[PLSDurationKey]; - } else { - // 设置背景音乐只插入一次到视频中 - self.backgroundAudioSettings[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:0.f]; - self.backgroundAudioSettings[PLSLocationDurationKey] = self.backgroundAudioSettings[PLSDurationKey]; - } -} - -#pragma mark - PLShortVideoEditorDelegate 编辑时处理视频数据,并将加了滤镜效果的视频数据返回 -- (CVPixelBufferRef)shortVideoEditor:(PLShortVideoEditor *)editor didGetOriginPixelBuffer:(CVPixelBufferRef)pixelBuffer timestamp:(CMTime)timestamp { - //此处可以做美颜/滤镜等处理 -// NSLog(@"%s, line:%d, timestamp:%f", __FUNCTION__, __LINE__, CMTimeGetSeconds(timestamp)); - - CVPixelBufferRef tempPixelBuffer = pixelBuffer; - - // 更新时间线视图 - CGFloat time = CMTimeGetSeconds(timestamp); - [self.timelineView seekToTime:time]; - - if (self.timelineView.getAllAddedItems.count != 0) { - for (int i = 0; i < self.timelineView.getAllAddedItems.count; i++) { - PLSTimeLineItem *item = self.timelineView.getAllAddedItems[i]; - PLSStickerView *stickerView = (PLSStickerView *)item.target; - CGFloat itemStartTime = item.startTime; - CGFloat itemEndTime = item.endTime; - dispatch_async(dispatch_get_main_queue(), ^{ - if (CMTimeGetSeconds(timestamp) < itemStartTime || CMTimeGetSeconds(timestamp) > itemEndTime) { - stickerView.hidden = YES; - } else { - stickerView.hidden = NO; - } - }); - } - } - - // 多音效 - if (self.selectionViewIndex == 4 && self.currentSelectedIndexPath.row != 0) { - dispatch_async(dispatch_get_main_queue(), ^{ - do { - if ([self.currentSelectedIndexPath compare:self.lastSelectedIndexPath] == NSOrderedSame) { - if (self.processAudioItem) { - self.processAudioItem.endTime = CMTimeGetSeconds(timestamp); - [self.timelineView updateTimelineAudioItem:self.processAudioItem]; - - self.processAudioItem = nil; - self.currentSelectedIndexPath = nil; - self.lastSelectedIndexPath = nil; - - // 更新音效信息,并显示 - [self updateMultiMusics:[self.timelineView getAllAddedAudioItems]]; - - break; - } - } - - if (!self.processAudioItem) { - PLSEditVideoCell *editVideoCell = (PLSEditVideoCell *)[self.editCollectionView cellForItemAtIndexPath:self.currentSelectedIndexPath]; - - CGFloat startTime = CMTimeGetSeconds(timestamp); - CGFloat endTime = 1.0f; - NSString *audioName = editVideoCell.iconPromptLabel.text; - - self.processAudioItem = [[PLSTimeLineAudioItem alloc] init]; - self.processAudioItem.url = [[NSBundle mainBundle] URLForResource:audioName withExtension:nil]; - self.processAudioItem.startTime = startTime; - self.processAudioItem.endTime = endTime; - self.processAudioItem.volume = 1.0f; - self.processAudioItem.displayColor = [self colorWithName:audioName]; - } - self.processAudioItem.endTime = CMTimeGetSeconds(timestamp); - [self.timelineView updateTimelineAudioItem:self.processAudioItem]; - } while (0); - }); - } - - return tempPixelBuffer; -} - -- (void)shortVideoEditor:(PLShortVideoEditor *)editor didReadyToPlayForAsset:(AVAsset *)asset timeRange:(CMTimeRange)timeRange { - NSLog(@"%s, line:%d", __FUNCTION__, __LINE__); - dispatch_async(dispatch_get_main_queue(), ^{ - self.playButton.selected = NO; - }); -} - -- (void)shortVideoEditor:(PLShortVideoEditor *)editor didReachEndForAsset:(AVAsset *)asset timeRange:(CMTimeRange)timeRange { - NSLog(@"%s, line:%d", __FUNCTION__, __LINE__); - - // 多音效 - if (self.selectionViewIndex == 4 && self.currentSelectedIndexPath.row != 0) { - self.processAudioItem.endTime = CMTimeGetSeconds(timeRange.duration); - [self.timelineView updateTimelineAudioItem:self.processAudioItem]; - - self.processAudioItem = nil; - self.currentSelectedIndexPath = nil; - self.lastSelectedIndexPath = nil; - - // 更新音效信息,并显示 - [self updateMultiMusics:[self.timelineView getAllAddedAudioItems]]; - } -} - -#pragma mark - PLSAVAssetExportSessionDelegate 合成视频文件给视频数据加滤镜效果的回调 -- (CVPixelBufferRef)assetExportSession:(PLSAVAssetExportSession *)assetExportSession didOutputPixelBuffer:(CVPixelBufferRef)pixelBuffer timestamp:(CMTime)timestamp { - // 视频数据可用来做滤镜处理,将滤镜效果写入视频文件中 -// NSLog(@"%s, line:%d, timestamp:%f", __FUNCTION__, __LINE__, CMTimeGetSeconds(timestamp)); - - CVPixelBufferRef tempPixelBuffer = pixelBuffer; - - return tempPixelBuffer; -} - -#pragma mark - 显示滤镜、音乐、MV 的 CollectionView -- (void)showSourceCollectionView { - - [self hideAllBottomViews]; - - if (!self.editCollectionView) { - // 展示滤镜、音乐、MV列表效果的 UICollectionView - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - layout.itemSize = CGSizeMake(70, 85); - [layout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; - layout.minimumLineSpacing = 10; - layout.minimumInteritemSpacing = 10; - - CGFloat height = layout.itemSize.height; - self.editCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT - PLS_EditToolboxView_HEIGHT - height - [self bottomFixSpace], PLS_SCREEN_WIDTH, height) collectionViewLayout:layout]; - self.editCollectionView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); - self.editCollectionView.showsHorizontalScrollIndicator = NO; - self.editCollectionView.showsVerticalScrollIndicator = NO; - [self.editCollectionView setExclusiveTouch:YES]; - [self.editCollectionView registerClass:[PLSEditVideoCell class] forCellWithReuseIdentifier:NSStringFromClass([PLSEditVideoCell class])]; - self.editCollectionView.delegate = self; - self.editCollectionView.dataSource = self; - [self.editCollectionView reloadData]; - } - if (!self.editCollectionView.superview) { - [self.view addSubview:self.editCollectionView]; - } -} - -- (void)hideSourceCollectionView { - [self.editCollectionView removeFromSuperview]; -} +#pragma mark - UIButton 功能按钮响应事件 -#pragma mark - UIButton 按钮响应事件 -#pragma mark - 水印 +// 水印 - (void)watermarkButtonClick:(UIButton *)button { + button.selected = !button.selected; self.gifWaterMarkButton.selected = NO; if (!button.selected) { @@ -1405,6 +1313,7 @@ - (void)watermarkButtonClick:(UIButton *)button { } } +// gif 水印 - (void)gifWatermarkButtonClick:(UIButton *)button { button.selected = !button.selected; self.waterMarkButton.selected = NO; @@ -1441,6 +1350,7 @@ - (void)gifWatermarkButtonClick:(UIButton *)button { } } +// 旋转水印 - (void)rotateWatermarkButtonClick:(UIButton *)button { if (self.gifWaterMarkButton.isSelected || self.waterMarkButton.isSelected) { CGFloat degree = [self.watermarkSetting1[PLSRotationKey] floatValue]; @@ -1455,68 +1365,7 @@ - (void)rotateWatermarkButtonClick:(UIButton *)button { } } -#pragma mark - 剪视频 -- (void)clipVideoButtonClick:(id)sender { - [self showClipMovieView]; -} - -- (void)showClipMovieView { - - [self hideAllBottomViews]; - - if (!self.clipMovieView) { - AVAsset *asset = self.movieSettings[PLSAssetKey]; - CGFloat duration = CMTimeGetSeconds(asset.duration); - - self.clipMovieView = [[PLSClipMovieView alloc] initWithMovieAsset:asset minDuration:2.0f maxDuration:duration]; - self.clipMovieView.frame = CGRectMake(0, PLS_SCREEN_HEIGHT - PLS_EditToolboxView_HEIGHT - 150 - [self bottomFixSpace], PLS_SCREEN_WIDTH, 150); - self.clipMovieView.delegate = self; - } - if (!self.clipMovieView.superview) { - [self.view addSubview:self.clipMovieView]; - } -} - -- (void)hideClipMovieView { - [self.clipMovieView removeFromSuperview]; -} - -#pragma mark - 裁剪视频的回调 PLSClipMovieView delegate -- (void)didStartDragView { - -} - -- (void)clipFrameView:(PLSClipMovieView *)clipFrameView didEndDragLeftView:(CMTime)leftTime rightView:(CMTime)rightTime { - CGFloat start = CMTimeGetSeconds(leftTime); - CGFloat end = CMTimeGetSeconds(rightTime); - CGFloat duration = end - start; - - self.originMovieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:start]; - self.originMovieSettings[PLSDurationKey] = [NSNumber numberWithFloat:duration]; - - // 每次选段变化之后,将变化的值按照倍速作用到 movieSettings 中 - float rate = [self getRateNumberWithRateType:self.currentRateType]; - float rateStart = start * rate; - float rateDuration = duration * rate; - self.movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:rateStart]; - self.movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:rateDuration]; - - CMTimeRange timeRange = CMTimeRangeMake(CMTimeMake(rateStart * 1000, 1000), CMTimeMake(rateDuration * 1000, 1000)); - self.watermarkSetting1[PLSStartTimeKey] = [NSNumber numberWithFloat:0]; - self.watermarkSetting1[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(timeRange.duration)/3.0]; - - self.watermarkSetting2[PLSStartTimeKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(timeRange.duration)/3.0*2]; - self.watermarkSetting2[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(timeRange.duration)/3.0]; - - self.shortVideoEditor.timeRange = timeRange; - [self.shortVideoEditor startEditing]; -} - -- (void)clipFrameView:(PLSClipMovieView *)clipFrameView isScrolling:(BOOL)scrolling { - self.view.userInteractionEnabled = !scrolling; -} - -#pragma mark - 滤镜 +// 滤镜 - (void)filterButtonClick:(id)sender { [self showSourceCollectionView]; @@ -1527,7 +1376,7 @@ - (void)filterButtonClick:(id)sender { [self.editCollectionView reloadData]; } -#pragma mark - 多音效 +// 多音效 - (void)multiMusicButtonEvent:(id)sender { [self showSourceCollectionView]; @@ -1538,53 +1387,16 @@ - (void)multiMusicButtonEvent:(id)sender { [self.editCollectionView reloadData]; } -- (void)updateMultiMusics:(NSMutableArray *)allAddedAudioItems { - // 多音效 - if ([self.timelineView getAllAddedAudioItems].count != 0) { - for (int i = 0; i < [self.timelineView getAllAddedAudioItems].count; i++) { - PLSTimeLineAudioItem *audioItem = [self.timelineView getAllAddedAudioItems][i]; - - NSMutableDictionary *audioItemDictionary = [[NSMutableDictionary alloc] init]; - - audioItemDictionary[PLSURLKey] = audioItem.url; - audioItemDictionary[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f]; - audioItemDictionary[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds([[AVAsset assetWithURL:audioItem.url] duration])]; - audioItemDictionary[PLSVolumeKey] = [NSNumber numberWithFloat:audioItem.volume]; - audioItemDictionary[PLSLocationStartTimeKey] = [NSNumber numberWithFloat:audioItem.startTime]; - audioItemDictionary[PLSLocationDurationKey] = [NSNumber numberWithFloat:(audioItem.endTime - audioItem.startTime)]; - - [self.audioSettingsArray addObject:audioItemDictionary]; - } - - [self.shortVideoEditor updateMultiMusics:self.audioSettingsArray]; - } -} - -#pragma mark - 配音 +// 配音 - (void)dubAudioButtonEvent:(id)sender{ DubViewController *dubViewController = [[DubViewController alloc]init]; dubViewController.movieSettings = self.movieSettings; dubViewController.delegate = self; + dubViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:dubViewController animated:YES completion:nil]; } -#pragma mark - DubViewControllerDelegate 配音的回调 -- (void)didOutputAsset:(AVAsset *)asset { - NSLog(@"保存配音后的回调"); - - self.movieSettings[PLSAssetKey] = asset; - self.movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f]; - self.movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(asset.duration)]; - - CMTime start = CMTimeMake([self.movieSettings[PLSStartTimeKey] floatValue] * 1000, 1000); - CMTime duration = CMTimeMake([self.movieSettings[PLSDurationKey] floatValue] * 1000, 1000); - self.shortVideoEditor.timeRange = CMTimeRangeMake(start, duration); - [self.shortVideoEditor replaceCurrentAssetWithAsset:self.movieSettings[PLSAssetKey]]; - [self.shortVideoEditor startEditing]; - self.playButton.selected = NO; -} - -#pragma mark - 背景音乐 +// 背景音乐 - (void)musicButtonClick:(id)sender { [self showSourceCollectionView]; @@ -1595,7 +1407,7 @@ - (void)musicButtonClick:(id)sender { [self.editCollectionView reloadData]; } -#pragma mark - MV 特效 +// MV 特效 - (void)mvButtonClick:(id)sender { [self showSourceCollectionView]; @@ -1606,12 +1418,12 @@ - (void)mvButtonClick:(id)sender { [self.editCollectionView reloadData]; } -#pragma mark - 制作Gif图 +// 制作Gif图 - (void)formatGifButtonEvent:(id)sender { [self joinGifFormatViewController]; } -#pragma mark - 制作封面动图 +// 制作封面动图 - (void)formatGifThumbEvent:(id)sender { AVAsset *asset = self.movieSettings[PLSAssetKey]; [self loadActivityIndicatorView]; @@ -1649,6 +1461,7 @@ - (void)formatGifThumbEvent:(id)sender { PlayViewController *playViewController = [[PlayViewController alloc]init]; playViewController.actionType = PLSActionTypeGif; playViewController.url = url; + playViewController.modalPresentationStyle = UIModalPresentationFullScreen; [weakSelf presentViewController:playViewController animated:YES completion:nil]; }]; @@ -1661,7 +1474,7 @@ - (void)formatGifThumbEvent:(id)sender { }]; } -#pragma mark - 时光倒流 +// 时光倒流 - (void)reverserButtonEvent:(id)sender { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"是否移除音频" message:@"如果不移除音频,将维持原音频,即不对音频进行倒序处理" preferredStyle:(UIAlertControllerStyleAlert)]; @@ -1732,7 +1545,7 @@ - (void)doReserverEffect:(BOOL)removeAudio { [self.reverser startReversing]; } -#pragma mark - 裁剪背景音乐 +// 裁剪背景音乐 - (void)clipMusicButtonEvent:(id)sender { CMTimeRange currentMusicTimeRange = CMTimeRangeMake(CMTimeMake([self.backgroundAudioSettings[PLSStartTimeKey] floatValue] * 1000, 1000), CMTimeMake([self.backgroundAudioSettings[PLSDurationKey] floatValue] * 1000, 1000)); @@ -1741,28 +1554,7 @@ - (void)clipMusicButtonEvent:(id)sender { [clipAudioView showAtView:self.view]; } -#pragma mark - 裁剪背景音乐的回调 PLSClipAudioViewDelegate -// 裁剪背景音乐 -- (void)clipAudioView:(PLSClipAudioView *)clipAudioView musicTimeRangeChangedTo:(CMTimeRange)musicTimeRange { - self.backgroundAudioSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(musicTimeRange.start)]; - self.backgroundAudioSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(musicTimeRange.duration)]; - - // 从 CMTimeGetSeconds(musicTimeRange.start) 开始播放 - [self updateMusic:musicTimeRange volume:nil]; -} - -#pragma mark - 音量调节的回调 PLSAudioVolumeViewDelegate -// 调节视频和背景音乐的音量 -- (void)audioVolumeView:(PLSAudioVolumeView *)volumeView movieVolumeChangedTo:(CGFloat)movieVolume musicVolumeChangedTo:(CGFloat)musicVolume { - self.movieSettings[PLSVolumeKey] = [NSNumber numberWithFloat:movieVolume]; - self.backgroundAudioSettings[PLSVolumeKey] = [NSNumber numberWithFloat:musicVolume]; - - self.shortVideoEditor.volume = movieVolume; - - [self updateMusic:kCMTimeRangeZero volume:self.backgroundAudioSettings[PLSVolumeKey]]; -} - -#pragma mark - 音量调节 +// 音量调节 - (void)volumeChangeEvent:(id)sender { NSNumber *movieVolume = self.movieSettings[PLSVolumeKey]; NSNumber *musicVolume = self.backgroundAudioSettings[PLSVolumeKey]; @@ -1772,7 +1564,8 @@ - (void)volumeChangeEvent:(id)sender { [volumeView showAtView:self.view]; } -#pragma mark - 关闭原声 +// 关闭原声 + - (void)closeSoundButtonEvent:(UIButton *)button { button.selected = !button.selected; @@ -1784,7 +1577,7 @@ - (void)closeSoundButtonEvent:(UIButton *)button { self.movieSettings[PLSVolumeKey] = [NSNumber numberWithFloat:self.shortVideoEditor.volume]; } -#pragma mark - 旋转视频 +// 旋转视频 - (void)rotateVideoButtonEvent:(UIButton *)button { AVAsset *asset = self.movieSettings[PLSAssetKey]; if (![self checkMovieHasVideoTrack:asset]) { @@ -1799,6 +1592,7 @@ - (void)rotateVideoButtonEvent:(UIButton *)button { } #pragma mark - 添加文字、图片、涂鸦 + - (void)addTextButtonEvent:(UIButton *)button { self.playButton.selected = YES; @@ -1810,15 +1604,6 @@ - (void)addTextButtonEvent:(UIButton *)button { } } -- (void)addTuyaButtonEvent:(UIButton *)button { - button.selected = !button.selected; - if (button.selected) { - [self showDrawbar]; - } else { - [self hideDrawbar]; - } -} - - (void)addImageButtonEvent:(UIButton *)button { button.selected = !button.selected; if (button.selected) { @@ -1837,29 +1622,41 @@ - (void)addGIFImageButtonEvent:(UIButton *)button { } } +- (void)addTuyaButtonEvent:(UIButton *)button { + button.selected = !button.selected; + if (button.selected) { + [self showDrawbar]; + } else { + [self hideDrawbar]; + } +} + +#pragma mark - 所有 bar +// text bar show/hide - (void)showTextbar { - [self hideAllBottomViews]; [self.shortVideoEditor stopEditing]; self.playButton.selected = YES; - // 1. 创建贴纸 NSString *imgName = @"sticker_t_0"; UIImage *image = [UIImage imageNamed:imgName]; - PLSStickerView *stickerView = [[PLSStickerView alloc] initSubTextSticker:image]; - stickerView.delegate = self; - // 气泡字幕需要计算文字的输入范围,每个气泡的展示区域不一样 - [stickerView calcInputRectWithImgName:imgName]; + + CGRect frame = CGRectMake((self.stickerOverlayView.frame.size.width - image.size.width * 0.5) * 0.5, + (self.stickerOverlayView.frame.size.height - image.size.height * 0.5) * 0.5, + image.size.width * 0.5, + image.size.height * 0.5); + // 1. 创建贴纸 + PLSStickerView *stickerView = [[PLSStickerView alloc] initWithFrame:frame content:@"请输入文字!" font:[UIFont systemFontOfSize:13] color:[UIColor colorWithRed:100 green:149 blue:237 alpha:1]]; - _currentStickerView.select = NO; - stickerView.select = YES; - _currentStickerView = stickerView; + self.stickerOverlayView.currentSticker.isSelected = NO; + stickerView.isSelected = YES; + self.stickerOverlayView.currentSticker = stickerView; // 2. 添加至stickerOverlayView上 - [self.stickerOverlayView addSubview:stickerView]; + [self.stickerOverlayView addSticker:stickerView positionMode:PositionMode_All_Center]; // 3. 添加 timeLineItem 模型 PLSTimeLineItem *item =[[PLSTimeLineItem alloc] init]; @@ -1871,34 +1668,49 @@ - (void)showTextbar { [self.timelineView addTimelineItem:item]; [self.timelineView editTimelineItem:item]; - - stickerView.frame = CGRectMake((self.stickerOverlayView.frame.size.width - image.size.width * 0.5) * 0.5, - (self.stickerOverlayView.frame.size.height - image.size.height * 0.5) * 0.5, - image.size.width * 0.5, image.size.height * 0.5); - - UIPanGestureRecognizer *panGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:panGes]; - UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:tapGes]; - UIPinchGestureRecognizer *pinGes = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:pinGes]; - [stickerView.dragBtn addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(scaleAndRotateGestureRecognizerEvent:)]]; - - UITapGestureRecognizer *doubleTapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(startTextEditing:)]; - doubleTapGes.numberOfTapsRequired = 2; - [stickerView addGestureRecognizer:doubleTapGes]; } - (void)hideTextbar { } -- (void)startTextEditing:(UITapGestureRecognizer *)tapGes { - _currentStickerView = (PLSStickerView *)[tapGes view]; - _currentStickerView.select = YES; - [_currentStickerView becomeFirstResponder]; +// sticker bar show/hide +- (void)showStickerbar { + [self hideAllBottomViews]; + + if (!self.stickerBar) { + self.stickerBar = [[PLSStickerBar alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT - PLS_EditToolboxView_HEIGHT - 175 - [self bottomFixSpace], PLS_SCREEN_WIDTH, 175) resourcePath:self.stickerPath]; + self.stickerBar.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + self.stickerBar.delegate = self; + } + if (!self.stickerBar.superview) { + [self.view addSubview:self.stickerBar]; + } +} + +- (void)hideStickerbar { + [self.stickerBar removeFromSuperview]; +} + +// gif bar show/hide +- (void)showGIFBar { + [self hideAllBottomViews]; + + if (!self.gifStickerBar) { + self.gifStickerBar = [[PLSGifStickerBar alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT - PLS_EditToolboxView_HEIGHT - 175 - [self bottomFixSpace], PLS_SCREEN_WIDTH, 175) resourcePath:self.stickerPath]; + self.gifStickerBar.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + self.gifStickerBar.delegate = self; + } + if (!self.gifStickerBar.superview) { + [self.view addSubview:self.gifStickerBar]; + } +} + +- (void)hideGIFBar { + [self.gifStickerBar removeFromSuperview]; } +// draw bar show/hide - (void)showDrawbar { [self hideAllBottomViews]; @@ -1943,43 +1755,84 @@ - (void)hideDrawbar { _currnetDrawView.userInteractionEnabled = NO; } -- (void)showStickerbar { - - [self hideAllBottomViews]; +#pragma mark - 配音的回调 DubViewControllerDelegate - if (!self.stickerBar) { - self.stickerBar = [[PLSStickerBar alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT - PLS_EditToolboxView_HEIGHT - 175 - [self bottomFixSpace], PLS_SCREEN_WIDTH, 175) resourcePath:self.stickerPath]; - self.stickerBar.backgroundColor = PLS_RGBCOLOR(25, 24, 36); - self.stickerBar.delegate = self; - } - if(!self.stickerBar.superview) { - [self.view addSubview:self.stickerBar]; - } +- (void)didOutputAsset:(AVAsset *)asset { + NSLog(@"保存配音后的回调"); + + self.movieSettings[PLSAssetKey] = asset; + self.movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f]; + self.movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(asset.duration)]; + + CMTime start = CMTimeMake([self.movieSettings[PLSStartTimeKey] floatValue] * 1000, 1000); + CMTime duration = CMTimeMake([self.movieSettings[PLSDurationKey] floatValue] * 1000, 1000); + self.shortVideoEditor.timeRange = CMTimeRangeMake(start, duration); + [self.shortVideoEditor replaceCurrentAssetWithAsset:self.movieSettings[PLSAssetKey]]; + [self.shortVideoEditor startEditing]; + self.playButton.selected = NO; } -- (void)hideStickerbar { - [self.stickerBar removeFromSuperview]; +#pragma mark - 裁剪背景音乐的回调 PLSClipAudioViewDelegate + +// 裁剪背景音乐 +- (void)clipAudioView:(PLSClipAudioView *)clipAudioView musicTimeRangeChangedTo:(CMTimeRange)musicTimeRange { + self.backgroundAudioSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(musicTimeRange.start)]; + self.backgroundAudioSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(musicTimeRange.duration)]; + + // 从 CMTimeGetSeconds(musicTimeRange.start) 开始播放 + [self updateMusic:musicTimeRange volume:nil]; } -- (void)showGIFBar { - [self hideAllBottomViews]; +#pragma mark - 音量调节的回调 PLSAudioVolumeViewDelegate + +// 调节视频和背景音乐的音量 +- (void)audioVolumeView:(PLSAudioVolumeView *)volumeView movieVolumeChangedTo:(CGFloat)movieVolume musicVolumeChangedTo:(CGFloat)musicVolume { + self.movieSettings[PLSVolumeKey] = [NSNumber numberWithFloat:movieVolume]; + self.backgroundAudioSettings[PLSVolumeKey] = [NSNumber numberWithFloat:musicVolume]; - if (!self.gifStickerBar) { - self.gifStickerBar = [[PLSGifStickerBar alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT - PLS_EditToolboxView_HEIGHT - 175 - [self bottomFixSpace], PLS_SCREEN_WIDTH, 175) resourcePath:self.stickerPath]; - self.gifStickerBar.backgroundColor = PLS_RGBCOLOR(25, 24, 36); - self.gifStickerBar.delegate = self; - } - if(!self.gifStickerBar.superview) { - [self.view addSubview:self.gifStickerBar]; - } + self.shortVideoEditor.volume = movieVolume; + + [self updateMusic:kCMTimeRangeZero volume:self.backgroundAudioSettings[PLSVolumeKey]]; } -- (void)hideGIFBar { - [self.gifStickerBar removeFromSuperview]; +#pragma mark - 贴图蒙版的回调 PLSStickerOverlayViewDelegate + +- (void)stickerOverlayView:(PLSStickerOverlayView *)stickerOverlayView didClickClose:(PLSStickerView *)stickerView { + [self.stickerOverlayView cancelCurrentSticker]; +} + +- (void)stickerOverlayView:(PLSStickerOverlayView *)stickerOverlayView didRemovedSticker:(PLSStickerView *)sticker currentSticker:(PLSStickerView *)currentSticker { + PLSTimeLineItem *item = [self.timelineView getTimelineItemWithOjb:sticker]; + [self.timelineView removeTimelineItem:item]; +} + +- (void)stickerOverlayView:(PLSStickerOverlayView *)stickerOverlayView didTapSticker:(PLSStickerView *)sticker tap:(UITapGestureRecognizer *)tap { + [self.shortVideoEditor stopEditing]; + self.playButton.selected = YES; + + PLSStickerView *view = sticker; + [self.timelineView editTimelineComplete]; + PLSTimeLineItem *item = [self.timelineView getTimelineItemWithOjb:view]; + + if (view != self.stickerOverlayView.currentSticker) { + [self.timelineView editTimelineItem:item]; + + self.stickerOverlayView.currentSticker.isSelected = NO; + view.isSelected = YES; + self.stickerOverlayView.currentSticker = view; + }else{ + view.isSelected = !view.isSelected; + if (view.isSelected) { + [self.timelineView editTimelineItem:item]; + self.stickerOverlayView.currentSticker = view; + }else{ + self.stickerOverlayView.currentSticker = nil; + } + } } +#pragma mark - 时间线代理 PLSTimelineViewDelegate -#pragma mark - PLSTimelineViewDelegate 时间线代理 /** 回调拖动的item对象(在手势结束时发生) @@ -2013,6 +1866,7 @@ - (void)timelineCurrentTime:(CGFloat)time duration:(CGFloat)duration { } #pragma mark - PLSDrawBarDelegate + - (void)editorDrawViewDone:(PLSDrawBar *)editorDrawView { [self hideDrawbar]; _currnetDrawView.userInteractionEnabled = NO; @@ -2049,28 +1903,26 @@ - (void)editorDrawView:(PLSDrawBar *)editorDrawView addDrawModel:(PLSDrawModel * _currnetDrawView.drawModel = model; } -#pragma mark - PLSStickerViewDelegate -- (void)stickerViewClose:(PLSStickerView *)stickerView { - PLSTimeLineItem *item = [self.timelineView getTimelineItemWithOjb:stickerView]; - [self.timelineView removeTimelineItem:item]; -} - #pragma mark - PLSStickerBarDelegate + - (void)stickerBar:(PLSStickerBar *)stickerBar didSelectImage:(NSURL *)url { [self.shortVideoEditor stopEditing]; self.playButton.selected = YES; - // 1. 创建贴纸 - PLSStickerView *stickerView = [[PLSStickerView alloc] initImageSticker:url]; UIImage *image = [UIImage imageWithContentsOfFile:url.path]; - stickerView.delegate = self; + CGRect frame = CGRectMake((self.stickerOverlayView.frame.size.width - image.size.width * 0.5) * 0.5, + (self.stickerOverlayView.frame.size.height - image.size.height * 0.5) * 0.5, + image.size.width * 0.5, + image.size.height * 0.5); + // 1. 创建贴纸 + PLSStickerView *stickerView = [[PLSStickerView alloc] initWithFrame:frame stickerType:StickerType_Image stickerURL:url]; - _currentStickerView.select = NO; - stickerView.select = YES; - _currentStickerView = stickerView; + self.stickerOverlayView.currentSticker.isSelected = NO; + stickerView.isSelected = YES; + self.stickerOverlayView.currentSticker = stickerView; // 2. 添加至stickerOverlayView上 - [self.stickerOverlayView addSubview:stickerView]; + [self.stickerOverlayView addSticker:stickerView positionMode:PositionMode_All_Center]; // 3. 添加 timeLineItem 模型 PLSTimeLineItem *item = [[PLSTimeLineItem alloc] init]; @@ -2082,35 +1934,27 @@ - (void)stickerBar:(PLSStickerBar *)stickerBar didSelectImage:(NSURL *)url { [self.timelineView addTimelineItem:item]; [self.timelineView editTimelineItem:item]; - - stickerView.frame = CGRectMake((self.stickerOverlayView.frame.size.width - image.size.width * 0.5) * 0.5, - (self.stickerOverlayView.frame.size.height - image.size.height * 0.5) * 0.5, - image.size.width * 0.5, - image.size.height * 0.5); - - UIPanGestureRecognizer *panGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:panGes]; - UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:tapGes]; - UIPinchGestureRecognizer *pinGes = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:pinGes]; - [stickerView.dragBtn addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(scaleAndRotateGestureRecognizerEvent:)]]; } - (void)gifStickerBar:(PLSGifStickerBar *)stickerBar didSelectImage:(NSURL *)url { [self.shortVideoEditor stopEditing]; self.playButton.selected = YES; + UIImage *image = [UIImage imageWithContentsOfFile:url.path]; + CGRect frame = CGRectMake((self.stickerOverlayView.frame.size.width - image.size.width * 0.5) * 0.5, + (self.stickerOverlayView.frame.size.height - image.size.height * 0.5) * 0.5, + image.size.width * 0.5, + image.size.height * 0.5); // 1. 创建贴纸 - PLSStickerView *stickerView = [[PLSStickerView alloc] initGifSticker:url]; - stickerView.delegate = self; + PLSStickerView *stickerView = [[PLSStickerView alloc] initWithFrame:frame stickerType:StickerType_Gif stickerURL:url]; + stickerView.stickerURL = url; - _currentStickerView.select = NO; - stickerView.select = YES; - _currentStickerView = stickerView; + self.stickerOverlayView.currentSticker.isSelected = NO; + stickerView.isSelected = YES; + self.stickerOverlayView.currentSticker = stickerView; // 2. 添加至stickerOverlayView上 - [self.stickerOverlayView addSubview:stickerView]; + [self.stickerOverlayView addSticker:stickerView positionMode:PositionMode_All_Center]; // 3. 添加 timeLineItem 模型 PLSTimeLineItem *item = [[PLSTimeLineItem alloc] init]; @@ -2125,149 +1969,10 @@ - (void)gifStickerBar:(PLSGifStickerBar *)stickerBar didSelectImage:(NSURL *)url [self.timelineView addTimelineItem:item]; [self.timelineView editTimelineItem:item]; - - UIImage *image = [UIImage imageWithContentsOfFile:url.path]; - stickerView.frame = CGRectMake((self.stickerOverlayView.frame.size.width - image.size.width * 0.5) * 0.5, - (self.stickerOverlayView.frame.size.height - image.size.height * 0.5) * 0.5, - image.size.width * 0.5, - image.size.height * 0.5); - - UIPanGestureRecognizer *panGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:panGes]; - UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:tapGes]; - UIPinchGestureRecognizer *pinGes = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureRecognizerEvent:)]; - [stickerView addGestureRecognizer:pinGes]; - [stickerView.dragBtn addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(scaleAndRotateGestureRecognizerEvent:)]]; -} - -- (void)moveGestureRecognizerEvent:(UIPanGestureRecognizer *)panGes { - if ([[panGes view] isKindOfClass:[PLSStickerView class]]){ - CGPoint loc = [panGes locationInView:self.view]; - PLSStickerView *view = (PLSStickerView *)[panGes view]; - if (_currentStickerView.select) { - if ([_currentStickerView pointInside:[_currentStickerView convertPoint:loc fromView:self.view] withEvent:nil]){ - view = _currentStickerView; - } - } - if (!view.select) { - return; - } - if (panGes.state == UIGestureRecognizerStateBegan) { - _loc_in = [panGes locationInView:self.view]; - _ori_center = view.center; - } - - CGFloat x; - CGFloat y; - x = _ori_center.x + (loc.x - _loc_in.x); - - y = _ori_center.y + (loc.y - _loc_in.y); - - dispatch_async(dispatch_get_main_queue(), ^{ - [UIView animateWithDuration:0 animations:^{ - view.center = CGPointMake(x, y); - }]; - }); - } -} - -- (void)tapGestureRecognizerEvent:(UITapGestureRecognizer *)tapGes { - if ([[tapGes view] isKindOfClass:[PLSStickerView class]]){ - [self.shortVideoEditor stopEditing]; - self.playButton.selected = YES; - - PLSStickerView *view = (PLSStickerView *)[tapGes view]; - [self.timelineView editTimelineComplete]; - PLSTimeLineItem *item = [self.timelineView getTimelineItemWithOjb:view]; - - if (view != _currentStickerView) { - [self.timelineView editTimelineItem:item]; - - _currentStickerView.select = NO; - view.select = YES; - _currentStickerView = view; - }else{ - view.select = !view.select; - if (view.select) { - [self.timelineView editTimelineItem:item]; - _currentStickerView = view; - }else{ - _currentStickerView = nil; - } - } - } -} - -- (void)pinchGestureRecognizerEvent:(UIPinchGestureRecognizer *)pinGes { - if ([[pinGes view] isKindOfClass:[PLSStickerView class]]){ - PLSStickerView *view = (PLSStickerView *)[pinGes view]; - - if (pinGes.state ==UIGestureRecognizerStateBegan) { - view.oriTransform = view.transform; - } - - if (pinGes.state ==UIGestureRecognizerStateChanged) { - _curScale = pinGes.scale; - CGAffineTransform tr = CGAffineTransformScale(view.oriTransform, pinGes.scale, pinGes.scale); - - view.transform = tr; - } - - // 当手指离开屏幕时,将lastscale设置为1.0 - if ((pinGes.state == UIGestureRecognizerStateEnded) || (pinGes.state == UIGestureRecognizerStateCancelled)) { - view.oriScale = view.oriScale * _curScale; - pinGes.scale = 1; - } - } -} - -- (void)scaleAndRotateGestureRecognizerEvent:(UIPanGestureRecognizer *)gesture { - if (_currentStickerView.isSelected) { - CGPoint curPoint = [gesture locationInView:self.view]; - if (gesture.state == UIGestureRecognizerStateBegan) { - _loc_in = [gesture locationInView:self.view]; - } - - if (gesture.state == UIGestureRecognizerStateBegan) { - _currentStickerView.oriTransform = _currentStickerView.transform; - } - - // 计算缩放 - CGFloat preDistance = [self getDistance:_loc_in withPointB:_currentStickerView.center]; - CGFloat curDistance = [self getDistance:curPoint withPointB:_currentStickerView.center]; - CGFloat scale = curDistance / preDistance; - // 计算弧度 - CGFloat preRadius = [self getRadius:_currentStickerView.center withPointB:_loc_in]; - CGFloat curRadius = [self getRadius:_currentStickerView.center withPointB:curPoint]; - CGFloat radius = curRadius - preRadius; - radius = - radius; - CGAffineTransform transform = CGAffineTransformScale(_currentStickerView.oriTransform, scale, scale); - _currentStickerView.transform = CGAffineTransformRotate(transform, radius); - - if (gesture.state == UIGestureRecognizerStateEnded || - gesture.state == UIGestureRecognizerStateCancelled) { - _currentStickerView.oriScale = scale * _currentStickerView.oriScale; - } - } -} - -// 距离 -- (CGFloat)getDistance:(CGPoint)pointA withPointB:(CGPoint)pointB { - CGFloat x = pointA.x - pointB.x; - CGFloat y = pointA.y - pointB.y; - - return sqrt(x*x + y*y); -} - -// 角度 -- (CGFloat)getRadius:(CGPoint)pointA withPointB:(CGPoint)pointB { - CGFloat x = pointA.x - pointB.x; - CGFloat y = pointA.y - pointB.y; - return atan2(x, y); } #pragma mark - 视频列表 + - (void)videoListButtonEvent:(UIButton *)button { button.selected = !button.selected; if (button.selected) { @@ -2278,6 +1983,7 @@ - (void)videoListButtonEvent:(UIButton *)button { } #pragma mark - 视频倍速 + - (void)videoSpeedButtonEvent:(UIButton *)button { [self showSourceCollectionView]; @@ -2289,6 +1995,7 @@ - (void)videoSpeedButtonEvent:(UIButton *)button { } #pragma mark - 视频倍速处理的响应事件 + - (void)videoSpeedSeletor:(NSInteger)titleIndex { self.titleIndex = titleIndex; PLSVideoRecoderRateType rateType = PLSVideoRecoderRateNormal; @@ -2381,73 +2088,61 @@ - (void)videoSpeedSeletor:(NSInteger)titleIndex { self.playButton.selected = NO; } -/// 根据速率配置相应倍速后的视频时长 -- (CGFloat)getRateNumberWithRateType:(PLSVideoRecoderRateType)rateType { - CGFloat scaleFloat = 1.0; - switch (rateType) { - case PLSVideoRecoderRateNormal: - scaleFloat = 1.0; - break; - case PLSVideoRecoderRateSlow: - scaleFloat = 1.5; - break; - case PLSVideoRecoderRateTopSlow: - scaleFloat = 2.0; - break; - case PLSVideoRecoderRateFast: - scaleFloat = 0.666667; - break; - case PLSVideoRecoderRateTopFast: - scaleFloat = 0.5; - break; - default: - break; - } - return scaleFloat; -} - -- (UIImage *)convertViewToImage:(UIView *)view { - CGSize size = view.bounds.size; - UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); - [view.layer renderInContext:UIGraphicsGetCurrentContext()]; - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} +#pragma mark - 进入 Gif 制作页面 + +- (void)joinGifFormatViewController { + AVAsset *asset = self.movieSettings[PLSAssetKey]; + + if (![self checkMovieHasVideoTrack:asset]) { + NSString *errorInfo = @"Error: movie has no videoTrack"; + NSLog(@"%s, %@", __func__, errorInfo); + AlertViewShow(errorInfo); + return; + } + + GifFormatViewController *gifFormatViewController = [[GifFormatViewController alloc] init]; + gifFormatViewController.asset = asset; + gifFormatViewController.videoURL = self.movieSettings[PLSURLKey]; + gifFormatViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:gifFormatViewController animated:YES completion:nil]; +} + +#pragma mark - 返回 -#pragma mark - 返回 - (void)backButtonClick { [self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - 下一步 + - (void)nextButtonClick { [self.shortVideoEditor stopEditing]; self.playButton.selected = YES; [self loadActivityIndicatorView]; - // 贴纸信息 [self.stickerSettingsArray removeAllObjects]; - // 涂鸦 - if (_currnetDrawView) { - float duration = 0; - for (NSURL *url in self.filesURLArray) { - duration += [self getFileDuration:url]; + // 涂鸦 + if (_currnetDrawView) { + float duration = 0; + for (NSURL *url in self.filesURLArray) { + duration += [self getFileDuration:url]; + } + + NSLog(@"duration - %f", duration); + + NSMutableDictionary *stickerSettings = [[NSMutableDictionary alloc] init]; + stickerSettings[PLSSizeKey] = [NSValue valueWithCGSize:_currnetDrawView.bounds.size]; + stickerSettings[PLSPointKey] = [NSValue valueWithCGPoint:CGPointZero]; + stickerSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(kCMTimeZero)]; + stickerSettings[PLSDurationKey] = [NSNumber numberWithFloat:duration]; + stickerSettings[PLSVideoPreviewSizeKey] = [NSValue valueWithCGSize:self.stickerOverlayView.frame.size]; + stickerSettings[PLSVideoOutputSizeKey] = [NSValue valueWithCGSize:self.videoSize]; + stickerSettings[PLSStickerKey] = [self convertViewToImage:_currnetDrawView]; + [self.stickerSettingsArray addObject:stickerSettings]; } - NSMutableDictionary *stickerSettings = [[NSMutableDictionary alloc] init]; - stickerSettings[PLSSizeKey] = [NSValue valueWithCGSize:_currnetDrawView.bounds.size]; - stickerSettings[PLSPointKey] = [NSValue valueWithCGPoint:CGPointZero]; - stickerSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(kCMTimeZero)]; - stickerSettings[PLSDurationKey] = [NSNumber numberWithFloat:duration]; - stickerSettings[PLSVideoPreviewSizeKey] = [NSValue valueWithCGSize:self.stickerOverlayView.frame.size]; - stickerSettings[PLSVideoOutputSizeKey] = [NSValue valueWithCGSize:self.videoSize]; - stickerSettings[PLSStickerKey] = [self convertViewToImage:_currnetDrawView]; - [self.stickerSettingsArray addObject:stickerSettings]; - } - if ([self.timelineView getAllAddedItems].count != 0) { for (int i = 0; i < [self.timelineView getAllAddedItems].count; i++) { PLSTimeLineItem *item = [self.timelineView getAllAddedItems][i]; @@ -2474,8 +2169,7 @@ - (void)nextButtonClick { stickerSettings[PLSVideoPreviewSizeKey] = [NSValue valueWithCGSize:self.stickerOverlayView.frame.size]; stickerSettings[PLSVideoOutputSizeKey] = [NSValue valueWithCGSize:self.videoSize]; - if (StickerType_GIFAnimation == stickerView.type) { - + if (StickerType_Gif == stickerView.stickerType) { // 如果贴纸是 GIF 类型,PLSStickerKey 的 value 必须是下列三种中的某一种: int type = arc4random() % 3; if (0 == type) { @@ -2496,7 +2190,7 @@ - (void)nextButtonClick { stickerSettings[PLSStickerKey] = stickerView; #else // ===== 新的静态贴纸添加方式,v2.1.0 之后生效,建议所有用户换成新的添加贴纸方式 ====== - if (StickerType_Sticker == stickerView.type) { + if (StickerType_Image == stickerView.stickerType) { int type = arc4random() % 4; if (0 == type) { @@ -2508,12 +2202,12 @@ - (void)nextButtonClick { } else if (2 == type) { // value = image data // 如果贴纸含 alpha 通道,使用 UIImageJPEGRepresentation(stickerView.image, 1) 得到的是没有 alpha 的图片,建议使用 UIImagePNGRepresentation(stickerView.image) 来获取 data - stickerSettings[PLSStickerKey] = UIImagePNGRepresentation(stickerView.image); + stickerSettings[PLSStickerKey] = UIImagePNGRepresentation(stickerView.stickerImage); } else { // value = image - stickerSettings[PLSStickerKey] = stickerView.image; + stickerSettings[PLSStickerKey] = stickerView.stickerImage; } - } else if (StickerType_SubTitle == stickerView.type) { + } else if (StickerType_Text == stickerView.stickerType) { // 文字 stickerView.hidden = NO; stickerSettings[PLSStickerKey] = [self convertViewToImage:stickerView]; @@ -2557,61 +2251,68 @@ - (void)nextButtonClick { } __weak typeof(self) weakSelf = self; - [exportSession setCompletionBlock:^(NSURL *url) { - NSLog(@"Asset Export Completed"); + + [exportSession setCompletionBlock:^(NSURL *url) { + NSLog(@"Asset Export Completed"); + + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf joinNextViewController:url]; + }); + }]; - dispatch_async(dispatch_get_main_queue(), ^{ - [weakSelf joinNextViewController:url]; - }); - }]; - - [exportSession setFailureBlock:^(NSError *error) { - NSLog(@"Asset Export Failed: %@", error); + [exportSession setFailureBlock:^(NSError *error) { + NSLog(@"Asset Export Failed: %@", error); + + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf removeActivityIndicatorView]; + AlertViewShow(error); + }); + }]; - dispatch_async(dispatch_get_main_queue(), ^{ - [weakSelf removeActivityIndicatorView]; - AlertViewShow(error); - }); - }]; - - [exportSession setProcessingBlock:^(float progress) { - // 更新进度 UI - NSLog(@"Asset Export Progress: %f", progress); - dispatch_async(dispatch_get_main_queue(), ^{ - weakSelf.progressLabel.text = [NSString stringWithFormat:@"%d%%", (int)(progress * 100)]; - }); - }]; - - [exportSession exportAsynchronously]; -} - -#pragma mark - 进入 Gif 制作页面 -- (void)joinGifFormatViewController { - AVAsset *asset = self.movieSettings[PLSAssetKey]; - - if (![self checkMovieHasVideoTrack:asset]) { - NSString *errorInfo = @"Error: movie has no videoTrack"; - NSLog(@"%s, %@", __func__, errorInfo); - AlertViewShow(errorInfo); - return; - } - - GifFormatViewController *gifFormatViewController = [[GifFormatViewController alloc] init]; - gifFormatViewController.asset = asset; - gifFormatViewController.videoURL = self.movieSettings[PLSURLKey]; - [self presentViewController:gifFormatViewController animated:YES completion:nil]; + [exportSession setProcessingBlock:^(float progress) { + // 更新进度 UI + NSLog(@"Asset Export Progress: %f", progress); + dispatch_async(dispatch_get_main_queue(), ^{ + weakSelf.progressLabel.text = [NSString stringWithFormat:@"%d%%", (int)(progress * 50)]; + }); + }]; + + [exportSession exportAsynchronously]; } #pragma mark - 完成视频合成跳转到下一页面 + - (void)joinNextViewController:(NSURL *)url { [self removeActivityIndicatorView]; PlayViewController *playViewController = [[PlayViewController alloc] init]; playViewController.url = url; + playViewController.modalPresentationStyle = UIModalPresentationFullScreen; + playViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:playViewController animated:YES completion:nil]; } +#pragma mark - UIActivityIndicatorView + +// 加载拼接视频的动画 +- (void)loadActivityIndicatorView { + if ([self.activityIndicatorView isAnimating]) { + [self.activityIndicatorView stopAnimating]; + [self.activityIndicatorView removeFromSuperview]; + } + + [self.view addSubview:self.activityIndicatorView]; + [self.activityIndicatorView startAnimating]; +} + +// 移除拼接视频的动画 +- (void)removeActivityIndicatorView { + [self.activityIndicatorView removeFromSuperview]; + [self.activityIndicatorView stopAnimating]; +} + #pragma mark - 程序的状态监听 + - (void)observerUIApplicationStatusForShortVideoEditor { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shortVideoEditorWillResignActiveEvent:) name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shortVideoEditorDidBecomeActiveEvent:) name:UIApplicationDidBecomeActiveNotification object:nil]; @@ -2634,36 +2335,60 @@ - (void)shortVideoEditorDidBecomeActiveEvent:(id)sender { self.playButton.selected = NO; } -- (void)printTimeRange:(CMTimeRange)timeRange { - printf("timeRange - "); - printf("start: "); - [self printTime:timeRange.start]; - printf(" , duration: "); - [self printTime:timeRange.duration]; - printf("\n"); -} +#pragma mark - 各类自定义方法 -- (void)printTime:(CMTime)time { - printf("{%lld / %d = %f}", time.value, time.timescale, time.value*1.0 / time.timescale); +// view 转 image +- (UIImage *)convertViewToImage:(UIView *)view { + CGSize size = view.bounds.size; + UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); + [view.layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; } -- (UIColor *)colorWithName:(NSString *)name { - UIColor *color = [UIColor greenColor]; +// 检查视频文件中是否含有视频轨道 +- (BOOL)checkMovieHasVideoTrack:(AVAsset *)asset { + BOOL hasVideoTrack = YES; - if ([name isEqualToString:@"古代韵味音效.m4r"]) { - color = PLS_RGBCOLOR_ALPHA(254, 160, 29, 0.9); - } else if ([name isEqualToString:@"清新鸟鸣音效.m4r"]) { - color = PLS_RGBCOLOR_ALPHA(251, 222, 56, 0.9); - } else if ([name isEqualToString:@"天使简约音效.m4r"]) { - color = PLS_RGBCOLOR_ALPHA(98, 182, 254, 0.9); - } else if ([name isEqualToString:@"跳动旋律音效.m4r"]) { - color = PLS_RGBCOLOR_ALPHA(220, 92, 179, 0.9); + NSArray *videoAssetTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; + + if (videoAssetTracks.count > 0) { + hasVideoTrack = YES; + } else { + hasVideoTrack = NO; } - return color; + return hasVideoTrack; +} + +// 获取视频/音频文件的总时长 +- (CGFloat)getFileDuration:(NSURL*)URL { + NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]; + AVURLAsset *asset = [AVURLAsset URLAssetWithURL:URL options:opts]; + + CMTime duration = asset.duration; + float durationSeconds = CMTimeGetSeconds(duration); + + return durationSeconds; } -#pragma mark - 自定义文件的名称和存储路径 +// 获取视频第一帧 +- (UIImage *)getVideoPreViewImage:(AVAsset *)asset { + AVAssetImageGenerator *assetGen = [[AVAssetImageGenerator alloc] initWithAsset:asset]; + + assetGen.maximumSize = CGSizeMake(150, 150); + assetGen.appliesPreferredTrackTransform = YES; + CMTime time = CMTimeMakeWithSeconds(0.0, 600); + NSError *error = nil; + CMTime actualTime; + CGImageRef image = [assetGen copyCGImageAtTime:time actualTime:&actualTime error:&error]; + UIImage *videoImage = [[UIImage alloc] initWithCGImage:image]; + CGImageRelease(image); + return videoImage; +} + +// 自定义文件的名称和存储路径 - (NSURL *)getFileURL:(NSString *)name { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [paths objectAtIndex:0]; @@ -2691,12 +2416,147 @@ - (NSURL *)getFileURL:(NSString *)name { return fileURL; } +- (void)printTimeRange:(CMTimeRange)timeRange { + printf("timeRange - "); + printf("start: "); + [self printTime:timeRange.start]; + printf(" , duration: "); + [self printTime:timeRange.duration]; + printf("\n"); +} + +- (void)printTime:(CMTime)time { + printf("{%lld / %d = %f}", time.value, time.timescale, time.value*1.0 / time.timescale); +} + +// 获取音乐文件的封面 +- (UIImage *)musicImageWithMusicURL:(NSURL *)url { + NSData *data = nil; + // 初始化媒体文件 + AVURLAsset *mp3Asset = [AVURLAsset URLAssetWithURL:url options:nil]; + // 读取文件中的数据 + for (NSString *format in [mp3Asset availableMetadataFormats]) { + for (AVMetadataItem *metadataItem in [mp3Asset metadataForFormat:format]) { + //artwork这个key对应的value里面存的就是封面缩略图,其它key可以取出其它摘要信息,例如title - 标题 + if ([metadataItem.commonKey isEqualToString:@"artwork"]) { + data = (NSData *)metadataItem.value; + + break; + } + } + } + if (!data) { + // 如果音乐没有图片,就返回默认图片 + return [UIImage imageNamed:@"music"]; + } + return [UIImage imageWithData:data]; +} + +// 更新 stickerOverlayView 的 frame +- (void)updateStickerOverlayView:(AVAsset *)asset { + // 视频分辨率 + CGSize vSize = asset.pls_videoSize; + + CGFloat x = 0; + CGFloat y = 0; + + CGFloat displayViewWidth = self.editDisplayView.frame.size.width; + CGFloat displayViewHeight = self.editDisplayView.frame.size.height; + + CGFloat width = displayViewWidth; + CGFloat height = displayViewHeight; + + if (vSize.width / vSize.height < displayViewWidth / displayViewHeight) { + width = vSize.width / vSize.height * displayViewHeight; + x = (displayViewWidth - width) * 0.5; + }else if (vSize.width / vSize.height > displayViewWidth / displayViewHeight){ + height = vSize.height / vSize.width * displayViewWidth; + y = (displayViewHeight - height) * 0.5; + } + self.stickerOverlayView.frame = CGRectMake(x, y, width, height); +} + +- (UIColor *)colorWithName:(NSString *)name { + UIColor *color = [UIColor greenColor]; + + if ([name isEqualToString:@"古代韵味音效.m4r"]) { + color = PLS_RGBCOLOR_ALPHA(254, 160, 29, 0.9); + } else if ([name isEqualToString:@"清新鸟鸣音效.m4r"]) { + color = PLS_RGBCOLOR_ALPHA(251, 222, 56, 0.9); + } else if ([name isEqualToString:@"天使简约音效.m4r"]) { + color = PLS_RGBCOLOR_ALPHA(98, 182, 254, 0.9); + } else if ([name isEqualToString:@"跳动旋律音效.m4r"]) { + color = PLS_RGBCOLOR_ALPHA(220, 92, 179, 0.9); + } + + return color; +} + +// 根据速率配置相应倍速后的视频时长 +- (CGFloat)getRateNumberWithRateType:(PLSVideoRecoderRateType)rateType { + CGFloat scaleFloat = 1.0; + switch (rateType) { + case PLSVideoRecoderRateNormal: + scaleFloat = 1.0; + break; + case PLSVideoRecoderRateSlow: + scaleFloat = 1.5; + break; + case PLSVideoRecoderRateTopSlow: + scaleFloat = 2.0; + break; + case PLSVideoRecoderRateFast: + scaleFloat = 0.666667; + break; + case PLSVideoRecoderRateTopFast: + scaleFloat = 0.5; + break; + default: + break; + } + return scaleFloat; +} + +// 初始化 button +- (UIButton *)toolBoxButtonWithSelector:(SEL)selector + startX:(CGFloat)startX + title:(NSString*)buttonTitle { + CGFloat height = 50; + UIButton *button = [UIButton buttonWithType:(UIButtonTypeCustom)]; + [button setTitle:buttonTitle forState:UIControlStateNormal]; + [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + button.titleLabel.font = [UIFont systemFontOfSize:16]; + [button sizeToFit]; + button.frame = CGRectMake(startX, 0, button.bounds.size.width, height); + [button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside]; + + [self.buttonScrollView addSubview:button]; + + return button; +} + +//类型识别:将 NSNull类型转化成 nil +- (id)checkNSNullType:(id)object { + if([object isKindOfClass:[NSNull class]]) { + return nil; + } + else { + return object; + } +} + +- (CGFloat)bottomFixSpace { + return iPhoneX_SERIES ? 30 : 0; +} + #pragma mark - 隐藏状态栏 + - (BOOL)prefersStatusBarHidden { return YES; } #pragma mark - dealloc + - (void)dealloc { self.shortVideoEditor.delegate = nil; self.shortVideoEditor = nil; diff --git a/Example/PLShortVideoKitDemo/GifFormatViewController.m b/Example/PLShortVideoKitDemo/GifFormatViewController.m index 7d0040ba..5ad9be1d 100644 --- a/Example/PLShortVideoKitDemo/GifFormatViewController.m +++ b/Example/PLShortVideoKitDemo/GifFormatViewController.m @@ -12,11 +12,7 @@ #import #import "PlayViewController.h" - -#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 GifFormatViewController () @@ -160,6 +156,7 @@ - (void)joinNextViewControllerWithGifUrl:(NSURL *)url imagesArray:(NSArray *)ima PlayViewController *playViewController = [[PlayViewController alloc]init]; playViewController.actionType = PLSActionTypeGif; playViewController.url = url; + playViewController.modalPresentationStyle = UIModalPresentationFullScreen; [obj presentViewController:playViewController animated:YES completion:nil]; } diff --git a/Example/PLShortVideoKitDemo/H265MovieViewController.m b/Example/PLShortVideoKitDemo/H265MovieViewController.m index 6390f29c..8e8add47 100644 --- a/Example/PLShortVideoKitDemo/H265MovieViewController.m +++ b/Example/PLShortVideoKitDemo/H265MovieViewController.m @@ -9,8 +9,6 @@ #import "H265MovieViewController.h" #import "MovieTransCodeViewController.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 () @@ -31,8 +29,17 @@ - (void)viewDidLoad { // 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.navigationItem.title = @"H.265"; + self.navigationController.navigationBar.barTintColor = PLS_RGBCOLOR(65, 154, 208); + [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]; + + UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [backButton setImage:[UIImage imageNamed:@"get_back"] forState:UIControlStateNormal]; + backButton.frame = CGRectMake(0, 0, 26, 26); + backButton.imageEdgeInsets = UIEdgeInsetsMake(8, -6, 8, 20); + [backButton addTarget:self action:@selector(clickBackItem) forControlEvents:UIControlEventTouchUpInside]; + + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton]; [self loadH265Videos]; @@ -48,8 +55,8 @@ - (void)loadH265Videos { [_h265VideoArray addObjectsFromArray:[bundle pathsForResourcesOfType:@"mov" inDirectory:subpath]]; } -- (void)clickBackItem:(UIBarButtonItem *)item { - [self dismissViewControllerAnimated:YES completion:nil]; +- (void)clickBackItem { + [self.navigationController popViewControllerAnimated:YES]; } - (void)didReceiveMemoryWarning { @@ -91,6 +98,7 @@ - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)butto // 转码 MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; transCodeViewController.url = url; + transCodeViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:transCodeViewController animated:YES completion:nil]; } diff --git a/Example/PLShortVideoKitDemo/ImageRotateViewController.m b/Example/PLShortVideoKitDemo/ImageRotateViewController.m index 1f097d89..b5779ff9 100644 --- a/Example/PLShortVideoKitDemo/ImageRotateViewController.m +++ b/Example/PLShortVideoKitDemo/ImageRotateViewController.m @@ -120,7 +120,7 @@ - (void)clickFinishButton:(UIButton *)button { editViewController.filesURLArray = [self.recorder getAllRecordingFiles]; editViewController.settings = outputSettings; - + editViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:editViewController animated:YES completion:nil]; } diff --git a/Example/PLShortVideoKitDemo/ImageVideoMixViewController.m b/Example/PLShortVideoKitDemo/ImageVideoMixViewController.m index fd2dab02..f0d4ef04 100644 --- a/Example/PLShortVideoKitDemo/ImageVideoMixViewController.m +++ b/Example/PLShortVideoKitDemo/ImageVideoMixViewController.m @@ -212,6 +212,7 @@ - (void)nextButtonClick:(UIButton *)sender { EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; videoEditViewController.filesURLArray = @[url]; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [weakSelf presentViewController:videoEditViewController animated:YES completion:nil]; }]; diff --git a/Example/PLShortVideoKitDemo/Info.plist b/Example/PLShortVideoKitDemo/Info.plist index 74f51fd0..b8b9ba93 100644 --- a/Example/PLShortVideoKitDemo/Info.plist +++ b/Example/PLShortVideoKitDemo/Info.plist @@ -15,9 +15,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.2.0 + $(MARKETING_VERSION) CFBundleVersion - 2.2.0.git-2019-07-12-395e7f2 + $(MARKETING_VERSION).git-2019-07-25-f93b75a Fabric APIKey @@ -66,5 +66,7 @@ UIInterfaceOrientationPortrait + UIViewControllerBasedStatusBarAppearance + diff --git a/Example/PLShortVideoKitDemo/MatterImportViewController.h b/Example/PLShortVideoKitDemo/MatterImportViewController.h new file mode 100644 index 00000000..c6202baa --- /dev/null +++ b/Example/PLShortVideoKitDemo/MatterImportViewController.h @@ -0,0 +1,17 @@ +// +// MatterImportViewController.h +// PLShortVideoKitDemo +// +// Created by 冯文秀 on 2019/9/17. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MatterImportViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PLShortVideoKitDemo/MatterImportViewController.m b/Example/PLShortVideoKitDemo/MatterImportViewController.m new file mode 100644 index 00000000..a79930a6 --- /dev/null +++ b/Example/PLShortVideoKitDemo/MatterImportViewController.m @@ -0,0 +1,142 @@ +// +// MatterImportViewController.m +// PLShortVideoKitDemo +// +// Created by 冯文秀 on 2019/9/17. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "MatterImportViewController.h" +#import "PLSListFunctionTableViewCell.h" + +#import "ImageVideoMixViewController.h" +#import "H265MovieViewController.h" +#import "MulitPhotoAlbumViewController.h" + +@interface MatterImportViewController () +< +UITableViewDelegate, +UITableViewDataSource +> +@property (nonatomic, strong) UITableView *matterTableView; +@property (nonatomic, strong) NSArray *matterArray; +@end + +@implementation MatterImportViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + + self.navigationItem.title = @"素材导入编辑"; + self.navigationController.navigationBar.barTintColor = PLS_RGBCOLOR(65, 154, 208); + [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]; + + UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [backButton setImage:[UIImage imageNamed:@"get_back"] forState:UIControlStateNormal]; + backButton.frame = CGRectMake(0, 0, 26, 26); + backButton.imageEdgeInsets = UIEdgeInsetsMake(2, 0, 2, 8); + [backButton addTarget:self action:@selector(getBack) forControlEvents:UIControlEventTouchUpInside]; + + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton]; + + self.view.backgroundColor = PLS_RGBCOLOR(242, 242, 242); + + self.matterArray = @[@"视频截取", @"视频分割", @"视频拼接", @"视频转码", @"图片视频混排", @"导入 H.265 视频"]; + + [self setupMatterTableView]; +} + +- (void)setupMatterTableView { + self.matterTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; + self.matterTableView.backgroundColor = PLS_RGBCOLOR(242, 242, 242); + self.matterTableView.delegate = self; + self.matterTableView.dataSource = self; + self.matterTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + [self.matterTableView registerClass:[PLSListFunctionTableViewCell class] forCellReuseIdentifier:@"matterCell"]; + [self.view addSubview:_matterTableView]; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return _matterArray.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + PLSListFunctionTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"matterCell"]; + cell.titlelabel.text = _matterArray[indexPath.row]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.row == 0) { + // 视频剪辑 + PhotoAlbumViewController *photoAlbumViewController = [[PhotoAlbumViewController alloc] init]; + photoAlbumViewController.mediaType = PHAssetMediaTypeVideo; + photoAlbumViewController.maxSelectCount = 1; + photoAlbumViewController.typeIndex = 0; + photoAlbumViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:photoAlbumViewController animated:YES completion:nil]; + } else if (indexPath.row == 1) { + // 视频分割 + MulitPhotoAlbumViewController *mulitPhotoAlbumViewController = [[MulitPhotoAlbumViewController alloc] init]; + mulitPhotoAlbumViewController.mediaType = PHAssetMediaTypeVideo; + mulitPhotoAlbumViewController.maxSelectCount = 10; + mulitPhotoAlbumViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:mulitPhotoAlbumViewController animated:YES completion:nil]; + + } else if (indexPath.row == 2) { + // 视频拼接 + PhotoAlbumViewController *photoAlbumViewController = [[PhotoAlbumViewController alloc] init]; + photoAlbumViewController.mediaType = PHAssetMediaTypeVideo; + photoAlbumViewController.maxSelectCount = 10; + photoAlbumViewController.typeIndex = 2; + photoAlbumViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:photoAlbumViewController animated:YES completion:nil]; + + } else if (indexPath.row == 3) { + // 视频转码 + PhotoAlbumViewController *photoAlbumViewController = [[PhotoAlbumViewController alloc] init]; + photoAlbumViewController.mediaType = PHAssetMediaTypeVideo; + photoAlbumViewController.maxSelectCount = 1; + photoAlbumViewController.typeIndex = 1; + photoAlbumViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:photoAlbumViewController animated:YES completion:nil]; + + } else if (indexPath.row == 4) { + // 图片视频混排 + ImageVideoMixViewController *imageVideoMixViewController = [[ImageVideoMixViewController alloc] init]; + imageVideoMixViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:imageVideoMixViewController animated:YES completion:nil]; + + } else if (indexPath.row == 5) { + // 导入 H.265 + H265MovieViewController *h265MovieViewController = [[H265MovieViewController alloc] init]; + [self.navigationController pushViewController:h265MovieViewController animated:YES]; + } + +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 58; +} + +- (void)getBack { + [self.navigationController popViewControllerAnimated:YES]; +} + +/* +#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/MixRecordViewController.h b/Example/PLShortVideoKitDemo/MixRecordViewController.h index 553f7f25..2ad4baae 100644 --- a/Example/PLShortVideoKitDemo/MixRecordViewController.h +++ b/Example/PLShortVideoKitDemo/MixRecordViewController.h @@ -8,9 +8,18 @@ #import +typedef enum : NSUInteger { + enumMixTypeLeftRight,// 左右分屏 + enumMixTypeUpdown, // 画中画,素材在上 + enumMixTypeDownup, // 画中画,素材在下 +} EnumMixType; + + @interface MixRecordViewController : UIViewController // 合拍视频地址 @property (nonatomic, strong) NSURL *mixURL; +@property (nonatomic, assign) EnumMixType mixType; + @end diff --git a/Example/PLShortVideoKitDemo/MixRecordViewController.m b/Example/PLShortVideoKitDemo/MixRecordViewController.m index c55c7d4d..27b2f327 100644 --- a/Example/PLShortVideoKitDemo/MixRecordViewController.m +++ b/Example/PLShortVideoKitDemo/MixRecordViewController.m @@ -15,17 +15,8 @@ #import "PLSEditVideoCell.h" #import "PLSFilterGroup.h" -#define AlertViewShow(msg) [[[UIAlertView alloc] initWithTitle:@"warning" message:[NSString stringWithFormat:@"%@", msg] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil] show] - #define PLS_CLOSE_CONTROLLER_ALERTVIEW_TAG 10001 -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] -#define PLS_RGBACOLOR(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)] - #define PLS_BaseToolboxView_HEIGHT 64 -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) @interface MixRecordViewController () < @@ -64,7 +55,13 @@ @interface MixRecordViewController () // 展示所有滤镜的集合视图 @property (strong, nonatomic) UICollectionView *editVideoCollectionView; @property (strong, nonatomic) NSMutableArray *filtersArray; -@property (assign, nonatomic) NSInteger filterIndex; +// 切换滤镜的时候,为了更好的用户体验,添加以下属性来做切换动画 +@property (nonatomic, assign) BOOL isPanning; +@property (nonatomic, assign) BOOL isLeftToRight; +@property (nonatomic, assign) BOOL isNeedChangeFilter; +@property (nonatomic, weak) PLSFilter *leftFilter; +@property (nonatomic, weak) PLSFilter *rightFilter; +@property (nonatomic, assign) float leftPercent; @property (strong, nonatomic) UIButton *draftButton; @property (strong, nonatomic) NSURL *URL; @@ -140,16 +137,45 @@ - (void)viewWillDisappear:(BOOL)animated { - (void)setupvideoMixRecorder { + CGSize videoSize = CGSizeZero; + CGRect cameraFrame = CGRectZero; + CGRect sampleFrame = CGRectZero; + NSInteger cameraZIndex = 0; + NSInteger sampleZIndex = 0; + + if (enumMixTypeLeftRight == self.mixType) { + videoSize = CGSizeMake(1080, 960); + cameraFrame = CGRectMake(0, 0, 540, 960); + sampleFrame = CGRectMake(540, 0, 540, 960); + cameraZIndex = 0; + sampleZIndex = 1; + } else if (enumMixTypeUpdown == self.mixType) { + videoSize = CGSizeMake(720, 1280); + cameraFrame = CGRectMake(0, 0, 720, 1280); + sampleFrame = CGRectMake(50, 50, 240, 426); + cameraZIndex = 0; + sampleZIndex = 1; + } else { + videoSize = CGSizeMake(720, 1280); + sampleFrame = CGRectMake(0, 0, 720, 1280); + cameraFrame = CGRectMake(50, 50, 240, 426); + cameraZIndex = 1; + sampleZIndex = 0; + } + self.videoConfiguration = [PLSVideoMixConfiguration defaultConfiguration]; self.videoConfiguration.position = AVCaptureDevicePositionFront; self.videoConfiguration.sessionPreset = AVCaptureSessionPresetiFrame1280x720; - self.videoConfiguration.videoFrameRate = 25; - self.videoConfiguration.averageVideoBitRate = 1024*2000;//2.0M - self.videoConfiguration.videoSize = CGSizeMake(720, 640); - self.videoConfiguration.cameraVideoFrame = CGRectMake(0, 0, 360, 640); - self.videoConfiguration.sampleVideoFrame = CGRectMake(360, 0, 360, 640); + self.videoConfiguration.videoFrameRate = 30; + self.videoConfiguration.videoSize = videoSize; + self.videoConfiguration.averageVideoBitRate = 1024*4000; + self.videoConfiguration.cameraVideoFrame = cameraFrame; + self.videoConfiguration.sampleVideoFrame = sampleFrame; + self.videoConfiguration.camermZIndex = cameraZIndex; + self.videoConfiguration.sampleZIndex = sampleZIndex; self.videoConfiguration.videoOrientation = AVCaptureVideoOrientationPortrait; - self.videoConfiguration.previewMirrorFrontFacing = NO; + self.videoConfiguration.previewMirrorFrontFacing = YES; + self.videoConfiguration.streamMirrorFrontFacing = YES; self.audioConfiguration = [PLSAudioMixConfiguration defaultConfiguration]; self.audioConfiguration.sampleVolume = 0.5; @@ -166,6 +192,9 @@ - (void)setupvideoMixRecorder { self.videoMixRecorder.mergeVideoURL = self.mixURL; [self.videoMixRecorder setBeautifyModeOn:YES]; CGFloat height = PLS_SCREEN_WIDTH/2 * 640.0 / 360.0; + if (enumMixTypeLeftRight != self.mixType) { + height = PLS_SCREEN_WIDTH * 1280 / 720; + } self.videoMixRecorder.previewView.frame = CGRectMake(0, (PLS_SCREEN_HEIGHT - height)/2, PLS_SCREEN_WIDTH, height); [self.view addSubview:self.videoMixRecorder.previewView]; @@ -602,8 +631,15 @@ - (CVPixelBufferRef)videoMixRecorder:(PLSVideoMixRecorder *)recorder cameraSourc //此处可以做美颜/滤镜等处理 // 是否在录制时使用滤镜,默认是关闭的,NO if (self.isUseFilterWhenRecording) { - PLSFilter *filter = self.filterGroup.currentFilter; - pixelBuffer = [filter process:pixelBuffer]; + if (self.isPanning) { + pixelBuffer = [self.filterGroup processPixelBuffer:pixelBuffer + leftPercent:self.leftPercent + leftFilter:self.leftFilter + rightFilter:self.rightFilter]; + } else { + PLSFilter *filter = self.filterGroup.currentFilter; + pixelBuffer = [filter process:pixelBuffer]; + } } return pixelBuffer; @@ -721,6 +757,7 @@ - (void)playEvent:(AVAsset *)asset { EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; videoEditViewController.filesURLArray = filesURLArray; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:videoEditViewController animated:YES completion:nil]; } @@ -828,61 +865,122 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell } - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - // 滤镜 self.filterGroup.filterIndex = indexPath.row; } #pragma mark - 通过手势切换滤镜 - (void)setupGestureRecognizer { - UISwipeGestureRecognizer *recognizer; - // 添加右滑手势 - recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; - [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)]; - [self.view addGestureRecognizer:recognizer]; - // 添加左滑手势 - recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; - [recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)]; - [self.view addGestureRecognizer:recognizer]; - // 添加上滑手势 - recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; - [recognizer setDirection:(UISwipeGestureRecognizerDirectionUp)]; - [self.view addGestureRecognizer:recognizer]; - // 添加下滑手势 - recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; - [recognizer setDirection:(UISwipeGestureRecognizerDirectionDown)]; - [self.view addGestureRecognizer:recognizer]; + UIPanGestureRecognizer * panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleFilterPan:)]; + [self.view addGestureRecognizer:panGesture]; } // 添加手势的响应事件 -- (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer{ - if(recognizer.direction == UISwipeGestureRecognizerDirectionDown) { - NSLog(@"swipe down"); - self.filterIndex++; - self.filterIndex %= self.filterGroup.filtersInfo.count; - } - if(recognizer.direction == UISwipeGestureRecognizerDirectionUp) { - NSLog(@"swipe up"); - self.filterIndex--; - if (self.filterIndex < 0) { - self.filterIndex = self.filterGroup.filtersInfo.count - 1; +- (void)handleFilterPan:(UIPanGestureRecognizer *)gestureRecognizer { + + CGPoint transPoint = [gestureRecognizer translationInView:gestureRecognizer.view]; + CGPoint speed = [gestureRecognizer velocityInView:gestureRecognizer.view]; + + switch (gestureRecognizer.state) { + + case UIGestureRecognizerStateBegan: { + NSInteger index = 0; + if (speed.x > 0) { + self.isLeftToRight = YES; + index = self.filterGroup.filterIndex - 1; + } else { + index = self.filterGroup.filterIndex + 1; + self.isLeftToRight = NO; + } + + if (index < 0) { + index = self.filterGroup.filtersInfo.count - 1; + } else if (index >= self.filterGroup.filtersInfo.count) { + index = index - self.filterGroup.filtersInfo.count; + } + self.filterGroup.nextFilterIndex = index; + + if (self.isLeftToRight) { + self.leftFilter = self.filterGroup.nextFilter; + self.rightFilter = self.filterGroup.currentFilter; + self.leftPercent = 0.0; + } else { + self.leftFilter = self.filterGroup.currentFilter; + self.rightFilter = self.filterGroup.nextFilter; + self.leftPercent = 1.0; + } + self.isPanning = YES; + break; } - } - if(recognizer.direction == UISwipeGestureRecognizerDirectionLeft) { - NSLog(@"swipe left"); - self.filterIndex--; - if (self.filterIndex < 0) { - self.filterIndex = self.filterGroup.filtersInfo.count - 1; + case UIGestureRecognizerStateChanged: { + if (self.isLeftToRight) { + if (transPoint.x <= 0) { + transPoint.x = 0; + } + self.leftPercent = 2 * transPoint.x / gestureRecognizer.view.bounds.size.width; + self.isNeedChangeFilter = (self.leftPercent >= 0.5) || (speed.x > 500 ); + } else { + if (transPoint.x >= 0) { + transPoint.x = 0; + } + self.leftPercent = 1 - 2 * fabs(transPoint.x) / gestureRecognizer.view.bounds.size.width; + self.isNeedChangeFilter = (self.leftPercent <= 0.5) || (speed.x < -500); + } + break; } + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: { + + gestureRecognizer.enabled = NO; + __weak typeof(self) weakself = self; + + // 做一个滤镜过渡动画,优化用户体验 + dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC, 0.005 * NSEC_PER_SEC); + dispatch_source_set_event_handler(timer, ^{ + + if (!weakself.isPanning) return; + + float delta = 0.03; + if (weakself.isNeedChangeFilter) { + // apply filter change + if (weakself.isLeftToRight) { + weakself.leftPercent = MIN(1, weakself.leftPercent + delta); + } else { + weakself.leftPercent = MAX(0, weakself.leftPercent - delta); + } + } else { + // cancel filter change + if (weakself.isLeftToRight) { + weakself.leftPercent = MAX(0, weakself.leftPercent - delta); + } else { + weakself.leftPercent = MIN(1, weakself.leftPercent + delta); + } + } + + if (weakself.leftPercent < FLT_EPSILON || fabs(1.0 - weakself.leftPercent) < FLT_EPSILON) { + dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_source_cancel(timer); + dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_source_cancel(timer); + if (self.isNeedChangeFilter) { + self.filterGroup.filterIndex = self.filterGroup.nextFilterIndex; + } + self.isPanning = NO; + self.isNeedChangeFilter = NO; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + gestureRecognizer.enabled = YES; + }); + }); + }); + } + }); + dispatch_resume(timer); + break; + } + default: + break; } - if(recognizer.direction == UISwipeGestureRecognizerDirectionRight) { - NSLog(@"swipe right"); - self.filterIndex++; - self.filterIndex %= self.filterGroup.filtersInfo.count; - } - - // 滤镜 - self.filterGroup.filterIndex = self.filterIndex; } @end diff --git a/Example/PLShortVideoKitDemo/MoiveClipViewController.h b/Example/PLShortVideoKitDemo/MoiveClipViewController.h new file mode 100644 index 00000000..8ec3d72d --- /dev/null +++ b/Example/PLShortVideoKitDemo/MoiveClipViewController.h @@ -0,0 +1,18 @@ +// +// MoiveClipViewController.h +// PLShortVideoKitDemo +// +// Created by 冯文秀 on 2019/9/18. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MoiveClipViewController : UIViewController +@property (strong, nonatomic) NSURL *url; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PLShortVideoKitDemo/MoiveClipViewController.m b/Example/PLShortVideoKitDemo/MoiveClipViewController.m new file mode 100644 index 00000000..8ad4f3b5 --- /dev/null +++ b/Example/PLShortVideoKitDemo/MoiveClipViewController.m @@ -0,0 +1,314 @@ +// +// MoiveClipViewController.m +// PLShortVideoKitDemo +// +// Created by 冯文秀 on 2019/9/18. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "MoiveClipViewController.h" +#import "PLShortVideoKit/PLShortVideoKit.h" +#import "PLSClipMovieView.h" +#import +#import "EditViewController.h" + +#define PLS_BaseToolboxView_HEIGHT 64 + + +typedef enum : NSUInteger { + enumPanPositionTopLeft, + enumPanPositionTopRight, + enumPanPositionBottomLeft, + enumPanPositionBottomRight, + enumPanPositionCenter, +} EnumPanPosition; + +@interface MoiveClipViewController () +< +PLSClipMovieViewDelegate, +PLShortVideoEditorDelegate +> + +// 视图 +@property (strong, nonatomic) UIView *baseToolboxView; +@property (strong, nonatomic) UIActivityIndicatorView *activityIndicatorView; +@property (strong, nonatomic) UILabel *progressLabel; + +// 选取需要的视频段 +@property (strong, nonatomic) PLSClipMovieView *clipMovieView; + + +// 编辑 +@property (strong, nonatomic) PLShortVideoEditor *shortVideoEditor; +// 要编辑的视频的信息 +@property (strong, nonatomic) NSMutableDictionary *movieSettings; + +@property (strong, nonatomic) AVAsset *asset; +@end + +@implementation MoiveClipViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + + // -------------------------- + + self.view.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + + // -------------------------- + // 编辑类 + [self setupShortVideoEditor]; + + // 配置工具视图 + [self setupBaseToolboxView]; + + [self setupClipMovieView]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + [self observerUIApplicationStatusForShortVideoEditor]; + + [self.shortVideoEditor startEditing]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + [self removeObserverUIApplicationStatusForShortVideoEditor]; + + [self.shortVideoEditor stopEditing]; +} + +#pragma mark - 编辑类 +- (void)setupShortVideoEditor { + // 待编辑的原始视频素材 + self.movieSettings = [[NSMutableDictionary alloc] init]; + AVAsset *asset = [AVAsset assetWithURL:self.url]; + self.movieSettings[PLSURLKey] = self.url; + self.movieSettings[PLSAssetKey] = asset; + self.movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:0.f]; + self.movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:CMTimeGetSeconds(asset.duration)]; + self.movieSettings[PLSVolumeKey] = [NSNumber numberWithFloat:1.0f]; + + // 剪裁使用到 + self.asset = asset; + + // 视频编辑类 + self.shortVideoEditor = [[PLShortVideoEditor alloc] initWithAsset:asset videoSize:CGSizeZero]; + self.shortVideoEditor.delegate = self; + self.shortVideoEditor.loopEnabled = YES; + + // 要处理的视频的时间区域 + CMTime start = CMTimeMake([self.movieSettings[PLSStartTimeKey] floatValue] * 1000, 1000); + CMTime duration = CMTimeMake([self.movieSettings[PLSDurationKey] floatValue] * 1000, 1000); + self.shortVideoEditor.timeRange = CMTimeRangeMake(start, duration); + + // 视频的预览视图 + self.shortVideoEditor.previewView.frame = CGRectMake(0, PLS_BaseToolboxView_HEIGHT, PLS_SCREEN_WIDTH, PLS_SCREEN_HEIGHT - 64 - 145); + [self.view addSubview:self.shortVideoEditor.previewView]; +} + +#pragma mark -- 配置视图 +- (void)setupBaseToolboxView { + self.view.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + + self.baseToolboxView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, PLS_SCREEN_WIDTH, PLS_BaseToolboxView_HEIGHT)]; + self.baseToolboxView.backgroundColor = PLS_RGBCOLOR(25, 24, 36); + [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.frame = CGRectMake(0, 20, 80, 44); + 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]; + + // 标题 + UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 20, 100, 44)]; + if (iPhoneX_SERIES) { + titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 58); + } else { + titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 42); + } + titleLabel.text = @"剪辑"; + titleLabel.textAlignment = NSTextAlignmentCenter; + titleLabel.textColor = [UIColor grayColor]; + titleLabel.font = [UIFont systemFontOfSize:18]; + [self.baseToolboxView addSubview: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, 20, 80, 44); + 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]; +} + +- (void)setupClipMovieView { + CGFloat duration = [self getFileDuration:self.url]; + self.clipMovieView = [[PLSClipMovieView alloc] initWithMovieURL:self.url minDuration:2.0f maxDuration:duration]; + self.clipMovieView.delegate = self; + [self.view addSubview:self.clipMovieView]; + [self.clipMovieView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.mas_equalTo(0); + make.height.mas_equalTo(145); + }]; +} + +#pragma mark - PLSClipMovieView delegate +- (void)didStartDragView { + +} + +- (void)clipFrameView:(PLSClipMovieView *)clipFrameView didEndDragLeftView:(CMTime)leftTime rightView:(CMTime)rightTime { + CGFloat start = CMTimeGetSeconds(leftTime); + CGFloat end = CMTimeGetSeconds(rightTime); + CGFloat duration = end - start; + + self.movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:start]; + self.movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:duration]; + + self.shortVideoEditor.timeRange = CMTimeRangeMake(leftTime, CMTimeSubtract(rightTime, leftTime)); + [self.shortVideoEditor startEditing]; +} + +- (void)clipFrameView:(PLSClipMovieView *)clipFrameView isScrolling:(BOOL)scrolling { + self.view.userInteractionEnabled = !scrolling; +} + +// 检查视频文件中是否含有视频轨道 +- (BOOL)checkMovieHasVideoTrack:(AVAsset *)asset { + BOOL hasVideoTrack = YES; + + NSArray *videoAssetTracks = [asset tracksWithMediaType:AVMediaTypeVideo]; + + if (videoAssetTracks.count > 0) { + hasVideoTrack = YES; + } else { + hasVideoTrack = NO; + } + + return hasVideoTrack; +} + +#pragma mark -- UIButton 按钮响应事件 +#pragma mark -- 返回 +- (void)backButtonClick { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark -- 下一步 +- (void)nextButtonClick { + // 设置音视频、水印等编辑信息 + NSMutableDictionary *outputSettings = [[NSMutableDictionary alloc] init]; + outputSettings[PLSMovieSettingsKey] = self.movieSettings; + + EditViewController *videoEditViewController = [[EditViewController alloc] init]; + videoEditViewController.settings = outputSettings; + videoEditViewController.filesURLArray = @[_url]; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:videoEditViewController animated:YES completion:nil]; +} + +#pragma mark - 自定义文件的名称和存储路径 +- (NSURL *)getFileURL:(NSString *)name { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *path = [paths objectAtIndex:0]; + + path = [path stringByAppendingPathComponent:@"TestPath"]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + if(![fileManager fileExistsAtPath:path]) { + // 如果不存在,则说明是第一次运行这个程序,那么建立这个文件夹 + [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil]; + } + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"yyyyMMddHHmmss"; + NSString *nowTimeStr = [formatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:0]]; + + if (name != nil && ![name isEqualToString:@""]) { + nowTimeStr = name; + } + + NSString *fileName = [[path stringByAppendingPathComponent:nowTimeStr] stringByAppendingString:@".mp4"]; + + NSURL *fileURL = [NSURL fileURLWithPath:fileName]; + + return fileURL; +} + +#pragma mark -- 计算文件的大小,单位为 M +- (CGFloat)fileSize:(NSURL *)url { + return [[NSData dataWithContentsOfURL:url] length] / 1024.00 / 1024.00; +} + +#pragma mark -- 获取视频/音频文件的总时长 +- (CGFloat)getFileDuration:(NSURL*)URL { + NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]; + AVURLAsset *asset = [AVURLAsset URLAssetWithURL:URL options:opts]; + + CMTime duration = asset.duration; + float durationSeconds = CMTimeGetSeconds(duration); + + return durationSeconds; +} + +#pragma mark - 程序的状态监听 +- (void)observerUIApplicationStatusForShortVideoEditor { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shortVideoEditorWillResignActiveEvent:) name:UIApplicationWillResignActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shortVideoEditorDidBecomeActiveEvent:) name:UIApplicationDidBecomeActiveNotification object:nil]; +} + +- (void)removeObserverUIApplicationStatusForShortVideoEditor { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; +} + +- (void)shortVideoEditorWillResignActiveEvent:(id)sender { + NSLog(@"[self.shortVideoEditor UIApplicationWillResignActiveNotification]"); + [self.shortVideoEditor stopEditing]; +} + +- (void)shortVideoEditorDidBecomeActiveEvent:(id)sender { + NSLog(@"[self.shortVideoEditor UIApplicationDidBecomeActiveNotification]"); + [self.shortVideoEditor startEditing]; +} + +#pragma mark -- 隐藏状态栏 +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark -- dealloc +- (void)dealloc { + if ([self.activityIndicatorView isAnimating]) { + [self.activityIndicatorView stopAnimating]; + self.activityIndicatorView = nil; + } + + NSLog(@"dealloc: %@", [[self class] description]); +} + +@end diff --git a/Example/PLShortVideoKitDemo/MovieTransCodeViewController.m b/Example/PLShortVideoKitDemo/MovieTransCodeViewController.m index b648a2cb..3ee194d4 100644 --- a/Example/PLShortVideoKitDemo/MovieTransCodeViewController.m +++ b/Example/PLShortVideoKitDemo/MovieTransCodeViewController.m @@ -8,16 +8,11 @@ #import "MovieTransCodeViewController.h" #import "PLShortVideoKit/PLShortVideoKit.h" -#import "PLSClipMovieView.h" #import #import "PLSSelectionView.h" #import "EditViewController.h" -#define AlertViewShow(msg) [[[UIAlertView alloc] initWithTitle:@"warning" message:[NSString stringWithFormat:@"%@", msg] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil] show] -#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) typedef enum : NSUInteger { @@ -30,7 +25,6 @@ @interface MovieTransCodeViewController () < -PLSClipMovieViewDelegate, PLSSelectionViewDelegate, PLShortVideoEditorDelegate > @@ -40,9 +34,6 @@ @interface MovieTransCodeViewController () @property (strong, nonatomic) UIActivityIndicatorView *activityIndicatorView; @property (strong, nonatomic) UILabel *progressLabel; -// 选取需要的视频段 -@property (strong, nonatomic) PLSClipMovieView *clipMovieView; - // 选取转码质量 @property (strong, nonatomic) PLSSelectionView *selectionView; @@ -86,8 +77,6 @@ - (void)viewDidLoad { [self setupSelectionView]; - [self setupClipMovieView]; - [self setupScopeCutView]; } @@ -132,7 +121,7 @@ - (void)setupShortVideoEditor { self.shortVideoEditor.timeRange = CMTimeRangeMake(start, duration); // 视频的预览视图 - self.shortVideoEditor.previewView.frame = CGRectMake(0, PLS_BaseToolboxView_HEIGHT, PLS_SCREEN_WIDTH, PLS_SCREEN_WIDTH); + self.shortVideoEditor.previewView.frame = CGRectMake(0, PLS_BaseToolboxView_HEIGHT, PLS_SCREEN_WIDTH, PLS_SCREEN_WIDTH + 145); [self.view addSubview:self.shortVideoEditor.previewView]; } @@ -151,18 +140,18 @@ - (void)setupBaseToolboxView { [backButton setTitle:@"返回" forState:UIControlStateNormal]; [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [backButton setTitleColor:PLS_RGBCOLOR(141, 141, 142) forState:UIControlStateHighlighted]; - backButton.frame = CGRectMake(0, 0, 80, 64); + backButton.frame = CGRectMake(0, 20, 80, 44); 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]; // 标题 - UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 100, 64)]; + UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 20, 100, 44)]; if (iPhoneX_SERIES) { - titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 48); + titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 58); } else { - titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 32); + titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 42); } titleLabel.text = @"转码"; titleLabel.textAlignment = NSTextAlignmentCenter; @@ -177,7 +166,7 @@ - (void)setupBaseToolboxView { [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.frame = CGRectMake(PLS_SCREEN_WIDTH - 80, 20, 80, 44); nextButton.titleEdgeInsets = UIEdgeInsetsMake(0, -40, 0, 0); nextButton.imageEdgeInsets = UIEdgeInsetsMake(0, 50, 0, 0); nextButton.titleLabel.font = [UIFont systemFontOfSize:16]; @@ -201,9 +190,9 @@ - (void)setupBaseToolboxView { - (void)setupSelectionView { CGFloat rotateViewTopSpace; if (PLS_SCREEN_HEIGHT > 568) { - rotateViewTopSpace = PLS_BaseToolboxView_HEIGHT + PLS_SCREEN_WIDTH + 5; + rotateViewTopSpace = PLS_BaseToolboxView_HEIGHT + PLS_SCREEN_WIDTH + 5 + 145; } else{ - rotateViewTopSpace = PLS_BaseToolboxView_HEIGHT + PLS_SCREEN_WIDTH; + rotateViewTopSpace = PLS_BaseToolboxView_HEIGHT + PLS_SCREEN_WIDTH + 145; } self.selectionView = [[PLSSelectionView alloc] initWithFrame:CGRectMake(0, rotateViewTopSpace, PLS_SCREEN_WIDTH, 35) lineWidth:1 lineColor:[UIColor blackColor]]; @@ -218,36 +207,15 @@ - (void)setupSelectionView { // 视频旋转 UIButton *rotateVideoButton = [UIButton buttonWithType:UIButtonTypeCustom]; - rotateVideoButton.frame = CGRectMake(PLS_SCREEN_WIDTH - 120, self.selectionView.frame.origin.y + 38, 100, 36); + rotateVideoButton.frame = CGRectMake(PLS_SCREEN_WIDTH/2 - 50, self.selectionView.frame.origin.y + 38, 100, 36); [rotateVideoButton setTitle:@"旋转视频" forState:UIControlStateNormal]; [rotateVideoButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; rotateVideoButton.titleLabel.font = [UIFont systemFontOfSize:16]; rotateVideoButton.layer.cornerRadius = 5; rotateVideoButton.layer.borderWidth = 1; rotateVideoButton.layer.borderColor = [UIColor whiteColor].CGColor; - - UILabel *cutLabel = [[UILabel alloc] init]; - cutLabel.font = [UIFont systemFontOfSize:14]; - cutLabel.text = @"移动红色线框选择剪裁区域"; - cutLabel.textColor = [UIColor colorWithWhite:1 alpha:.5]; - [cutLabel sizeToFit]; - cutLabel.frame = CGRectMake(5, rotateVideoButton.frame.origin.y + 10, cutLabel.bounds.size.width, cutLabel.bounds.size.height); - [self.view addSubview:cutLabel]; - [rotateVideoButton addTarget:self action:@selector(rotateVideoButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:rotateVideoButton]; - -} - -- (void)setupClipMovieView { - CGFloat duration = [self getFileDuration:self.url]; - self.clipMovieView = [[PLSClipMovieView alloc] initWithMovieURL:self.url minDuration:2.0f maxDuration:duration]; - self.clipMovieView.delegate = self; - [self.view addSubview:self.clipMovieView]; - [self.clipMovieView mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.right.bottom.mas_equalTo(0); - make.height.mas_equalTo(145); - }]; } - (void)setupScopeCutView { @@ -380,27 +348,6 @@ - (void)panGestureHandle:(UIPanGestureRecognizer *)gestureRecognizer { } } -#pragma mark - PLSClipMovieView delegate -- (void)didStartDragView { - -} - -- (void)clipFrameView:(PLSClipMovieView *)clipFrameView didEndDragLeftView:(CMTime)leftTime rightView:(CMTime)rightTime { - CGFloat start = CMTimeGetSeconds(leftTime); - CGFloat end = CMTimeGetSeconds(rightTime); - CGFloat duration = end - start; - - self.movieSettings[PLSStartTimeKey] = [NSNumber numberWithFloat:start]; - self.movieSettings[PLSDurationKey] = [NSNumber numberWithFloat:duration]; - - self.shortVideoEditor.timeRange = CMTimeRangeMake(leftTime, CMTimeSubtract(rightTime, leftTime)); - [self.shortVideoEditor startEditing]; -} - -- (void)clipFrameView:(PLSClipMovieView *)clipFrameView isScrolling:(BOOL)scrolling { - self.view.userInteractionEnabled = !scrolling; -} - #pragma mark -- PLSSelectionViewDelegate - (void)selectionView:(PLSSelectionView *)selectionView didSelectedItemNumber:(NSInteger)number { if (selectionView == self.selectionView) { @@ -574,6 +521,7 @@ - (void)movieTransCodeAction { EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; videoEditViewController.filesURLArray = @[url]; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [weakSelf presentViewController:videoEditViewController animated:YES completion:nil]; }); }]; diff --git a/Example/PLShortVideoKitDemo/MultiVideoViewController.h b/Example/PLShortVideoKitDemo/MultiVideoViewController.h index ac3368d7..17d51b5a 100644 --- a/Example/PLShortVideoKitDemo/MultiVideoViewController.h +++ b/Example/PLShortVideoKitDemo/MultiVideoViewController.h @@ -9,5 +9,4 @@ #import "BaseViewController.h" @interface MultiVideoViewController : BaseViewController - @end diff --git a/Example/PLShortVideoKitDemo/MultiVideoViewController.m b/Example/PLShortVideoKitDemo/MultiVideoViewController.m index 332410da..06b3a5f5 100644 --- a/Example/PLShortVideoKitDemo/MultiVideoViewController.m +++ b/Example/PLShortVideoKitDemo/MultiVideoViewController.m @@ -28,37 +28,9 @@ @implementation MultiVideoViewController - (void)viewDidLoad { [super viewDidLoad]; - self.nextButton.hidden = YES; - - UIImage *image = [UIImage imageNamed:@"select_pintu"]; - _mulitMixButton = [[UIButton alloc] init]; - [_mulitMixButton setImage:image forState:(UIControlStateNormal)]; - [_mulitMixButton sizeToFit]; - _mulitMixButton.center = CGPointMake(self.view.center.x, self.view.center.y - image.size.height); - [_mulitMixButton addTarget:self action:@selector(pressMulitMixButtonEvent) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:_mulitMixButton]; - - _mulitMixLabel = [[UILabel alloc] init]; - [_mulitMixLabel setTextColor:[UIColor colorWithWhite:1.0 alpha:.6]]; - [_mulitMixLabel setText:@"视频拼图"]; - [_mulitMixLabel sizeToFit]; - _mulitMixLabel.center = CGPointMake(_mulitMixButton.center.x, _mulitMixButton.center.y + _mulitMixButton.bounds.size.height/2 + 20); - [self.view addSubview:_mulitMixLabel]; + [self pressMulitMixButtonEvent]; - image = [UIImage imageNamed:@"select_meterial"]; - _recordingButton = [[UIButton alloc] init]; - [_recordingButton setImage:image forState:(UIControlStateNormal)]; - [_recordingButton sizeToFit]; - _recordingButton.center = CGPointMake(self.view.center.x, self.view.center.y + image.size.height); - [_recordingButton addTarget:self action:@selector(pressBiRecordButtonEvent) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:_recordingButton]; - - _recordingMixLabel = [[UILabel alloc] init]; - [_recordingMixLabel setTextColor:[UIColor colorWithWhite:1.0 alpha:.6]]; - [_recordingMixLabel setText:@"素材合拍"]; - [_recordingMixLabel sizeToFit]; - _recordingMixLabel.center = CGPointMake(_recordingButton.center.x, _recordingButton.center.y + _recordingButton.bounds.size.height/2 + 20); - [self.view addSubview:_recordingMixLabel]; + self.nextButton.hidden = YES; } - (void)didReceiveMemoryWarning { @@ -66,30 +38,7 @@ - (void)didReceiveMemoryWarning { // Dispose of any resources that can be recreated. } -- (void)backButtonClick { - if (nil == self.mulitMixLabel.superview) { - - [self.mix2Button removeFromSuperview]; - [self.mix3Button removeFromSuperview]; - [self.mix4Button removeFromSuperview]; - - [self.view addSubview:self.mulitMixButton]; - [self.view addSubview:self.mulitMixLabel]; - [self.view addSubview:self.recordingButton]; - [self.view addSubview:self.recordingMixLabel]; - - } else { - [super backButtonClick]; - } -} - - (void)pressMulitMixButtonEvent { - - [self.mulitMixLabel removeFromSuperview]; - [self.mulitMixButton removeFromSuperview]; - [self.recordingMixLabel removeFromSuperview]; - [self.recordingButton removeFromSuperview]; - self.titleLabel.text = @"选择拼图样式"; if (nil == self.mix2Button) { UIImage *image = [UIImage imageNamed:@"2video_template"]; @@ -126,16 +75,7 @@ - (void)pressMixButton:(UIButton *)button { VideoSelectViewController *videoSelectViewController = [[VideoSelectViewController alloc] init]; videoSelectViewController.actionType = enumVideoNextActionPingtu; videoSelectViewController.needVideoCount = button.tag; - - [self presentViewController:videoSelectViewController animated:YES completion:nil]; -} - -- (void)pressBiRecordButtonEvent { - VideoSelectViewController *videoSelectViewController = [[VideoSelectViewController alloc] init]; - videoSelectViewController.actionType = enumVideoNextActionRecording; - videoSelectViewController.needVideoCount = 1; - + videoSelectViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:videoSelectViewController animated:YES completion:nil]; } - @end diff --git a/Example/PLShortVideoKitDemo/PhotoAlbumViewController.h b/Example/PLShortVideoKitDemo/PhotoAlbumViewController.h index ab1e1f37..eb9ca496 100644 --- a/Example/PLShortVideoKitDemo/PhotoAlbumViewController.h +++ b/Example/PLShortVideoKitDemo/PhotoAlbumViewController.h @@ -67,6 +67,10 @@ @property (strong, nonatomic) PLSRateButtonView *rateButtonView; @property (strong, nonatomic) PLSScrollView *dynamicScrollView; + +// 0 剪辑 1 转码 2 拼接 +@property (assign, nonatomic) NSInteger typeIndex; + - (void)nextButtonClick:(UIButton *)sender; - (void)fetchAssetsWithMediaType:(PHAssetMediaType)mediaType; diff --git a/Example/PLShortVideoKitDemo/PhotoAlbumViewController.m b/Example/PLShortVideoKitDemo/PhotoAlbumViewController.m index 1c043d24..bf7cee3d 100644 --- a/Example/PLShortVideoKitDemo/PhotoAlbumViewController.m +++ b/Example/PLShortVideoKitDemo/PhotoAlbumViewController.m @@ -10,14 +10,9 @@ #import "MovieTransCodeViewController.h" #import "PLShortVideoKit/PLShortVideoKit.h" #import "ViewRecordViewController.h" +#import "MoiveClipViewController.h" #import "EditViewController.h" -#define AlertViewShow(msg) [[[UIAlertView alloc] initWithTitle:@"warning" message:[NSString stringWithFormat:@"%@", msg] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil] show] -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) - - #pragma mark -- PLSScrollView @implementation PLSScrollView @@ -501,11 +496,11 @@ - (void)setupBaseToolboxView { [self.view addSubview:self.baseToolboxView]; // 标题 - UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 100, 64)]; + UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 20, 100, 44)]; if (iPhoneX_SERIES) { - titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 48); + titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 58); } else { - titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 32); + titleLabel.center = CGPointMake(PLS_SCREEN_WIDTH / 2, 42); } titleLabel.text = @"相机胶卷"; titleLabel.textAlignment = NSTextAlignmentCenter; @@ -518,13 +513,13 @@ - (void)setupBaseToolboxView { [cancelButton setTitle:@"取消" forState:UIControlStateNormal]; [cancelButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [cancelButton setTitleColor:PLS_RGBCOLOR(141, 141, 142) forState:UIControlStateHighlighted]; - cancelButton.frame = CGRectMake(PLS_SCREEN_WIDTH - 80, 0, 80, 64); + cancelButton.frame = CGRectMake(PLS_SCREEN_WIDTH - 80, 20, 80, 44); cancelButton.titleLabel.font = [UIFont systemFontOfSize:16]; [cancelButton addTarget:self action:@selector(cancelButtonClick:) forControlEvents:UIControlEventTouchUpInside]; [self.baseToolboxView addSubview:cancelButton]; // 展示视频拼接的进度 - self.progressLabel = [[UILabel alloc] initWithFrame:CGRectMake(160, 0, 200, 45)]; + self.progressLabel = [[UILabel alloc] initWithFrame:CGRectMake(160, 20, 200, 25)]; self.progressLabel.center = CGPointMake(self.view.center.x, self.view.center.y + 30); self.progressLabel.textAlignment = NSTextAlignmentCenter; self.progressLabel.textColor = [UIColor whiteColor]; @@ -756,16 +751,36 @@ - (void)nextButtonClick:(UIButton *)sender { } if (self.urls.count == 1) { - // 视频转码 - 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]; + if (_typeIndex == 1) { + // 视频转码 + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"视频转码" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; + alertView.tag = 10002; + [alertView show]; + } else if (_typeIndex == 2) { + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"视频拼接需要选择视频个数大于 1!" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil]; + alertView.tag = 10005; + [alertView show]; + } else { + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"视频截取" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; + alertView.tag = 10006; + [alertView show]; + } + } else { + if (_typeIndex == 2) { + // 多个视频拼接 或者 单个视频转码 都可以用 PLSMovieComposer + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"视频拼接" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; + alertView.tag = 10003; + [alertView show]; + } else if (_typeIndex == 1) { + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"选择 1 个视频进行转码处理!" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil]; + alertView.tag = 10005; + [alertView show]; + } else { + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"选择 1 个视频进行剪辑处理!" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; + alertView.tag = 10005; + [alertView show]; + } } } } @@ -774,7 +789,7 @@ - (void)nextButtonClick:(UIButton *)sender { #pragma mark -- UIAlertView delegate - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { // 检测是否授权访问相册,没有授权就跳转到 App 的设置页 - if (10001 != alertView.tag && 10002 != alertView.tag && 10003 != alertView.tag && 10004 != alertView.tag) { + if (10001 != alertView.tag && 10002 != alertView.tag && 10003 != alertView.tag && 10004 != alertView.tag && 10005 != alertView.tag && 10006 != alertView.tag) { if (buttonIndex == alertView.firstOtherButtonIndex) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; } @@ -822,6 +837,13 @@ - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)butto } else { [self movieComposerEvent:PLSComposerPriorityTypeAudio]; } + } else if (10005 == alertView.tag) { + [self dismissViewControllerAnimated:YES completion:nil]; + } else if (10006 == alertView.tag) { + MoiveClipViewController *movieClipViewController = [[MoiveClipViewController alloc] init]; + movieClipViewController.url = self.urls[0]; + movieClipViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:movieClipViewController animated:YES completion:nil]; } } @@ -842,6 +864,7 @@ - (void)joinEditViewController:(NSURL *)url { EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; videoEditViewController.filesURLArray = @[url]; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:videoEditViewController animated:YES completion:nil]; } @@ -886,9 +909,7 @@ - (void)imageToMovieEvent { [weakSelf removeActivityIndicatorView]; weakSelf.progressLabel.text = @""; - MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; - transCodeViewController.url = url; - [weakSelf presentViewController:transCodeViewController animated:YES completion:nil]; + [weakSelf joinEditViewController:url]; }]; [self.imageToMovieComposer setFailureBlock:^(NSError *error) { NSLog(@"imageToMovieComposer failed"); @@ -910,6 +931,7 @@ - (void)imageToMovieEvent { - (void)viewRecordEvent { ViewRecordViewController *viewRecordViewController = [[ViewRecordViewController alloc] init]; viewRecordViewController.selectedAssets = self.dynamicScrollView.selectedAssets; + viewRecordViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:viewRecordViewController animated:YES completion:nil]; } @@ -917,6 +939,7 @@ - (void)viewRecordEvent { - (void)movieTransCodeEvent { MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; transCodeViewController.url = self.urls[0]; + transCodeViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:transCodeViewController animated:YES completion:nil]; } @@ -946,9 +969,7 @@ - (void)movieComposerEvent:(PLSComposerPriorityType)type { [weakSelf removeActivityIndicatorView]; weakSelf.progressLabel.text = @""; - MovieTransCodeViewController *transCodeViewController = [[MovieTransCodeViewController alloc] init]; - transCodeViewController.url = url; - [weakSelf presentViewController:transCodeViewController animated:YES completion:nil]; + [weakSelf joinEditViewController:url]; }]; [self.movieComposer setFailureBlock:^(NSError *error) { NSLog(@"movieComposer failed"); diff --git a/Example/PLShortVideoKitDemo/PlayViewController.m b/Example/PLShortVideoKitDemo/PlayViewController.m index aa64fa0f..458dff0b 100644 --- a/Example/PLShortVideoKitDemo/PlayViewController.m +++ b/Example/PLShortVideoKitDemo/PlayViewController.m @@ -12,11 +12,9 @@ #import "FLAnimatedImage.h" #import "PLSPlayerView.h" -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) + #define PLS_BaseToolboxView_HEIGHT 64 #define PLS_EditToolboxView_HEIGHT 50 -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] static NSString *const kUploadToken = @"QxZugR8TAhI38AiJ_cptTl3RbzLyca3t-AAiH-Hh:3hK7jJJQKwmemseSwQ1duO5AXOw=:eyJzY29wZSI6InNhdmUtc2hvcnQtdmlkZW8tZnJvbS1kZW1vIiwiZGVhZGxpbmUiOjM1NTk2OTU4NzYsInVwaG9zdHMiOlsiaHR0cDovL3VwLXoyLnFpbml1LmNvbSIsImh0dHA6Ly91cGxvYWQtejIucWluaXUuY29tIiwiLUggdXAtejIucWluaXUuY29tIGh0dHA6Ly8xNC4xNTIuMzcuNCJdfQ=="; static NSString *const kURLPrefix = @"http://panm32w98.bkt.clouddn.com"; @@ -163,7 +161,7 @@ - (void)setupToolboxUI { [backButton setTitle:@"返回" forState:UIControlStateNormal]; [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [backButton setTitleColor:PLS_RGBCOLOR(141, 141, 142) forState:UIControlStateHighlighted]; - backButton.frame = CGRectMake(0, 0, 80, 64); + backButton.frame = CGRectMake(0, 20, 80, 44); backButton.titleLabel.font = [UIFont systemFontOfSize:16]; [backButton addTarget:self action:@selector(backButtonClick) forControlEvents:UIControlEventTouchUpInside]; [self.baseToolboxView addSubview:backButton]; @@ -173,7 +171,7 @@ - (void)setupToolboxUI { [self.uploadButton setTitle:@"取消" forState:UIControlStateSelected]; [self.uploadButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self.uploadButton setTitleColor:PLS_RGBCOLOR(141, 141, 142) forState:UIControlStateHighlighted]; - self.uploadButton.frame = CGRectMake(PLS_SCREEN_WIDTH - 80, 0, 80, 64); + self.uploadButton.frame = CGRectMake(PLS_SCREEN_WIDTH - 80, 20, 80, 44); self.uploadButton.titleLabel.font = [UIFont systemFontOfSize:16]; [self.uploadButton addTarget:self action:@selector(uploadButtonClick:) forControlEvents:UIControlEventTouchUpInside]; [self.baseToolboxView addSubview:self.uploadButton]; diff --git a/Example/PLShortVideoKitDemo/PrefixHeader.pch b/Example/PLShortVideoKitDemo/PrefixHeader.pch index 4753e5a0..3eb848de 100644 --- a/Example/PLShortVideoKitDemo/PrefixHeader.pch +++ b/Example/PLShortVideoKitDemo/PrefixHeader.pch @@ -36,4 +36,16 @@ #define ARRAY_SIZE(c_array) (sizeof((c_array))/sizeof((c_array)[0])) #endif +// 颜色 +#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] +#define PLS_RGBCOLOR_ALPHA(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)] + +// 提示框 +#define AlertViewShow(msg) [[[UIAlertView alloc] initWithTitle:@"warning" message:[NSString stringWithFormat:@"%@", msg] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil] show] + +// 屏幕宽高 +#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) +#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) + + #endif /* PrefixHeader_pch */ diff --git a/Example/PLShortVideoKitDemo/RecordViewController.h b/Example/PLShortVideoKitDemo/RecordViewController.h index ad8631da..390ffb2c 100644 --- a/Example/PLShortVideoKitDemo/RecordViewController.h +++ b/Example/PLShortVideoKitDemo/RecordViewController.h @@ -9,5 +9,5 @@ #import @interface RecordViewController : UIViewController - +@property (nonatomic, assign) BOOL screenRecord; @end diff --git a/Example/PLShortVideoKitDemo/RecordViewController.m b/Example/PLShortVideoKitDemo/RecordViewController.m index 30e8637a..b7a4f161 100644 --- a/Example/PLShortVideoKitDemo/RecordViewController.m +++ b/Example/PLShortVideoKitDemo/RecordViewController.m @@ -19,17 +19,9 @@ #import "PLSRateButtonView.h" #import "PLScreenRecorderManager.h" -#define AlertViewShow(msg) [[[UIAlertView alloc] initWithTitle:@"warning" message:[NSString stringWithFormat:@"%@", msg] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil] show] #define PLS_CLOSE_CONTROLLER_ALERTVIEW_TAG 10001 -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] -#define PLS_RGBACOLOR(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)] - #define PLS_BaseToolboxView_HEIGHT 64 -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) @interface RecordViewController () < @@ -49,7 +41,6 @@ @interface RecordViewController () @property (strong, nonatomic) PLScreenRecorderManager *screenRecorderManager; @property (strong, nonatomic) PLSProgressBar *progressBar; @property (strong, nonatomic) UIButton *recordButton; -@property (strong, nonatomic) UIButton *viewRecordButton; @property (strong, nonatomic) PLSDeleteButton *deleteButton; @property (strong, nonatomic) UIButton *endButton; @property (strong, nonatomic) PLSRateButtonView *rateButtonView; @@ -80,7 +71,13 @@ @interface RecordViewController () // 展示所有滤镜的集合视图 @property (strong, nonatomic) UICollectionView *editVideoCollectionView; @property (strong, nonatomic) NSMutableArray *filtersArray; -@property (assign, nonatomic) NSInteger filterIndex; +// 切换滤镜的时候,为了更好的用户体验,添加以下属性来做切换动画 +@property (nonatomic, assign) BOOL isPanning; +@property (nonatomic, assign) BOOL isLeftToRight; +@property (nonatomic, assign) BOOL isNeedChangeFilter; +@property (nonatomic, weak) PLSFilter *leftFilter; +@property (nonatomic, weak) PLSFilter *rightFilter; +@property (nonatomic, assign) float leftPercent; @property (strong, nonatomic) UIButton *draftButton; @property (strong, nonatomic) NSURL *URL; @@ -88,6 +85,8 @@ @interface RecordViewController () @property (strong, nonatomic) UIButton *musicButton; @property (strong, nonatomic) UIActivityIndicatorView *activityIndicatorView; +@property (strong, nonatomic) UIButton *filterButton; + @property (strong, nonatomic) UIButton *monitorButton; // 实时截图按钮 @property (strong, nonatomic) UIButton *snapshotButton; @@ -97,6 +96,9 @@ @interface RecordViewController () // 录制前是否开启自动检测设备方向调整视频拍摄的角度(竖屏、横屏) @property (assign, nonatomic) BOOL isUseAutoCheckDeviceOrientationBeforeRecording; +@property (assign, nonatomic) BOOL isViewRecord; + + @end @implementation RecordViewController @@ -126,6 +128,11 @@ - (void)loadView{ // 短视频录制核心类设置 [self setupShortVideoRecorder]; + if (_screenRecord) { + _isViewRecord = YES; + [self viewRecorder]; + } + // -------------------------- [self setupBaseToolboxView]; [self setupRecordToolboxView]; @@ -146,6 +153,8 @@ - (void)viewDidLoad { - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:YES]; + [self.shortVideoRecorder startCaptureSession]; [self getFirstMovieFromPhotoAlbum]; @@ -154,6 +163,8 @@ - (void)viewWillAppear:(BOOL)animated { - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; + [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:YES]; + [self.shortVideoRecorder stopCaptureSession]; } @@ -172,8 +183,8 @@ - (void)setupShortVideoRecorder { self.videoConfiguration = [PLSVideoConfiguration defaultConfiguration]; self.videoConfiguration.position = AVCaptureDevicePositionFront; self.videoConfiguration.videoFrameRate = 30; - self.videoConfiguration.averageVideoBitRate = 1000*2500; self.videoConfiguration.videoSize = CGSizeMake(720, 1280); + self.videoConfiguration.averageVideoBitRate = [self suitableVideoBitrateWithSize:self.videoConfiguration.videoSize]; self.videoConfiguration.videoOrientation = AVCaptureVideoOrientationPortrait; self.videoConfiguration.sessionPreset = AVCaptureSessionPreset1280x720; @@ -191,12 +202,6 @@ - (void)setupShortVideoRecorder { // 录制前是否开启自动检测设备方向调整视频拍摄的角度(竖屏、横屏) if (self.isUseAutoCheckDeviceOrientationBeforeRecording) { - UIView *deviceOrientationView = [[UIView alloc] init]; - deviceOrientationView.frame = CGRectMake(0, 0, PLS_SCREEN_WIDTH/2, 44); - deviceOrientationView.center = CGPointMake(PLS_SCREEN_WIDTH/2, 44/2); - deviceOrientationView.backgroundColor = [UIColor grayColor]; - deviceOrientationView.alpha = 0.7; - [self.view addSubview:deviceOrientationView]; self.shortVideoRecorder.adaptationRecording = YES; // 根据设备方向自动确定横屏 or 竖屏拍摄效果 [self.shortVideoRecorder setDeviceOrientationBlock:^(PLSPreviewOrientation deviceOrientation){ switch (deviceOrientation) { @@ -215,23 +220,6 @@ - (void)setupShortVideoRecorder { default: break; } - - if (deviceOrientation == PLSPreviewOrientationPortrait) { - deviceOrientationView.frame = CGRectMake(0, 0, PLS_SCREEN_WIDTH/2, 44); - deviceOrientationView.center = CGPointMake(PLS_SCREEN_WIDTH/2, 44/2); - - } else if (deviceOrientation == PLSPreviewOrientationPortraitUpsideDown) { - deviceOrientationView.frame = CGRectMake(0, 0, PLS_SCREEN_WIDTH/2, 44); - deviceOrientationView.center = CGPointMake(PLS_SCREEN_WIDTH/2, PLS_SCREEN_HEIGHT - 44/2); - - } else if (deviceOrientation == PLSPreviewOrientationLandscapeRight) { - deviceOrientationView.frame = CGRectMake(0, 0, 44, PLS_SCREEN_HEIGHT/2); - deviceOrientationView.center = CGPointMake(PLS_SCREEN_WIDTH - 44/2, PLS_SCREEN_HEIGHT/2); - - } else if (deviceOrientation == PLSPreviewOrientationLandscapeLeft) { - deviceOrientationView.frame = CGRectMake(0, 0, 44, PLS_SCREEN_HEIGHT/2); - deviceOrientationView.center = CGPointMake(44/2, PLS_SCREEN_HEIGHT/2); - } }]; } @@ -250,17 +238,6 @@ - (void)setupShortVideoRecorder { [self.filtersArray addObject:dic]; } - - // 展示多种滤镜的 UICollectionView - CGRect frame = self.editVideoCollectionView.frame; - CGFloat x = PLS_BaseToolboxView_HEIGHT; - CGFloat y = PLS_BaseToolboxView_HEIGHT; - CGFloat width = frame.size.width - 2*x; - CGFloat height = frame.size.height; - self.editVideoCollectionView.frame = CGRectMake(x, y, width, height); - [self.view addSubview:self.editVideoCollectionView]; - [self.editVideoCollectionView reloadData]; - self.editVideoCollectionView.hidden = YES; } // 本地视频 @@ -269,83 +246,121 @@ - (void)setupShortVideoRecorder { } - (void)setupBaseToolboxView { - self.baseToolboxView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, PLS_BaseToolboxView_HEIGHT, PLS_BaseToolboxView_HEIGHT + PLS_SCREEN_WIDTH)]; - self.baseToolboxView.backgroundColor = [UIColor clearColor]; - [self.view addSubview:self.baseToolboxView]; + UIView *topToolView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 176, 35)]; + topToolView.backgroundColor = [UIColor clearColor]; + [self.view addSubview:topToolView]; // 返回 UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; - backButton.frame = CGRectMake(10, 10, 35, 35); - [backButton setBackgroundImage:[UIImage imageNamed:@"btn_camera_cancel_a"] forState:UIControlStateNormal]; - [backButton setBackgroundImage:[UIImage imageNamed:@"btn_camera_cancel_b"] forState:UIControlStateHighlighted]; + backButton.frame = CGRectMake(0, 0, 35, 35); + backButton.imageEdgeInsets = UIEdgeInsetsMake(2, 2, 2, 2); + [backButton setImage:[UIImage imageNamed:@"close_back"] forState:UIControlStateNormal]; [backButton addTarget:self action:@selector(backButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; - [self.baseToolboxView addSubview:backButton]; + [topToolView addSubview:backButton]; - // 七牛滤镜 - UIButton *filterButton = [UIButton buttonWithType:UIButtonTypeCustom]; - filterButton.frame = CGRectMake(10, 55, 35, 35); - [filterButton setTitle:@"滤镜" forState:UIControlStateNormal]; - [filterButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - filterButton.titleLabel.font = [UIFont systemFontOfSize:14]; - [filterButton addTarget:self action:@selector(filterButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; - [self.baseToolboxView addSubview:filterButton]; - - // 录屏按钮 - self.viewRecordButton = [UIButton buttonWithType:UIButtonTypeCustom]; - self.viewRecordButton.frame = CGRectMake(10, 100, 35, 35); - [self.viewRecordButton setTitle:@"录屏" forState:UIControlStateNormal]; - [self.viewRecordButton setTitle:@"完成" forState:UIControlStateSelected]; - self.viewRecordButton.selected = NO; - [self.viewRecordButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - self.viewRecordButton.titleLabel.font = [UIFont systemFontOfSize:14]; - [self.viewRecordButton addTarget:self action:@selector(viewRecorderButtonClick:) forControlEvents:UIControlEventTouchUpInside]; - [self.baseToolboxView addSubview:self.viewRecordButton]; + // 截图 + self.snapshotButton = [UIButton buttonWithType:UIButtonTypeCustom]; + self.snapshotButton.frame = CGRectMake(47, 0, 35, 35); + [self.snapshotButton setImage:[UIImage imageNamed:@"screen_shoots"] forState:UIControlStateNormal]; + [self.snapshotButton addTarget:self action:@selector(snapshotButtonOnClick:) forControlEvents:UIControlEventTouchUpInside]; + [topToolView addSubview:_snapshotButton]; - // 全屏/正方形录制模式 - self.squareRecordButton = [UIButton buttonWithType:UIButtonTypeCustom]; - self.squareRecordButton.frame = CGRectMake(10, 145, 35, 35); - [self.squareRecordButton setTitle:@"1:1" forState:UIControlStateNormal]; - [self.squareRecordButton setTitle:@"全屏" forState:UIControlStateSelected]; - self.squareRecordButton.selected = NO; - [self.squareRecordButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - self.squareRecordButton.titleLabel.font = [UIFont systemFontOfSize:14]; - [self.squareRecordButton addTarget:self action:@selector(squareRecordButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; - [self.baseToolboxView addSubview:self.squareRecordButton]; + // 切换摄像头 + UIButton *toggleCameraButton = [UIButton buttonWithType:UIButtonTypeCustom]; + toggleCameraButton.frame = CGRectMake(47 * 2, 0, 35, 35); + toggleCameraButton.imageEdgeInsets = UIEdgeInsetsMake(1, 1, 1, 1); + [toggleCameraButton setImage:[UIImage imageNamed:@"toggle_camera"] forState:UIControlStateNormal]; + [toggleCameraButton addTarget:self action:@selector(toggleCameraButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; + [topToolView addSubview:toggleCameraButton]; // 闪光灯 UIButton *flashButton = [UIButton buttonWithType:UIButtonTypeCustom]; - flashButton.frame = CGRectMake(10, 190, 35, 35); - [flashButton setBackgroundImage:[UIImage imageNamed:@"flash_close"] forState:UIControlStateNormal]; - [flashButton setBackgroundImage:[UIImage imageNamed:@"flash_open"] forState:UIControlStateSelected]; + flashButton.frame = CGRectMake(47 * 3, 0, 35, 35); + flashButton.imageEdgeInsets = UIEdgeInsetsMake(2, 2, 2, 2); + [flashButton setImage:[UIImage imageNamed:@"flash_close"] forState:UIControlStateNormal]; + [flashButton setImage:[UIImage imageNamed:@"flash_open"] forState:UIControlStateSelected]; [flashButton addTarget:self action:@selector(flashButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; - [self.baseToolboxView addSubview:flashButton]; + [topToolView addSubview:flashButton]; + + UIView *leftToolView = [[UIView alloc] initWithFrame:CGRectMake(10, 60, 72, 228)]; + leftToolView.backgroundColor = [UIColor clearColor]; + [self.view addSubview:leftToolView]; // 美颜 UIButton *beautyFaceButton = [UIButton buttonWithType:UIButtonTypeCustom]; - beautyFaceButton.frame = CGRectMake(10, 235, 30, 30); - [beautyFaceButton setTitle:@"美颜" forState:UIControlStateNormal]; + beautyFaceButton.frame = CGRectMake(0, 0, 72, 28); + [beautyFaceButton setTitle:@"美颜: 关" forState:UIControlStateNormal]; [beautyFaceButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [beautyFaceButton setTitle:@"美颜: 开" forState:UIControlStateSelected]; + [beautyFaceButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; beautyFaceButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [beautyFaceButton sizeToFit]; [beautyFaceButton addTarget:self action:@selector(beautyFaceButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; - [self.baseToolboxView addSubview:beautyFaceButton]; + [leftToolView addSubview:beautyFaceButton]; beautyFaceButton.selected = YES; - // 切换摄像头 - UIButton *toggleCameraButton = [UIButton buttonWithType:UIButtonTypeCustom]; - toggleCameraButton.frame = CGRectMake(10, 280, 35, 35); - [toggleCameraButton setBackgroundImage:[UIImage imageNamed:@"toggle_camera"] forState:UIControlStateNormal]; - [toggleCameraButton addTarget:self action:@selector(toggleCameraButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; - [self.baseToolboxView addSubview:toggleCameraButton]; + // 七牛滤镜 + self.filterButton = [UIButton buttonWithType:UIButtonTypeCustom]; + self.filterButton.frame = CGRectMake(0, 40, 72, 28); + [self.filterButton setTitle:@"滤镜: 原色" forState:UIControlStateNormal]; + [self.filterButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + self.filterButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.filterButton sizeToFit]; + [self.filterButton addTarget:self action:@selector(filterButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; + [leftToolView addSubview:self.filterButton]; + + //是否开启 SDK 退到后台监听 + self.monitorButton = [UIButton buttonWithType:UIButtonTypeCustom]; + self.monitorButton.frame = CGRectMake(0, 80, 72, 28); + [self.monitorButton setTitle:@"监听: 关" forState:UIControlStateNormal]; + [self.monitorButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [self.monitorButton setTitle:@"监听: 开" forState:UIControlStateSelected]; + [self.monitorButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; + self.monitorButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.monitorButton sizeToFit]; + [self.monitorButton addTarget:self action:@selector(monitorButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; + [leftToolView addSubview:self.monitorButton]; + self.monitorButton.selected = NO; + + // 30FPS/60FPS + self.frameRateButton = [[UIButton alloc] init]; + self.frameRateButton.frame = CGRectMake(0, 120, 72, 28); + [self.frameRateButton setTitle:@"帧率: 30" forState:(UIControlStateNormal)]; + [self.frameRateButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [self.frameRateButton setTitle:@"帧率: 60" forState:(UIControlStateSelected)]; + [self.frameRateButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; + self.frameRateButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.frameRateButton sizeToFit]; + [self.frameRateButton addTarget:self action:@selector(frameRateButtonOnClick:) forControlEvents:UIControlEventTouchUpInside]; + [leftToolView addSubview:self.frameRateButton]; + + // 全屏/正方形录制模式 + self.squareRecordButton = [[UIButton alloc] init]; + self.squareRecordButton.frame = CGRectMake(0, 160, 72, 28); + [self.squareRecordButton setTitle:@"屏比: 全屏" forState:UIControlStateNormal]; + [self.squareRecordButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [self.squareRecordButton setTitle:@"屏比: 1:1" forState:UIControlStateSelected]; + [self.squareRecordButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; + self.squareRecordButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.squareRecordButton sizeToFit]; + [self.squareRecordButton addTarget:self action:@selector(squareRecordButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; + [leftToolView addSubview:self.squareRecordButton]; + self.squareRecordButton.selected = NO; // 录制的视频文件的存储路径设置 self.filePathButton = [[UIButton alloc] init]; - self.filePathButton.frame = CGRectMake(10, 325, 35, 35); - [self.filePathButton setImage:[UIImage imageNamed:@"file_path"] forState:UIControlStateNormal]; + self.filePathButton.frame = CGRectMake(0, 200, 72, 28); + [self.filePathButton setTitle:@"目录: 开" forState:UIControlStateNormal]; + [self.filePathButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [self.filePathButton setTitle:@"目录: 关" forState:UIControlStateSelected]; + [self.filePathButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; + self.filePathButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.filePathButton sizeToFit]; [self.filePathButton addTarget:self action:@selector(filePathButtonClickedEvent:) forControlEvents:UIControlEventTouchUpInside]; - [self.baseToolboxView addSubview:self.filePathButton]; - + [leftToolView addSubview:self.filePathButton]; self.filePathButton.selected = NO; self.useSDKInternalPath = YES; + // 展示拼接视频的动画 self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.view.bounds]; @@ -355,7 +370,6 @@ - (void)setupBaseToolboxView { } - (void)setupRightButtonView { - self.rightScrollView = [[UIScrollView alloc] init]; self.rightScrollView.bounces = YES; CGRect rc = self.rateButtonView.bounds; @@ -366,65 +380,31 @@ - (void)setupRightButtonView { [weakSelf.rightScrollView flashScrollIndicators]; }); - UIColor *backgroundColor = [UIColor colorWithWhite:0.0 alpha:.55]; + UIColor *backgroundColor = [UIColor whiteColor]; int index = 0; - // 拍照 - self.snapshotButton = [[UIButton alloc] initWithFrame:CGRectMake(0, index * 60 + 10, 46, 46)]; - self.snapshotButton.layer.cornerRadius = 23; - self.snapshotButton.backgroundColor = backgroundColor; - [self.snapshotButton setImage:[UIImage imageNamed:@"icon_trim"] forState:UIControlStateNormal]; - self.snapshotButton.imageEdgeInsets = UIEdgeInsetsMake(6, 6, 6, 6); - [self.snapshotButton addTarget:self action:@selector(snapshotButtonOnClick:) forControlEvents:UIControlEventTouchUpInside]; - [self.rightScrollView addSubview:_snapshotButton]; - - index ++; // 加载草稿视频 - self.draftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, index * 60 + 10, 46, 46)]; - self.draftButton.layer.cornerRadius = 23; + self.draftButton = [[UIButton alloc] initWithFrame:CGRectMake(0, index * 46 + 20, 46, 32)]; + self.draftButton.layer.cornerRadius = 3; self.draftButton.backgroundColor = backgroundColor; - [self.draftButton setImage:[UIImage imageNamed:@"draft_video"] forState:UIControlStateNormal]; - self.draftButton.imageEdgeInsets = UIEdgeInsetsMake(6, 6, 6, 6); + [self.draftButton setTitle:@"片段" forState:UIControlStateNormal]; + self.draftButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.draftButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [self.draftButton addTarget:self action:@selector(draftVideoButtonOnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.rightScrollView addSubview:self.draftButton]; index ++; // 是否使用背景音乐 - self.musicButton = [[UIButton alloc] initWithFrame:CGRectMake(0, index * 60 + 10, 46, 46)]; - self.musicButton.layer.cornerRadius = 23; + self.musicButton = [[UIButton alloc] initWithFrame:CGRectMake(0, index * 46 + 20, 46, 32)]; + self.musicButton.layer.cornerRadius = 3; self.musicButton.backgroundColor = backgroundColor; - [self.musicButton setImage:[UIImage imageNamed:@"music_no_selected"] forState:UIControlStateNormal]; - [self.musicButton setImage:[UIImage imageNamed:@"music_selected"] forState:UIControlStateSelected]; - self.musicButton.imageEdgeInsets = UIEdgeInsetsMake(6, 6, 6, 6); + [self.musicButton setTitle:@"音乐" forState:UIControlStateNormal]; + self.musicButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [self.musicButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [self.musicButton setTitleColor:PLS_RGBCOLOR(65, 154, 208) forState:UIControlStateSelected]; [self.musicButton addTarget:self action:@selector(musicButtonOnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.rightScrollView addSubview:self.musicButton]; - index ++; - // 30FPS/60FPS - self.frameRateButton = [[UIButton alloc] initWithFrame:CGRectMake(0, index * 60 + 10, 46, 46)]; - self.frameRateButton.layer.cornerRadius = 23; - self.frameRateButton.backgroundColor = backgroundColor; - [self.frameRateButton setTitle:@"30帧" forState:(UIControlStateNormal)]; - self.frameRateButton.titleLabel.font = [UIFont systemFontOfSize:14]; - [self.frameRateButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - [self.frameRateButton addTarget:self action:@selector(frameRateButtonOnClick:) forControlEvents:UIControlEventTouchUpInside]; - [self.rightScrollView addSubview:self.frameRateButton]; - - index ++; - //是否开启 SDK 退到后台监听 - self.monitorButton = [UIButton buttonWithType:UIButtonTypeCustom]; - self.monitorButton.layer.cornerRadius = 23; - self.monitorButton.backgroundColor = backgroundColor; - [self.monitorButton setTitle:@"监听关" forState:UIControlStateNormal]; - [self.monitorButton setTitle:@"监听开" forState:UIControlStateSelected]; - self.monitorButton.selected = NO; - [self.monitorButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - self.monitorButton.titleLabel.font = [UIFont systemFontOfSize:14]; - [self.monitorButton sizeToFit]; - self.monitorButton.frame = CGRectMake(0, index * 60 + 10, 46, 46); - [self.monitorButton addTarget:self action:@selector(monitorButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; - [self.rightScrollView addSubview:self.monitorButton]; - index ++; [self.view addSubview:self.rightScrollView]; self.rightScrollView.contentSize = CGSizeMake(60, index * 60 + 10); @@ -458,9 +438,12 @@ - (void)setupRecordToolboxView { // 录制视频的操作按钮 CGFloat buttonWidth = 80.0f; self.recordButton = [UIButton buttonWithType:UIButtonTypeCustom]; + self.recordButton.layer.cornerRadius = buttonWidth/2; + self.recordButton.layer.borderWidth = 5; + self.recordButton.layer.borderColor = [UIColor whiteColor].CGColor; + self.recordButton.backgroundColor = PLS_RGBCOLOR(65, 154, 208); self.recordButton.frame = CGRectMake(0, 0, buttonWidth, buttonWidth); self.recordButton.center = CGPointMake(PLS_SCREEN_WIDTH / 2, self.recordToolboxView.frame.size.height - 80); - [self.recordButton setImage:[UIImage imageNamed:@"btn_record_a"] forState:UIControlStateNormal]; [self.recordButton addTarget:self action:@selector(recordButtonEvent:) forControlEvents:UIControlEventTouchUpInside]; [self.recordToolboxView addSubview:self.recordButton]; @@ -559,7 +542,7 @@ - (void)getFirstMovieFromPhotoAlbum { // 返回上一层 - (void)backButtonEvent:(id)sender { - if (self.viewRecordButton.isSelected) { + if (self.isViewRecord) { [self.viewRecorderManager cancelRecording]; [self.screenRecorderManager cancelRecording]; } @@ -602,40 +585,25 @@ - (void)squareRecordButtonEvent:(id)sender { } //录制 self.view -- (void)viewRecorderButtonClick:(id)sender { +- (void)viewRecorder { if (@available(iOS 11.0, *)) { if (!self.screenRecorderManager) { self.screenRecorderManager = [[PLScreenRecorderManager alloc] init]; self.screenRecorderManager.delegate = self; } - if (self.viewRecordButton.isSelected) { - self.viewRecordButton.selected = NO; - [self.screenRecorderManager stopRecording]; - } else { - self.viewRecordButton.selected = YES; - [self.screenRecorderManager startRecording]; - } + [self.screenRecorderManager startRecording]; } else { if (!self.viewRecorderManager) { self.viewRecorderManager = [[PLSViewRecorderManager alloc] initWithRecordedView:self.shortVideoRecorder.previewView]; self.viewRecorderManager.delegate = self; } + [self.viewRecorderManager startRecording]; - if (self.viewRecordButton.isSelected) { - self.viewRecordButton.selected = NO; - [self.viewRecorderManager stopRecording]; - - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; - } - else { - self.viewRecordButton.selected = YES; - [self.viewRecorderManager startRecording]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(applicationWillResignActive:) - name:UIApplicationWillResignActiveNotification - object:nil]; - }} + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(applicationWillResignActive:) + name:UIApplicationWillResignActiveNotification + object:nil]; + } } // 打开/关闭闪光灯 @@ -678,7 +646,23 @@ - (void)toggleCameraButtonEvent:(UIButton *)sender { // 七牛滤镜 - (void)filterButtonEvent:(UIButton *)button { button.selected = !button.selected; - self.editVideoCollectionView.hidden = !button.selected; + CGFloat height = CGRectGetHeight(self.editVideoCollectionView.frame); + if (button.selected) { + [self.view insertSubview:self.editVideoCollectionView aboveSubview:self.view.subviews.lastObject]; + [UIView animateWithDuration:0.5 animations:^{ + self.editVideoCollectionView.frame = CGRectMake(0, PLS_SCREEN_HEIGHT - height, PLS_SCREEN_WIDTH, height); + } completion:^(BOOL finished) { + [self.editVideoCollectionView reloadData]; + }]; + } else { + [UIView animateWithDuration:1 animations:^{ + self.editVideoCollectionView.frame = CGRectMake(0, PLS_SCREEN_HEIGHT, PLS_SCREEN_WIDTH, height); + } completion:^(BOOL finished) { + [self.editVideoCollectionView reloadData]; + [self.editVideoCollectionView removeFromSuperview]; + }]; + } + } // 加载草稿视频 @@ -719,15 +703,11 @@ - (void)musicButtonOnClick:(id)sender { - (void)frameRateButtonOnClick:(UIButton *)button { if (60 == self.videoConfiguration.videoFrameRate) { self.videoConfiguration.videoFrameRate = 30; - self.videoConfiguration.averageVideoBitRate = 1000 * 2500; self.videoConfiguration.sessionPreset = AVCaptureSessionPreset1280x720; - [button setTitle:@"30帧" forState:(UIControlStateNormal)]; [self.shortVideoRecorder reloadvideoConfiguration:self.videoConfiguration]; } else { self.videoConfiguration.videoFrameRate = 60; - self.videoConfiguration.averageVideoBitRate = 1000 * 3500; self.videoConfiguration.sessionPreset = AVCaptureSessionPresetInputPriority; - [button setTitle:@"60帧" forState:(UIControlStateNormal)]; [self.shortVideoRecorder reloadvideoConfiguration:self.videoConfiguration]; [self checkActiveFormat]; } @@ -830,7 +810,6 @@ - (void)endButtonEvent:(id)sender { [self playEvent:asset]; [self.viewRecorderManager cancelRecording]; [self.screenRecorderManager cancelRecording]; - self.viewRecordButton.selected = NO; } // 取消录制 @@ -842,14 +821,14 @@ - (void)discardRecord { // 导入视频 - (void)importMovieButtonEvent:(id)sender { PhotoAlbumViewController *photoAlbumViewController = [[PhotoAlbumViewController alloc] init]; + photoAlbumViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:photoAlbumViewController animated:YES completion:nil]; } #pragma mark - Notification - (void)applicationWillResignActive:(NSNotification *)notification { - if (self.viewRecordButton.selected) { + if (self.isViewRecord) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; - self.viewRecordButton.selected = NO; [self.viewRecorderManager cancelRecording]; } } @@ -904,7 +883,7 @@ - (void)rateButtonView:(PLSRateButtonView *)rateButtonView didSelectedTitleIndex #pragma mark - PLSViewRecorderManagerDelegate - (void)viewRecorderManager:(PLSViewRecorderManager *)manager didFinishRecordingToAsset:(AVAsset *)asset totalDuration:(CGFloat)totalDuration { - self.viewRecordButton.selected = NO; + self.isViewRecord = NO; // 设置音视频、水印等编辑信息 NSMutableDictionary *outputSettings = [[NSMutableDictionary alloc] init]; // 待编辑的原始视频素材 @@ -917,12 +896,13 @@ - (void)viewRecorderManager:(PLSViewRecorderManager *)manager didFinishRecording EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:videoEditViewController animated:YES completion:nil]; } #pragma mark - PLScreenRecorderManagerDelegate - (void)screenRecorderManager:(PLScreenRecorderManager *)manager didFinishRecordingToAsset:(AVAsset *)asset totalDuration:(CGFloat)totalDuration { - self.viewRecordButton.selected = NO; + self.isViewRecord = NO; // 设置音视频、水印等编辑信息 NSMutableDictionary *outputSettings = [[NSMutableDictionary alloc] init]; // 待编辑的原始视频素材 @@ -935,6 +915,7 @@ - (void)screenRecorderManager:(PLScreenRecorderManager *)manager didFinishRecord EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:videoEditViewController animated:YES completion:nil]; } @@ -942,7 +923,7 @@ - (void)screenRecorderManager:(PLScreenRecorderManager *)manager errorOccur:(NSE NSString *message = [NSString stringWithFormat:@"%@", error]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"错误" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil]; [alert show]; - self.viewRecordButton.selected = NO; + self.isViewRecord = NO; } #pragma mark -- PLShortVideoRecorderDelegate 摄像头/麦克风鉴权的回调 @@ -975,8 +956,14 @@ - (CVPixelBufferRef)shortVideoRecorder:(PLShortVideoRecorder *)recorder cameraSo //此处可以做美颜/滤镜等处理 // 是否在录制时使用滤镜,默认是关闭的,NO if (self.isUseFilterWhenRecording) { - PLSFilter *filter = self.filterGroup.currentFilter; - pixelBuffer = [filter process:pixelBuffer]; + // 进行滤镜处理 + if (self.isPanning) { + // 正在滤镜切换过程中,使用 processPixelBuffer:leftPercent:leftFilter:rightFilter 做滤镜切换动画 + pixelBuffer = [self.filterGroup processPixelBuffer:pixelBuffer leftPercent:self.leftPercent leftFilter:self.leftFilter rightFilter:self.rightFilter]; + } else { + // 正常滤镜处理 + pixelBuffer = [self.filterGroup.currentFilter process:pixelBuffer]; + } } return pixelBuffer; @@ -1057,7 +1044,7 @@ - (void)shortVideoRecorder:(PLShortVideoRecorder *)recorder didFinishRecordingMa AVAsset *asset = self.shortVideoRecorder.assetRepresentingAllFiles; [self playEvent:asset]; [self.viewRecorderManager cancelRecording]; - self.viewRecordButton.selected = NO; + self.isViewRecord = NO; } #pragma mark -- 下一步 @@ -1114,6 +1101,7 @@ - (void)playEvent:(AVAsset *)asset { EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; videoEditViewController.filesURLArray = filesURLArray; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:videoEditViewController animated:YES completion:nil]; } #pragma mark - 输出路径 @@ -1148,11 +1136,6 @@ - (void)removeActivityIndicatorView { [self.activityIndicatorView stopAnimating]; } -#pragma mark -- 隐藏状态栏 -- (BOOL)prefersStatusBarHidden { - return YES; -} - - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. @@ -1189,8 +1172,8 @@ - (UICollectionView *)editVideoCollectionView { layout.minimumLineSpacing = 10; layout.minimumInteritemSpacing = 10; - _editVideoCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, PLS_SCREEN_WIDTH, layout.itemSize.height) collectionViewLayout:layout]; - _editVideoCollectionView.backgroundColor = [UIColor clearColor]; + _editVideoCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, PLS_SCREEN_HEIGHT, PLS_SCREEN_WIDTH, layout.itemSize.height) collectionViewLayout:layout]; + _editVideoCollectionView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3]; _editVideoCollectionView.showsHorizontalScrollIndicator = NO; _editVideoCollectionView.showsVerticalScrollIndicator = NO; @@ -1224,61 +1207,152 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell } - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - // 滤镜 self.filterGroup.filterIndex = indexPath.row; + NSArray *array = @[]; + NSDictionary *dic = self.filtersArray[indexPath.row]; + [self.filterButton setTitle:[NSString stringWithFormat:@"滤镜: %@", dic[@"name"]] forState:UIControlStateNormal]; } #pragma mark - 通过手势切换滤镜 - (void)setupGestureRecognizer { - UISwipeGestureRecognizer *recognizer; - // 添加右滑手势 - recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; - [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)]; - [self.view addGestureRecognizer:recognizer]; - // 添加左滑手势 - recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; - [recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)]; - [self.view addGestureRecognizer:recognizer]; - // 添加上滑手势 - recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; - [recognizer setDirection:(UISwipeGestureRecognizerDirectionUp)]; - [self.view addGestureRecognizer:recognizer]; - // 添加下滑手势 - recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; - [recognizer setDirection:(UISwipeGestureRecognizerDirectionDown)]; - [self.view addGestureRecognizer:recognizer]; + UIPanGestureRecognizer * panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleFilterPan:)]; + [self.view addGestureRecognizer:panGesture]; } // 添加手势的响应事件 -- (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer{ - if(recognizer.direction == UISwipeGestureRecognizerDirectionDown) { - NSLog(@"swipe down"); - self.filterIndex++; - self.filterIndex %= self.filterGroup.filtersInfo.count; - } - if(recognizer.direction == UISwipeGestureRecognizerDirectionUp) { - NSLog(@"swipe up"); - self.filterIndex--; - if (self.filterIndex < 0) { - self.filterIndex = self.filterGroup.filtersInfo.count - 1; +- (void)handleFilterPan:(UIPanGestureRecognizer *)gestureRecognizer { + + CGPoint transPoint = [gestureRecognizer translationInView:gestureRecognizer.view]; + CGPoint speed = [gestureRecognizer velocityInView:gestureRecognizer.view]; + + switch (gestureRecognizer.state) { + + /*! + 手势开始的时候,根据手势的滑动方向,确定切换到下一个滤镜的索引值 + */ + case UIGestureRecognizerStateBegan: { + NSInteger index = 0; + if (speed.x > 0) { + self.isLeftToRight = YES; + index = self.filterGroup.filterIndex - 1; + } else { + index = self.filterGroup.filterIndex + 1; + self.isLeftToRight = NO; + } + + if (index < 0) { + index = self.filterGroup.filtersInfo.count - 1; + } else if (index >= self.filterGroup.filtersInfo.count) { + index = index - self.filterGroup.filtersInfo.count; + } + self.filterGroup.nextFilterIndex = index; + + if (self.isLeftToRight) { + self.leftFilter = self.filterGroup.nextFilter; + self.rightFilter = self.filterGroup.currentFilter; + self.leftPercent = 0.0; + } else { + self.leftFilter = self.filterGroup.currentFilter; + self.rightFilter = self.filterGroup.nextFilter; + self.leftPercent = 1.0; + } + self.isPanning = YES; + + break; } - } - if(recognizer.direction == UISwipeGestureRecognizerDirectionLeft) { - NSLog(@"swipe left"); - self.filterIndex--; - if (self.filterIndex < 0) { - self.filterIndex = self.filterGroup.filtersInfo.count - 1; + + /*! + 手势变化的过程中,根据滑动的距离来确定两个滤镜所占的百分比 + */ + case UIGestureRecognizerStateChanged: { + if (self.isLeftToRight) { + if (transPoint.x <= 0) { + transPoint.x = 0; + } + self.leftPercent = transPoint.x / gestureRecognizer.view.bounds.size.width; + self.isNeedChangeFilter = (self.leftPercent >= 0.5) || (speed.x > 500 ); + } else { + if (transPoint.x >= 0) { + transPoint.x = 0; + } + self.leftPercent = 1 - fabs(transPoint.x) / gestureRecognizer.view.bounds.size.width; + self.isNeedChangeFilter = (self.leftPercent <= 0.5) || (speed.x < -500); + } + break; } + + /*! + 手势结束的时候,根据滑动距离,判断是否切换到下一个滤镜,并且做一下切换的动画 + */ + case UIGestureRecognizerStateEnded: + case UIGestureRecognizerStateCancelled: + case UIGestureRecognizerStateFailed: { + gestureRecognizer.enabled = NO; + + // 做一个滤镜过渡动画,优化用户体验 + dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC, 0.005 * NSEC_PER_SEC); + dispatch_source_set_event_handler(timer, ^{ + if (!self.isPanning) return; + + float delta = 0.03; + if (self.isNeedChangeFilter) { + // apply filter change + if (self.isLeftToRight) { + self.leftPercent = MIN(1, self.leftPercent + delta); + } else { + self.leftPercent = MAX(0, self.leftPercent - delta); + } + } else { + // cancel filter change + if (self.isLeftToRight) { + self.leftPercent = MAX(0, self.leftPercent - delta); + } else { + self.leftPercent = MIN(1, self.leftPercent + delta); + } + } + + if (self.leftPercent < FLT_EPSILON || fabs(1.0 - self.leftPercent) < FLT_EPSILON) { + dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_source_cancel(timer); + if (self.isNeedChangeFilter) { + self.filterGroup.filterIndex = self.filterGroup.nextFilterIndex; + } + self.isPanning = NO; + self.isNeedChangeFilter = NO; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + gestureRecognizer.enabled = YES; + }); + }); + } + }); + dispatch_resume(timer); + break; + } + + case UIGestureRecognizerStatePossible: { + NSLog(@"UIGestureRecognizerStatePossible"); + } break; + + default: + break; } - if(recognizer.direction == UISwipeGestureRecognizerDirectionRight) { - NSLog(@"swipe right"); - self.filterIndex++; - self.filterIndex %= self.filterGroup.filtersInfo.count; - } +} + +#pragma mark - 较高质量下,不同分辨率对应的码率值取值 +- (NSInteger)suitableVideoBitrateWithSize:(CGSize)videoSize { - // 滤镜 - self.filterGroup.filterIndex = self.filterIndex; + // 下面的码率设置均偏大,为了拍摄出来的视频更清晰,选择了偏大的码率,不过均比系统相机拍摄出来的视频码率小很多 + if (videoSize.width + videoSize.height > 720 + 1280) { + return 8 * 1000 * 1000; + } else if (videoSize.width + videoSize.height > 544 + 960) { + return 4 * 1000 * 1000; + } else if (videoSize.width + videoSize.height > 360 + 640) { + return 2 * 1000 * 1000; + } else { + return 1 * 1000 * 1000; + } } #pragma mark - addObserverEvent diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.m b/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.m index da67a87e..a053bbb9 100644 --- a/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.m +++ b/Example/PLShortVideoKitDemo/SegmentEffects/BaseViewController.m @@ -10,10 +10,7 @@ #import #import -#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 diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.h b/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.h index c6863758..da016e8e 100644 --- a/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.h +++ b/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.h @@ -6,7 +6,7 @@ // Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. // -#import "BaseViewController.h" + @interface MulitClipViewController : BaseViewController diff --git a/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.m b/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.m index 9f9de124..82e74832 100644 --- a/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.m +++ b/Example/PLShortVideoKitDemo/SegmentEffects/MulitClipViewController.m @@ -335,6 +335,8 @@ - (void)clipView:(PLSClipMulitMediaView *)clipView insertVideoWithAsset:(AVAsset transitionController.backgroundVideoURL = [(AVURLAsset *)asset URL]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:transitionController]; transitionController.delegate = self; + transitionController.modalPresentationStyle = UIModalPresentationFullScreen; + navigationController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:navigationController animated:YES completion:nil]; }]; @@ -393,6 +395,7 @@ - (void)clipView:(PLSClipMulitMediaView *)clipView finishClip:(NSArray -#import "BaseViewController.h" #import "PLShortVideoKit/PLShortVideoKit.h" #ifndef MAS_SHORTHAND_GLOBALS diff --git a/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerOverlayView.h b/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerOverlayView.h index 05661a9f..ea5cb82a 100644 --- a/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerOverlayView.h +++ b/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerOverlayView.h @@ -1,13 +1,97 @@ // // PLSStickerOverlayView.h -// PLVideoEditor +// PLShortVideoKitDemo // -// Created by suntongmian on 2018/5/24. -// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// Created by 冯文秀 on 2019/8/19. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. // #import +#import "PLSStickerView.h" + +@class PLSStickerOverlayView; + +@protocol PLSStickerOverlayViewDelegate + +/** + 点击当前贴图的关闭按钮回调 + + @param stickerOverlayView PLSStickerOverlayView 实例 + @param stickerView 被点击的贴图 + */ +- (void)stickerOverlayView:(PLSStickerOverlayView *_Nonnull)stickerOverlayView didClickClose:(PLSStickerView *_Nonnull)stickerView; + +/** + 当前贴图被移除后的回调 + + @param stickerOverlayView PLSStickerOverlayView 实例 + @param sticker 被移除的贴图 + @param currentSticker 被移除贴图的前一个贴图 + */ +- (void)stickerOverlayView:(PLSStickerOverlayView *_Nonnull)stickerOverlayView didRemovedSticker:(PLSStickerView *_Nonnull)sticker currentSticker:(PLSStickerView *_Nullable)currentSticker; + +/** + 已加载的某贴图被点击选中的回调 + + @param stickerOverlayView PLSStickerOverlayView 实例 + @param sticker 被点击的贴图 + @param tap 点击手势本身 + */ +- (void)stickerOverlayView:(PLSStickerOverlayView *_Nonnull)stickerOverlayView didTapSticker:(PLSStickerView *_Nonnull)sticker tap:(UITapGestureRecognizer*_Nonnull)tap; + +@end + +NS_ASSUME_NONNULL_BEGIN + +/** + * 贴纸的位置 + */ +typedef NS_ENUM(NSInteger, PositionMode){ + PositionMode_All_Center, // 垂直居中 + 水平居中 + PositionMode_Ver_Center, // 垂直居中 + PositionMode_Hor_Center, // 水平居中 + PositionMode_Top, // 顶部 + PositionMode_Bottom, // 底部 + PositionMode_Left, // 左边 + PositionMode_Right, // 右边 +}; + @interface PLSStickerOverlayView : UIView +@property (nonatomic, assign) iddelegate; +@property (nonatomic, assign) PositionMode positionMode; // 操作当前 sticker 的位置模式 +@property (nonatomic, strong, readonly) UIView *layoutView; +@property (nonatomic, strong) PLSStickerView *currentSticker; +@property (nonatomic, strong, readonly) NSArray *stickersArray; + +/** + PLSStickerOverlayView 初始化方法 + + @param frame 位置 + @param layoutView 需要显示的父视图 + @return PLSStickerOverlayView 实例 + */ +- (instancetype)initWithFrame:(CGRect)frame layoutView:(UIView *)layoutView; + +/** + 添加贴图 + + @param sticker 需要添加的贴图 + @param positionMode 添加后显示的位置 + */ +- (void)addSticker:(PLSStickerView *)sticker positionMode:(PositionMode)positionMode; + +/** + 取消当前的贴图,执行后将触发回调 - (void)stickerOverlayView:(PLSStickerOverlayView *_Nonnull)stickerOverlayView didRemovedSticker:(PLSStickerView *_Nonnull)sticker currentSticker:(PLSStickerView *_Nullable)currentSticker; + */ +- (void)cancelCurrentSticker; + +/** + 移除当前 overlayView 上所有的贴图 + */ +- (void)clearAllStickers; + @end + +NS_ASSUME_NONNULL_END diff --git a/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerOverlayView.m b/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerOverlayView.m index df3d333d..58b028bf 100644 --- a/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerOverlayView.m +++ b/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerOverlayView.m @@ -1,15 +1,131 @@ // // PLSStickerOverlayView.m -// PLVideoEditor +// PLShortVideoKitDemo // -// Created by suntongmian on 2018/5/24. -// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// Created by 冯文秀 on 2019/8/19. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. // #import "PLSStickerOverlayView.h" +@interface PLSStickerOverlayView() +< +PLSStickerViewDelegate +> + +@property (nonatomic, strong, readwrite) UIView *layoutView; +@property (nonatomic, strong) NSMutableArray *stickers; + +@property (nonatomic, assign) CGPoint loc_in; +@property (nonatomic, assign) CGPoint ori_center; + +@end + @implementation PLSStickerOverlayView +- (instancetype)initWithFrame:(CGRect)frame layoutView:(UIView *)layoutView { + self = [super initWithFrame:frame]; + if (self) { + self.layoutView = layoutView; + [self.layoutView addSubview:self]; + + self.stickers = [NSMutableArray array]; + self.positionMode = PositionMode_All_Center; + } + return self; +} + +- (void)setPositionMode:(PositionMode)positionMode { + if (positionMode == self.positionMode) { + return; + } + _positionMode = positionMode; + + [self adjustPositionWithPositionMode:positionMode]; +} + +- (NSArray *)stickersArray { + return [NSArray arrayWithArray:_stickers]; +} + +#pragma mark - PLSStickerViewDelegate + +- (void)stickerView:(PLSStickerView *)stickerView startTextEdit:(UITapGestureRecognizer *)tapGestureRecognizer { + self.currentSticker = stickerView; + self.currentSticker.isSelected = YES; + [self.currentSticker becomeFirstResponder]; +} + +#pragma mark - public + +- (void)addSticker:(PLSStickerView *)sticker positionMode:(PositionMode)positionMode{ + if ([self.stickers containsObject:sticker]) { + return; + } else{ + self.currentSticker.isSelected = NO; + + sticker.delegate = self; + [self adjustPositionWithPositionMode:positionMode]; + [self addSubview:sticker]; + [self.stickers addObject:sticker]; + sticker.isSelected = YES; + self.currentSticker = sticker; + } + +} + +- (void)cancelCurrentSticker { + PLSStickerView *baseSticker = _currentSticker; + [self.stickers removeObject:baseSticker]; + [self.currentSticker removeFromSuperview]; + _currentSticker = self.stickers.lastObject; + if (self.delegate && [self.delegate respondsToSelector:@selector(stickerOverlayView:didRemovedSticker:currentSticker:)]) { + [self.delegate stickerOverlayView:self didRemovedSticker:baseSticker currentSticker:_currentSticker]; + } +} + +- (void)clearAllStickers { + self.stickers = [NSMutableArray array]; + self.currentSticker = [[PLSStickerView alloc] init]; +} + +#pragma mark - private + +- (void)adjustPositionWithPositionMode:(PositionMode)positionMode { + CGFloat totalWidth = CGRectGetWidth(self.frame); + CGFloat totalHeight = CGRectGetHeight(self.frame); + + CGFloat width = CGRectGetWidth(self.currentSticker.frame); + CGFloat height = CGRectGetHeight(self.currentSticker.frame); + + switch (positionMode) { + case PositionMode_All_Center: + self.currentSticker.frame = CGRectMake(totalWidth/2 - width/2, totalHeight/2 - height/2, width, height); + break; + case PositionMode_Ver_Center: + self.currentSticker.frame = CGRectMake(self.currentSticker.frame.origin.x, totalHeight/2 - height/2, width, height); + break; + case PositionMode_Hor_Center: + self.currentSticker.frame = CGRectMake(totalWidth/2 - width/2, self.currentSticker.frame.origin.y, width, height); + break; + case PositionMode_Top: + self.currentSticker.frame = CGRectMake(self.currentSticker.frame.origin.x, 0, width, height); + break; + case PositionMode_Bottom: + self.currentSticker.frame = CGRectMake(self.currentSticker.frame.origin.x, totalHeight - height, width, height); + break; + case PositionMode_Left: + self.currentSticker.frame = CGRectMake(0, self.currentSticker.frame.origin.y, width, height); + break; + case PositionMode_Right: + self.currentSticker.frame = CGRectMake(totalWidth - width, self.currentSticker.frame.origin.y, width, height); + break; + + default: + break; + } +} + - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ __block UIView *responseView = nil; [self.subviews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(__kindof UIView * _Nonnull subView, NSUInteger idx, BOOL * _Nonnull stop) { @@ -23,4 +139,12 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ return responseView ? responseView : nil; } +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect { + // Drawing code +} +*/ + @end diff --git a/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerView.h b/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerView.h index 94c6e338..94e77467 100644 --- a/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerView.h +++ b/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerView.h @@ -1,67 +1,122 @@ // // PLSStickerView.h -// PLVideoEditor +// PLShortVideoKitDemo // -// Created by suntongmian on 2018/5/24. -// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// Created by 冯文秀 on 2019/8/16. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. // #import @class PLSStickerView; + @protocol PLSStickerViewDelegate -@optional -- (void)stickerViewClose:(PLSStickerView *)stickerView; +/** + 双击文字贴纸编辑文本 + + @param stickerView 贴纸视图 + @param tapGestureRecognizer 双击手势 + */ +- (void)stickerView:(PLSStickerView *_Nonnull)stickerView startTextEdit:(UITapGestureRecognizer *_Nonnull)tapGestureRecognizer; @end +NS_ASSUME_NONNULL_BEGIN + /** * 贴纸类型 */ typedef NS_ENUM(NSInteger, StickerType){ - StickerType_SubTitle, // 文字 - StickerType_Sticker, // 图片 - StickerType_GIFAnimation, // GIF + StickerType_Text, // 文字 + StickerType_Image, // 图片 + StickerType_Gif, // GIF +}; + +/** + * 操作icon 的位置 + */ +typedef NS_ENUM(NSInteger, IconPosition){ + IconPosition_Left_Top, // 左上 + IconPosition_Right_Top, // 右上 + IconPosition_Left_Bottom, // 左下 + IconPosition_Right_Bottom, // 右下 +}; + +/** + * 文本对齐方式 + */ +typedef NS_ENUM(NSInteger, TextAlignment){ + TextAlignment_Center, // 居中 + TextAlignment_Left, // 靠左 + TextAlignment_Right, // 靠右 }; @interface PLSStickerView : UIImageView -#pragma mark - UI -@property (nonatomic) UIButton *closeBtn; -@property (nonatomic) UIImageView *dragBtn; -@property (nonatomic, assign) id delegate; -@property (nonatomic, readonly) NSURL *stickerURL; +@property (nonatomic, assign) id delegate; + +@property (nonatomic, assign) BOOL isSelected; +@property (nonatomic, assign) StickerType stickerType; -#pragma mark - -@property (nonatomic, assign) StickerType type; -// 选中后出现边框 -@property (nonatomic, assign, getter=isSelected) BOOL select; +// 自定义边框参数 +@property (nonatomic, assign) CGFloat layerWidth; +@property (nonatomic, assign) CGFloat layerCornerRadius; +@property (nonatomic, strong) UIColor *layerColor; -#pragma mark - Functions +@property (nonatomic, strong) UIImage *layerImage; // 边框图片 -// 创建文字贴纸 -- (instancetype)initSubTextSticker:(UIImage *)image; +@property (nonatomic, assign) IconPosition closePosition; // 默认右上 +@property (nonatomic, assign) IconPosition scalePosition; // 默认右下 -// 创建图片贴纸 -- (instancetype)initImageSticker:(NSURL *)imgURL; -// 创建 GIF 贴纸 -- (instancetype)initGifSticker:(NSURL *)gifURL; +// StickerType 为 StickerType_Image/StickerType_Gif 下可用 +@property (nonatomic, strong) NSURL *stickerURL; +@property (nonatomic, assign) CGFloat layoutSpace; // 0.5 ~ 8 +@property (nonatomic, strong, readonly) UIImage *stickerImage; + +// StickerType 为 StickerType_Text 下可用 +@property (nonatomic, strong) UIFont *textFont; +@property (nonatomic, strong) UIColor *textColor; +@property (nonatomic, copy) NSString *textContent; +@property (nonatomic, assign) TextAlignment textAlignment; // 默认居中 + + +// StickerType 为非 StickerType_Text 下的初始化方法 +- (instancetype)initWithFrame:(CGRect)frame stickerType:(StickerType)type stickerURL:(NSURL *)stickerURL; + +// StickerType 为 StickerType_Text 时的初始化方法 +- (instancetype)initWithFrame:(CGRect)frame content:(NSString *)content font:(UIFont *)font color:(UIColor *)color; + /** - 根据气泡类型,设置字符显示区域 - (需要用户根据自己的气泡设置显示区域) - @param name 气泡名称 + 设置缩放按钮图标以及大小 + + @param image 显示图标 + @param selectedImage 选中图标 + @param size 大小 */ -- (void)calcInputRectWithImgName:(NSString *)name; +- (void)setScaleImage:(UIImage *)image selectedImage:(UIImage *)selectedImage size:(CGSize)size; -- (void)close:(id)sender; -#pragma mark - Reserved +/** + 设置缩放的最小值以及最大值 -@property (nonatomic, assign) CGFloat oriScale; + @param minValue 可缩放到最小的值 + @param maxValue 可缩放到最大的值 + */ +- (void)setScaleMinScaleValue:(CGFloat)minValue maxScaleValue:(CGFloat)maxValue; + + +/** + 设置关闭按钮图标以及大小 -@property (nonatomic, assign) CGAffineTransform oriTransform; + @param image 显示图标 + @param selectedImage 选中图标 + @param size 大小 + */ +- (void)setCloseImage:(UIImage *)image selectedImage:(UIImage *)selectedImage size:(CGSize)size; @end + +NS_ASSUME_NONNULL_END diff --git a/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerView.m b/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerView.m index 532d5c80..199f4646 100644 --- a/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerView.m +++ b/Example/PLShortVideoKitDemo/StickerToolbox/StickerView/PLSStickerView.m @@ -1,279 +1,370 @@ // // PLSStickerView.m -// PLVideoEditor +// PLShortVideoKitDemo // -// Created by suntongmian on 2018/5/24. -// Copyright © 2018年 Pili Engineering, Qiniu Inc. All rights reserved. +// Created by 冯文秀 on 2019/8/16. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. // #import "PLSStickerView.h" +#import "PLSStickerOverlayView.h" -#define kPLSStickerViewBtnLength 16 +@class PLSStickerOverlay; -@interface PLSStickerView () +@interface PLSStickerView() < UITextViewDelegate > -@property (nonatomic) UITextView *tf; +@property (nonatomic, assign) CGFloat stickerWidth; +@property (nonatomic, assign) CGFloat stickerHeight; -@property (nonatomic) UILabel *lb; -// 写入范围 -@property (nonatomic, assign) CGRect inputRect; +@property (nonatomic, strong) UIButton *closeButton; +@property (nonatomic, strong) UIButton *scaleButton; + +@property (nonatomic, assign) CGPoint loc_in; +@property (nonatomic, assign) CGPoint ori_center; + +@property (nonatomic, assign) CGAffineTransform currentTransform; +@property (nonatomic, assign) CGFloat currentScale; + +@property (nonatomic, assign) CGFloat minValue; +@property (nonatomic, assign) CGFloat maxValue; + +// StickerType_Image/StickerType_Gif +@property (nonatomic, strong, readwrite) UIImage *stickerImage; +@property (nonatomic, strong) UIImageView *imageView; + +// StickerType_Text +@property (nonatomic, strong) UITextView *textView; +@property (nonatomic, strong) UILabel *textLabel; -@property (nonatomic, strong, readwrite) NSURL *stickerURL; -@property (nonatomic, strong) NSMutableArray *allImage; @end @implementation PLSStickerView -- (instancetype)initSubTextSticker:(UIImage *)image { - return [self initWithImage:image Type:(StickerType_SubTitle)]; -} +#pragma mark - init -- (instancetype)initImageSticker:(NSURL *)imgURL { - _stickerURL = imgURL; - return [self initWithImage:[UIImage imageWithContentsOfFile:imgURL.path] Type:(StickerType_Sticker)]; +- (instancetype)initWithFrame:(CGRect)frame stickerType:(StickerType)type stickerURL:(NSURL *)stickerURL { + self = [super initWithFrame:frame]; + if (self) { + self.stickerURL = stickerURL; + + self.stickerType = type; + self.layoutSpace = 4; + + CGFloat width = CGRectGetWidth(frame); + CGFloat height = CGRectGetHeight(frame); + + self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.layoutSpace, self.layoutSpace, width - self.layoutSpace * 2, height - self.layoutSpace * 2)]; + self.imageView.contentMode = UIViewContentModeScaleAspectFit; + self.imageView.userInteractionEnabled = YES; + + if (type == StickerType_Image) { + self.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:stickerURL]]; + } else { + [self setGifSource]; + } + self.stickerImage = self.imageView.image; + + [self insertSubview:self.imageView atIndex:0]; + } + return [self initWithFrame:frame stickerType:type]; } -- (instancetype)initWithImage:(UIImage *)image Type:(StickerType)type{ - if (self = [super initWithImage:image]) { - self.userInteractionEnabled = YES; - _type = type; - _oriScale = 1.0; +- (instancetype)initWithFrame:(CGRect)frame content:(NSString *)content font:(UIFont *)font color:(UIColor *)color { + self = [super initWithFrame:frame]; + if (self) { + self.stickerType = StickerType_Text; + + self.textFont = font; + self.textColor = color; + self.textAlignment = TextAlignment_Center; + self.textContent = content; + + self.textLabel = [[UILabel alloc] initWithFrame:self.bounds]; + self.textLabel.font = self.textFont; + self.textLabel.textColor = self.textColor; + self.textLabel.textAlignment = NSTextAlignmentCenter; + self.textLabel.text = self.textContent; + self.textLabel.userInteractionEnabled = YES; + self.textLabel.adjustsFontSizeToFitWidth = YES; + [self insertSubview:self.textLabel atIndex:0]; + + self.textView = [[UITextView alloc] initWithFrame:CGRectZero]; + self.textView.delegate = self; + self.textView.returnKeyType = UIReturnKeyContinue; + self.textView.font = self.textFont; + self.textView.textColor = self.textColor; + self.textView.textAlignment = NSTextAlignmentCenter; + self.textView.text = self.textContent; + [self addSubview:_textView]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextViewTextDidChangeNotification object:nil]; - [self setupUI]; + UITapGestureRecognizer *doubleTapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(startTextEditing:)]; + doubleTapGes.numberOfTapsRequired = 2; + [self.textLabel addGestureRecognizer:doubleTapGes]; } - return self; + return [self initWithFrame:frame stickerType:StickerType_Text]; } -- (instancetype)initGifSticker:(NSURL *)gifURL { - self = [super init]; +- (instancetype)initWithFrame:(CGRect)frame stickerType:(StickerType)type { + self = [super initWithFrame:frame]; if (self) { self.userInteractionEnabled = YES; - _type = StickerType_GIFAnimation; - _stickerURL = gifURL; - _oriScale = 1.0; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextViewTextDidChangeNotification object:nil]; + self.stickerWidth = CGRectGetWidth(frame); + self.stickerHeight = CGRectGetHeight(frame); + + self.stickerType = type; + self.layerWidth = 0.8; + self.layerCornerRadius = 3; + self.layerColor = [UIColor colorWithRed:100 green:149 blue:237 alpha:1]; + self.isSelected = YES; + self.layerImage = [[UIImage alloc] init]; + + self.closePosition = IconPosition_Right_Top; + self.scalePosition = IconPosition_Right_Bottom; + + self.layer.borderWidth = self.layerWidth; + self.layer.cornerRadius = self.layerCornerRadius; + self.layer.borderColor = self.layerColor.CGColor; + + self.closeButton = [[UIButton alloc] initWithFrame:CGRectMake(self.stickerWidth - 12, -12, 24, 24)]; + [self.closeButton setImage:[UIImage imageNamed:@"sticker_delete"] forState:UIControlStateNormal]; + [self.closeButton addTarget:self action:@selector(closeButtonClicked) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:_closeButton]; + + self.scaleButton = [[UIButton alloc] initWithFrame:CGRectMake(self.stickerWidth - 12, self.stickerHeight - 12, 24, 24)]; + [self.scaleButton setImage:[UIImage imageNamed:@"sticker_rotate"] forState:UIControlStateNormal]; + [self.scaleButton addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(scaleAndRotateGestureRecognizerEvent:)]]; + [self addSubview:_scaleButton]; + + UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognizerEvent:)]; + [self addGestureRecognizer:tapGestureRecognizer]; + + UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveGestureRecognizerEvent:)]; + [self addGestureRecognizer:panGestureRecognizer]; + + UIPinchGestureRecognizer *pinGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureRecognizerEvent:)]; + [self addGestureRecognizer:pinGestureRecognizer]; - [self setupUI]; - [self setupGIF]; } return self; } -- (void)dealloc{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} +#pragma mark - common set -- (void)layoutSubviews{ -// [super layoutSubviews]; - _dragBtn.center = CGPointMake(self.frame.size.width, self.frame.size.height); - _closeBtn.center = CGPointMake(self.frame.size.width, 0); - // 字样展示范围 - _lb.frame = CGRectMake(self.frame.size.width * _inputRect.origin.x, - self.frame.size.height * _inputRect.origin.y, - self.frame.size.width * _inputRect.size.width, - self.frame.size.height * _inputRect.size.height); +- (void)setStickerType:(StickerType)stickerType { + if (stickerType == self.stickerType) { + return; + } + _stickerType = stickerType; } -- (void)setupUI{ - _dragBtn = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"sticker_rotate"]]; - _dragBtn.userInteractionEnabled = YES; - [self addSubview:_dragBtn]; - - _closeBtn = [[UIButton alloc] init]; - [_closeBtn setImage:[UIImage imageNamed:@"sticker_delete"] forState:UIControlStateNormal]; - [_closeBtn addTarget:self action:@selector(close:) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:_closeBtn]; - - _dragBtn.frame = CGRectMake(0, 0, kPLSStickerViewBtnLength, kPLSStickerViewBtnLength); - _closeBtn.frame = CGRectMake(0, 0, kPLSStickerViewBtnLength, kPLSStickerViewBtnLength); - if (_type == StickerType_SubTitle) { - [self integrateTextViews]; +- (void)setLayerWidth:(CGFloat)layerWidth { + if (layerWidth == self.layerWidth) { + return; } + _layerWidth = layerWidth; + self.layer.borderWidth = layerWidth; } -- (void)integrateTextViews { - // TODO: 使用绘制方式替换lb - if (!_tf) { - [self addSubview:self.tf]; - } - if (!_lb) { - [self addSubview:self.lb]; +- (void)setLayerColor:(UIColor *)layerColor { + if (layerColor == self.layerColor) { + return; } + _layerColor = layerColor; + self.layer.borderColor = layerColor.CGColor; } -- (void)deintegrateTextViews { - if (_tf) { - [_tf removeFromSuperview]; - _tf = nil; - } - - if (_lb) { - [_lb removeFromSuperview]; - _lb = nil; +- (void)setLayerCornerRadius:(CGFloat)layerCornerRadius { + if (layerCornerRadius == self.layerCornerRadius) { + return; } + _layerCornerRadius = layerCornerRadius; + self.layer.cornerRadius = layerCornerRadius; } -- (void)close:(id)sender { - if ([self.delegate respondsToSelector:@selector(stickerViewClose:)]) { - [self.delegate stickerViewClose:self]; +- (void)setClosePosition:(IconPosition)closePosition { + if (closePosition == self.closePosition) { + return; } + _closePosition = closePosition; - [self removeFromSuperview]; + CGSize originSize = self.closeButton.frame.size; + switch (closePosition) { + case IconPosition_Left_Top: + self.closeButton.frame = CGRectMake(- originSize.width/2, - originSize.height/2, originSize.width, originSize.height); + break; + case IconPosition_Right_Top: + self.closeButton.frame = CGRectMake(self.stickerWidth - originSize.width/2, - originSize.height/2, originSize.width, originSize.height); + break; + case IconPosition_Left_Bottom: + self.closeButton.frame = CGRectMake(- originSize.width/2, self.stickerHeight - originSize.height/2, originSize.width, originSize.height); + break; + case IconPosition_Right_Bottom: + self.closeButton.frame = CGRectMake(self.stickerWidth - originSize.width/2, self.stickerHeight - originSize.height/2, originSize.width, originSize.height); + break; + default: + break; + } } -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { - if (self.alpha > 0.1 && !self.clipsToBounds) { - for (UIView *subView in @[self.dragBtn, self.closeBtn]) { - CGPoint subPoint = [self convertPoint:point toView:subView]; - UIView *resultView = [subView hitTest:subPoint withEvent:event]; - if (resultView) { - return resultView; - } - } +- (void)setScalePosition:(IconPosition)scalePosition { + if (scalePosition == self.scalePosition) { + return; } + _scalePosition = scalePosition; - return [super hitTest:point withEvent:event]; + CGSize originSize = self.scaleButton.frame.size; + switch (scalePosition) { + case IconPosition_Left_Top: + self.scaleButton.frame = CGRectMake(- originSize.width/2, - originSize.height/2, originSize.width, originSize.height); + break; + case IconPosition_Right_Top: + self.scaleButton.frame = CGRectMake(self.stickerWidth - originSize.width/2, - originSize.height/2, originSize.width, originSize.height); + break; + case IconPosition_Left_Bottom: + self.scaleButton.frame = CGRectMake(- originSize.width/2, self.stickerHeight - originSize.height/2, originSize.width, originSize.height); + break; + case IconPosition_Right_Bottom: + self.scaleButton.frame = CGRectMake(self.stickerWidth - originSize.width/2, self.stickerHeight - originSize.height/2, originSize.width, originSize.height); + break; + default: + break; + } } -- (BOOL)becomeFirstResponder { - if (![_tf canBecomeFirstResponder]) { - return NO; +- (void)setIsSelected:(BOOL)isSelected { + if (isSelected == self.isSelected) { + return; + } + _isSelected = isSelected; + if (isSelected) { + self.layer.borderWidth = self.layerWidth; + self.layer.cornerRadius = self.layerCornerRadius; + self.layer.borderColor = self.layerColor.CGColor; + + self.closeButton.hidden = NO; + self.scaleButton.hidden = NO; + } else { + self.layer.borderWidth = 0; + + self.closeButton.hidden = YES; + self.scaleButton.hidden = YES; } - return [_tf becomeFirstResponder]; } -- (BOOL)resignFirstResponder { - [super resignFirstResponder]; - return [_tf resignFirstResponder]; +- (void)setHidden:(BOOL)hidden { + [super setHidden:hidden]; + + if (self.stickerType == StickerType_Gif) { + if (hidden) { + [self stopAnimating]; + } else { + [self startAnimating]; + } + } } -#pragma mark - UITextFieldDelegate -- (void)textViewDidEndEditing:(UITextView *)textView { - [_lb setText:_tf.text]; +- (void)setLayerImage:(UIImage *)layerImage { + if (layerImage == self.layerImage) { + return; + } + _layerImage = layerImage; + self.image = self.layerImage; + if (self.layerImage == nil) { + self.layer.borderWidth = self.layerWidth; + self.layer.cornerRadius = self.layerCornerRadius; + self.layer.borderColor = self.layerColor.CGColor; + } else { + self.layer.borderWidth = 0; + } } -- (void)textDidChange:(NSNotification *)notify { - _lb.text = _tf.text; -} +#pragma mark - image/gif type set -#pragma mark - Getter/Setter -- (void)setType:(StickerType)type { - _type = type; - if (type == StickerType_Sticker) { - [self deintegrateTextViews]; - }else if (type == StickerType_SubTitle){ - [self integrateTextViews]; - } else if (type == StickerType_GIFAnimation) { - +- (void)setStickerURL:(NSURL *)stickerURL { + if (stickerURL == nil || stickerURL == self.stickerURL) { + return; } -} - -- (void)setSelect:(BOOL)select{ - _select = select; - if (select) { - self.layer.borderWidth = 1; - self.layer.borderColor = [[UIColor whiteColor] CGColor]; - self.closeBtn.hidden = NO; - self.dragBtn.hidden = NO; - }else{ - self.layer.borderWidth = 0; - self.closeBtn.hidden = YES; - self.dragBtn.hidden = YES; + _stickerURL = stickerURL; + + if (self.stickerType == StickerType_Image) { + self.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:stickerURL]]; + } else { + [self setGifSource]; } + self.stickerImage = self.imageView.image; } -- (UITextView *)tf { - if (!_tf) { - _tf = [[UITextView alloc] initWithFrame:CGRectZero]; - _tf.delegate = self; - _tf.returnKeyType = UIReturnKeyContinue; - _tf.font = [UIFont systemFontOfSize:20]; +- (void)setLayoutSpace:(CGFloat)layoutSpace { + if (layoutSpace < 0.5 || layoutSpace > 8) { + NSLog(@"边框范围过大或过小!"); + return; + } + if (layoutSpace == self.layoutSpace) { + return; } - return _tf; + _layoutSpace = layoutSpace; + + CGFloat width = CGRectGetWidth(self.frame); + CGFloat height = CGRectGetHeight(self.frame); + self.imageView.frame = CGRectMake(layoutSpace, layoutSpace, width - layoutSpace * 2, height - layoutSpace * 2); } -- (UILabel *)lb { - if(!_lb){ - // TODO:需要修正编辑范围 - _lb = [[UILabel alloc] initWithFrame:self.bounds]; - [_lb addSubview:_tf]; - _lb.numberOfLines = 0; - _lb.text = @""; - _lb.userInteractionEnabled = YES; - _lb.adjustsFontSizeToFitWidth = YES; +#pragma mark - text type set + +- (void)setTextFont:(UIFont *)textFont { + if (textFont == self.textFont) { + return; } - return _lb; + _textFont = textFont; + self.textLabel.font = textFont; } -- (CGAffineTransform)currentTransform { - return self.transform; +- (void)setTextColor:(UIColor *)textColor { + if (textColor == self.textColor) { + return; + } + _textColor = textColor; + self.textLabel.textColor = textColor; } -// 根据图片素材(如图片:sticker_t_0)设置字体渲染范围 -- (void)calcInputRectWithImgName:(NSString *)name { - CGFloat x,y,w,h; - char c = [name characterAtIndex:name.length-1]; - switch (c) { - case '1': - x = 25.0 / 243; - y = 42.0 / 120; - w = 172.0 / 243; - h = 50.0 / 120; - break; - case '2': - x = 55.0 / 198; - y = 39.0 / 148; - w = 90.0 / 198; - h = 72.0 / 148; - break; - case '3': - x = 22.0 / 189; - y = 23.0 / 120; - w = 102.0 / 189; - h = 72.0 / 120; +- (void)setTextAlignment:(TextAlignment)textAlignment { + if (textAlignment == self.textAlignment) { + return; + } + _textAlignment = textAlignment; + + switch (self.textAlignment) { + case TextAlignment_Center: + self.textLabel.textAlignment = NSTextAlignmentCenter; break; - case '4': - x = 105.0 / 294; - y = 41.0 / 95; - w = 158.0 / 294; - h = 39.0 / 95; + case TextAlignment_Left: + self.textLabel.textAlignment = NSTextAlignmentLeft; break; - case '5': - x = 23.0 / 151; - y = 31.0 / 139; - w = 90.0 / 151; - h = 56.0 / 139; + case TextAlignment_Right: + self.textLabel.textAlignment = NSTextAlignmentRight; break; default: - x = 0; - y = 0; - w = 1; - h = 1; + self.textLabel.textAlignment = NSTextAlignmentCenter; break; } - - _inputRect = CGRectMake(x, y, w, h); } -// ======= GIF ======= -- (void)setHidden:(BOOL)hidden { - [super setHidden:hidden]; - - if (StickerType_GIFAnimation == self.type) { - if (hidden) { - [self stopAnimating]; - } else { - [self startAnimating]; - } +- (void)setTextContent:(NSString *)textContent { + if (textContent == self.textContent) { + return; } + _textContent = textContent; + self.textLabel.text = textContent; } -- (void) setupGIF { - +#pragma mark - load gif image + +- (void)setGifSource { CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)_stickerURL, nil); CGFloat totalDuration = 0; size_t imageCount = CGImageSourceGetCount(imageSource); @@ -302,13 +393,212 @@ - (void) setupGIF { totalDuration += frameDuration; } - self.animationImages = allImage; - self.animationDuration = totalDuration; + self.imageView.animationImages = allImage; + self.imageView.animationDuration = totalDuration; - [self startAnimating]; + [self.imageView startAnimating]; CFRelease(imageSource); } +#pragma mark - gesture recognizer -@end +- (void)tapGestureRecognizerEvent:(UITapGestureRecognizer *)tapGes { + if ([[tapGes view] isEqual:self]){ + PLSStickerOverlayView *overlay = (PLSStickerOverlayView *)self.superview; + if (overlay.delegate && [overlay.delegate respondsToSelector:@selector(stickerOverlayView:didTapSticker:tap:)]) { + [overlay.delegate stickerOverlayView:overlay didTapSticker:self tap:tapGes]; + } + } +} + +- (void)moveGestureRecognizerEvent:(UIPanGestureRecognizer *)panGes { + if ([[panGes view] isEqual:self]){ + UIView *bottomSuperView = self.superview.superview; + CGPoint loc = [panGes locationInView:bottomSuperView]; + + if (!self.isSelected) { + return; + } + if (panGes.state == UIGestureRecognizerStateBegan) { + _loc_in = [panGes locationInView:bottomSuperView]; + _ori_center = self.center; + } + + CGFloat x; + CGFloat y; + x = _ori_center.x + (loc.x - _loc_in.x); + + y = _ori_center.y + (loc.y - _loc_in.y); + + dispatch_async(dispatch_get_main_queue(), ^{ + [UIView animateWithDuration:0 animations:^{ + self.center = CGPointMake(x, y); + }]; + }); + } +} + +- (void)pinchGestureRecognizerEvent:(UIPinchGestureRecognizer *)pinGes { + if ([[pinGes view] isEqual:self]){ + if (pinGes.state ==UIGestureRecognizerStateBegan) { + self.currentTransform = self.transform; + } + if (pinGes.state == UIGestureRecognizerStateChanged) { + CGAffineTransform transform = CGAffineTransformScale(self.currentTransform, pinGes.scale, pinGes.scale); + + self.transform = transform; + } + + // 当手指离开屏幕时,将lastscale设置为1.0 + if ((pinGes.state == UIGestureRecognizerStateEnded) || (pinGes.state == UIGestureRecognizerStateCancelled)) { + self.currentScale = self.currentScale * pinGes.scale; + pinGes.scale = 1; + } + } +} + +- (void)scaleAndRotateGestureRecognizerEvent:(UIPanGestureRecognizer *)gesture { + if (self.isSelected) { + UIView *bottomSuperView = self.superview.superview; + CGPoint curPoint = [gesture locationInView:bottomSuperView]; + if (gesture.state == UIGestureRecognizerStateBegan) { + _loc_in = [gesture locationInView:bottomSuperView]; + } + if (gesture.state == UIGestureRecognizerStateBegan) { + self.currentTransform = self.transform; + } + + // 计算缩放 + CGFloat preDistance = [self getDistance:_loc_in withPointB:self.center]; + CGFloat curDistance = [self getDistance:curPoint withPointB:self.center]; + CGFloat scale = curDistance / preDistance; + // 计算弧度 + CGFloat preRadius = [self getRadius:self.center withPointB:_loc_in]; + CGFloat curRadius = [self getRadius:self.center withPointB:curPoint]; + CGFloat radius = curRadius - preRadius; + radius = - radius; + CGAffineTransform transform = CGAffineTransformScale(self.currentTransform, scale, scale); + + self.transform = CGAffineTransformRotate(transform, radius); + + if (gesture.state == UIGestureRecognizerStateEnded || + gesture.state == UIGestureRecognizerStateCancelled) { + self.currentScale = scale * self.currentScale; + } + } +} + +// 距离 +- (CGFloat)getDistance:(CGPoint)pointA withPointB:(CGPoint)pointB { + CGFloat x = pointA.x - pointB.x; + CGFloat y = pointA.y - pointB.y; + + return sqrt(x*x + y*y); +} + +// 角度 +- (CGFloat)getRadius:(CGPoint)pointA withPointB:(CGPoint)pointB { + CGFloat x = pointA.x - pointB.x; + CGFloat y = pointA.y - pointB.y; + return atan2(x, y); +} + +#pragma mark - button action + +- (void)closeButtonClicked { + if (!self.superview) { + return; + } + PLSStickerOverlayView *overlay = (PLSStickerOverlayView *)self.superview; + if (overlay.delegate && [overlay.delegate respondsToSelector:@selector(stickerOverlayView:didClickClose:)]) { + [overlay.delegate stickerOverlayView:overlay didClickClose:self]; + } +} + +#pragma mark - UITextFieldDelegate +- (void)textViewDidEndEditing:(UITextView *)textView { + [self.textLabel setText:_textView.text]; +} + +- (void)textDidChange:(NSNotification *)notify { + self.textLabel.text = self.textView.text; +} + +- (void)startTextEditing:(UITapGestureRecognizer *)tapGes { + if (self.delegate && [self.delegate respondsToSelector:@selector(stickerView:startTextEdit:)]) { + [self.delegate stickerView:self startTextEdit:tapGes]; + } +} + +#pragma mark - public + +- (void)setScaleImage:(UIImage *)image selectedImage:(nonnull UIImage *)selectedImage size:(CGSize)size { + if (image) { + [self.scaleButton setImage:image forState:UIControlStateNormal]; + } + if (selectedImage) { + [self.scaleButton setImage:selectedImage forState:UIControlStateSelected]; + } + + CGSize originSize = self.scaleButton.frame.size; + if (!CGSizeEqualToSize(size, CGSizeZero) && !CGSizeEqualToSize(size, originSize)) { + self.scaleButton.frame = CGRectMake(self.scaleButton.frame.origin.x + originSize.width/2 - size.width/2, self.scaleButton.frame.origin.y + originSize.height/2 - size.height/2, size.width, size.height); + } +} + +- (void)setScaleMinScaleValue:(CGFloat)minValue maxScaleValue:(CGFloat)maxValue { + self.minValue = minValue; + self.maxValue = maxValue; +} + +- (void)setCloseImage:(UIImage *)image selectedImage:(UIImage *)selectedImage size:(CGSize)size { + if (image) { + [self.closeButton setImage:image forState:UIControlStateNormal]; + } + if (selectedImage) { + [self.closeButton setImage:selectedImage forState:UIControlStateSelected]; + } + + CGSize originSize = self.closeButton.frame.size; + if (!CGSizeEqualToSize(size, CGSizeZero) && !CGSizeEqualToSize(size, originSize)) { + self.closeButton.frame = CGRectMake(self.closeButton.frame.origin.x + originSize.width/2 - size.width/2, self.closeButton.frame.origin.y + originSize.height/2 - size.height/2, size.width, size.height); + } +} + +#pragma mark - super methods + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + if (self.alpha > 0.1 && !self.clipsToBounds) { + for (UIView *subView in @[self.scaleButton, self.closeButton]) { + CGPoint subPoint = [self convertPoint:point toView:subView]; + UIView *resultView = [subView hitTest:subPoint withEvent:event]; + if (resultView) { + return resultView; + } + } + } + return [super hitTest:point withEvent:event]; +} + +- (BOOL)becomeFirstResponder { + if (![self.textView canBecomeFirstResponder]) { + return NO; + } + return [self.textView becomeFirstResponder]; +} + +- (BOOL)resignFirstResponder { + [super resignFirstResponder]; + return [self.textView resignFirstResponder]; +} + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect { + // Drawing code +} +*/ + +@end diff --git a/Example/PLShortVideoKitDemo/StickerToolbox/ToolBar/PLSDrawBar.m b/Example/PLShortVideoKitDemo/StickerToolbox/ToolBar/PLSDrawBar.m index 0c1db812..0c62968f 100644 --- a/Example/PLShortVideoKitDemo/StickerToolbox/ToolBar/PLSDrawBar.m +++ b/Example/PLShortVideoKitDemo/StickerToolbox/ToolBar/PLSDrawBar.m @@ -196,7 +196,7 @@ - (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionV colorView.backgroundColor = cellColor; if (self.currentColor == cellColor) { colorView.layer.borderWidth = 2.0; - colorView.layer.borderColor = RGBCOLOR_ALPHA(229, 61, 146, 1).CGColor;; + colorView.layer.borderColor = RGBCOLOR_ALPHA(65, 154, 208, 1).CGColor;; } else { colorView.layer.borderWidth = 0; } diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSClipMovieView.m b/Example/PLShortVideoKitDemo/UI+Tools/PLSClipMovieView.m index a35fc510..cae9613a 100644 --- a/Example/PLShortVideoKitDemo/UI+Tools/PLSClipMovieView.m +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSClipMovieView.m @@ -15,14 +15,9 @@ #define PLSLineW 4 // 线宽 #define PLSMinImageCount 8 // 显示的图片个数 -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) - #define PLSImagesViewH 42 // 预览图高度 #define PLSImagesVIewW (PLS_SCREEN_WIDTH / PLSMinImageCount) // 图片宽度 -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] - @interface PLSClipMovieViewCell () @property (strong, nonatomic) UIImageView *scaledIamgeView; diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSFilterGroup.h b/Example/PLShortVideoKitDemo/UI+Tools/PLSFilterGroup.h index 780f170d..db986b0e 100644 --- a/Example/PLShortVideoKitDemo/UI+Tools/PLSFilterGroup.h +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSFilterGroup.h @@ -37,4 +37,29 @@ */ - (instancetype)initWithImage:(UIImage *)inputImage; + +/** =================== 以下属性和方法为切换滤镜的时候使用的 ============== + 使用方式: + step1. 设置 nextFilterIndex, FilterGroup 内部会根据 nextFilterIndex 创建好 nextFilter + step2. 调用 processPixelBuffer:leftPercent:leftFilter:rightFilter + */ + +/** + @abstract 下一个要使用的滤镜在滤镜组中的索引 + */ +@property (assign, nonatomic) NSInteger nextFilterIndex; + +/** + @abstract 下一个要使用的滤镜 + */ +@property (strong, nonatomic) PLSFilter *nextFilter; + +/** + @abstract 从一个 filter 切换到另外一个 filter,将两个 filter 分别作用在图片的两边,给人一种对比效果 + */ +- (CVPixelBufferRef)processPixelBuffer:(CVPixelBufferRef )originPixelBuffer + leftPercent:(float)leftPercent + leftFilter:(PLSFilter *)leftFilter + rightFilter:(PLSFilter *)rightFilter; + @end diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSFilterGroup.m b/Example/PLShortVideoKitDemo/UI+Tools/PLSFilterGroup.m index 26a4f6b7..b2e47a1e 100644 --- a/Example/PLShortVideoKitDemo/UI+Tools/PLSFilterGroup.m +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSFilterGroup.m @@ -23,7 +23,7 @@ @implementation PLSFilterGroup @synthesize filterIndex = _filterIndex; @synthesize colorImagePath = _colorImagePath; -- (void)setFilterIndex:(NSInteger)filterIndex { +- (void)setFilterIndex:(NSInteger)filterIndex { _filterIndex = filterIndex; _colorImagePath = _colorFilterArray[filterIndex]; self.currentFilter.colorImagePath = _colorImagePath; @@ -37,12 +37,18 @@ - (NSString *)colorImagePath { return _colorImagePath; } +- (void)setNextFilterIndex:(NSInteger)nextFilterIndex { + _nextFilterIndex = nextFilterIndex; + self.nextFilter.colorImagePath = _colorFilterArray[nextFilterIndex]; +} + - (instancetype)init { self = [super init]; if (self) { _colorFilterArray = [[NSMutableArray alloc] init]; _filtersInfo = [[NSMutableArray alloc] init]; self.currentFilter = [[PLSFilter alloc] init]; + self.nextFilter = [[PLSFilter alloc] init]; [self setupFilter]; } @@ -53,11 +59,12 @@ - (instancetype)initWithImage:(UIImage *)inputImage { self = [super init]; if (self) { self.coverImage = inputImage; - + _colorFilterArray = [[NSMutableArray alloc] init]; _filtersInfo = [[NSMutableArray alloc] init]; self.currentFilter = [[PLSFilter alloc] init]; - + self.nextFilter = [[PLSFilter alloc] init]; + [self setupFilter]; } return self; @@ -85,7 +92,7 @@ - (void)loadFilters:(UIImage *)inputImage { NSLog(@"load internal filters json error: %@", error); NSArray *array = [dicFromJson objectForKey:@"filters"]; - + for (int i = 0; i < array.count; i++) { NSDictionary *filter = array[i]; @@ -100,7 +107,7 @@ - (void)loadFilters:(UIImage *)inputImage { } else { coverImage = [NSNull null]; } - + NSDictionary *dic = @{ @"name" : name, @"dir" : dir, @@ -119,6 +126,104 @@ - (void)dealloc { self.currentFilter = nil; } +- (CVPixelBufferRef)processPixelBuffer:(CVPixelBufferRef)originPixelBuffer + leftPercent:(float)leftPercent + leftFilter:(PLSFilter *)leftFilter + rightFilter:(PLSFilter *)rightFilter { + + leftPercent = MIN(1.0, MAX(0, leftPercent)); + + if (leftPercent < FLT_EPSILON) { + return [rightFilter process:originPixelBuffer]; + } else if (1 - leftPercent < FLT_EPSILON) { + return [leftFilter process:originPixelBuffer]; + } + + CVPixelBufferRef leftPixelBuffer = [leftFilter process:originPixelBuffer]; + + /*! + 注意:这里需要拷贝 leftPixelBuffer,否则在 release 模式下,会出现 leftPixelBuffer = rightPixelBuffer 的情况,既就是: + + CVPixelBufferRef leftPixelBuffer = [leftFilter process:originPixelBuffer]; + CVPixelBufferRef rightPixelBuffer = [rightFilter process:originPixelBuffer]; + + 由于 PLSRenderEngine 内部有对 buffer 的重复利用,这两次执行返回的是同一个 buffer,因此,在获取到一个 buffer 之后,需要将 + 数据拷贝出来,否则就被第二次执行给覆盖掉 + */ + CVPixelBufferRef leftPixelBufferCopy = NULL; + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, + [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, + @{}, kCVPixelBufferIOSurfacePropertiesKey, + nil]; + CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault, CVPixelBufferGetWidth(leftPixelBuffer), CVPixelBufferGetHeight(leftPixelBuffer), CVPixelBufferGetPixelFormatType(leftPixelBuffer), (__bridge CFDictionaryRef _Nullable)(options), &leftPixelBufferCopy); + if (kCVReturnSuccess != result) { + NSLog(@"create pixel buffer error"); + return originPixelBuffer; + } + CVPixelBufferLockBaseAddress(leftPixelBuffer, 0); + CVPixelBufferLockBaseAddress(leftPixelBufferCopy, 0); + + size_t bytePerRow = CVPixelBufferGetBytesPerRow(leftPixelBuffer); + + char *leftAddress = CVPixelBufferGetBaseAddress(leftPixelBuffer); + char *leftAddressCopy = CVPixelBufferGetBaseAddress(leftPixelBufferCopy); + + size_t height = CVPixelBufferGetHeight(leftPixelBuffer); + memcpy(leftAddressCopy, leftAddress, height * bytePerRow); + + CVPixelBufferUnlockBaseAddress(leftPixelBuffer, 0); + CVPixelBufferUnlockBaseAddress(leftPixelBufferCopy, 0); + + CVPixelBufferRef rightPixelBuffer = [rightFilter process:originPixelBuffer]; + + // copy BGRA32 data + CVReturn result1 = CVPixelBufferLockBaseAddress(originPixelBuffer, 0); + CVReturn result2 = CVPixelBufferLockBaseAddress(leftPixelBufferCopy, 0); + CVReturn result3 = CVPixelBufferLockBaseAddress(rightPixelBuffer, 0); + + if (kCVReturnSuccess != result1 || result1 != result2 || result1 != result3 || + CVPixelBufferGetHeight(originPixelBuffer) != CVPixelBufferGetHeight(leftPixelBufferCopy) || + CVPixelBufferGetWidth(originPixelBuffer) != CVPixelBufferGetWidth(leftPixelBufferCopy) || + CVPixelBufferGetWidth(originPixelBuffer) != CVPixelBufferGetWidth(rightPixelBuffer) || + CVPixelBufferGetHeight(originPixelBuffer) != CVPixelBufferGetHeight(rightPixelBuffer) || + CVPixelBufferGetBytesPerRow(originPixelBuffer) != CVPixelBufferGetBytesPerRow(leftPixelBufferCopy) || + CVPixelBufferGetBytesPerRow(originPixelBuffer) != CVPixelBufferGetBytesPerRow(rightPixelBuffer)) { + + NSLog(@"filter data error"); + + CVPixelBufferUnlockBaseAddress(originPixelBuffer, 0); + CVPixelBufferUnlockBaseAddress(leftPixelBufferCopy, 0); + CVPixelBufferUnlockBaseAddress(rightPixelBuffer, 0); + + CVPixelBufferRelease(leftPixelBufferCopy); + return originPixelBuffer; + } + + size_t width = CVPixelBufferGetWidth(originPixelBuffer); + bytePerRow = CVPixelBufferGetBytesPerRow(originPixelBuffer); + size_t leftPixel = round(leftPercent * width); + size_t rightPixel = width - leftPixel; + + + leftAddressCopy = CVPixelBufferGetBaseAddress(leftPixelBufferCopy); + char *originAddress = CVPixelBufferGetBaseAddress(originPixelBuffer); + char *rightAddress = CVPixelBufferGetBaseAddress(rightPixelBuffer); + height = CVPixelBufferGetHeight(originPixelBuffer); + for (int i = 0; i < height; i ++) { + memcpy(originAddress + i * bytePerRow, leftAddressCopy + i * bytePerRow, leftPixel * 4); + memcpy(originAddress + i * bytePerRow + leftPixel * 4, rightAddress + i * bytePerRow + leftPixel * 4, rightPixel * 4); + } + + CVPixelBufferUnlockBaseAddress(originPixelBuffer, 0); + CVPixelBufferUnlockBaseAddress(leftPixelBufferCopy, 0); + CVPixelBufferUnlockBaseAddress(rightPixelBuffer, 0); + + CVPixelBufferRelease(leftPixelBufferCopy); + + return originPixelBuffer; +} + @end diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSFormatGifView.m b/Example/PLShortVideoKitDemo/UI+Tools/PLSFormatGifView.m index 4c86a0c6..931ad6df 100644 --- a/Example/PLShortVideoKitDemo/UI+Tools/PLSFormatGifView.m +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSFormatGifView.m @@ -11,12 +11,6 @@ #import #import "UIImage+PLSClip.h" - -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] - -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) - @interface PLSFormatGifViewCell () @property (strong, nonatomic) UIImageView *scaledIamgeView; diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSListFunctionTableViewCell.h b/Example/PLShortVideoKitDemo/UI+Tools/PLSListFunctionTableViewCell.h new file mode 100644 index 00000000..e9bb7469 --- /dev/null +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSListFunctionTableViewCell.h @@ -0,0 +1,18 @@ +// +// PLSListFunctionTableViewCell.h +// PLShortVideoKitDemo +// +// Created by 冯文秀 on 2019/9/17. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface PLSListFunctionTableViewCell : UITableViewCell +@property (nonatomic, strong) UILabel *titlelabel; +@property (nonatomic, strong) UIImageView *nextImageView; +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSListFunctionTableViewCell.m b/Example/PLShortVideoKitDemo/UI+Tools/PLSListFunctionTableViewCell.m new file mode 100644 index 00000000..05c0792f --- /dev/null +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSListFunctionTableViewCell.m @@ -0,0 +1,48 @@ +// +// PLSListFunctionTableViewCell.m +// PLShortVideoKitDemo +// +// Created by 冯文秀 on 2019/9/17. +// Copyright © 2019 Pili Engineering, Qiniu Inc. All rights reserved. +// + +#import "PLSListFunctionTableViewCell.h" + +@implementation PLSListFunctionTableViewCell + +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { + self.backgroundColor = PLS_RGBCOLOR(242, 242, 242); + self.contentView.backgroundColor = [UIColor whiteColor]; + CGFloat width = CGRectGetWidth([UIScreen mainScreen].bounds); + + self.titlelabel = [[UILabel alloc] initWithFrame:CGRectMake(16, 0, 120, 57.5)]; + self.titlelabel.textAlignment = NSTextAlignmentLeft; + self.titlelabel.textColor = [UIColor blackColor]; + self.titlelabel.font = [UIFont systemFontOfSize:15]; + [self.contentView addSubview:_titlelabel]; + + self.nextImageView = [[UIImageView alloc] initWithFrame:CGRectMake(width - 34, 17, 24, 24)]; + self.nextImageView.image = [UIImage imageNamed:@"next"]; + self.nextImageView.userInteractionEnabled = YES; + [self.contentView addSubview:_nextImageView]; + + UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 57.5, width, 0.5)]; + lineView.backgroundColor = [UIColor lightGrayColor]; + [self.contentView addSubview:lineView]; + } + return self; +} + +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSProgressBar.m b/Example/PLShortVideoKitDemo/UI+Tools/PLSProgressBar.m index 21f00ccb..7ddbd09b 100644 --- a/Example/PLShortVideoKitDemo/UI+Tools/PLSProgressBar.m +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSProgressBar.m @@ -64,7 +64,7 @@ - (void)initalize { - (UIView *)getProgressView { UIView *progressView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, _barHeight)]; - progressView.backgroundColor = RGB_COLOR_ALPHA(229, 61, 146, 1); + progressView.backgroundColor = PLS_RGBCOLOR(65, 154, 208); progressView.autoresizesSubviews = YES; return progressView; diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLSRateButtonView.m b/Example/PLShortVideoKitDemo/UI+Tools/PLSRateButtonView.m index f77cf110..77aadd85 100644 --- a/Example/PLShortVideoKitDemo/UI+Tools/PLSRateButtonView.m +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLSRateButtonView.m @@ -9,8 +9,7 @@ #import "PLSRateButtonView.h" #define KINDICATORHEIGHT 2.f -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) + #define COLOR_RGB(a,b,c,d) [UIColor colorWithRed:a/255.0 green:b/255.0 blue:c/255.0 alpha:d] #define BUTTON_BACKGROUNDCOLOR COLOR_RGB(30, 30, 30, 0.8) #define SELECTED_COLOR COLOR_RGB(60, 157, 191, 1) diff --git a/Example/PLShortVideoKitDemo/UI+Tools/PLScreenRecorderManager.m b/Example/PLShortVideoKitDemo/UI+Tools/PLScreenRecorderManager.m index 5b4c5bbf..a9aab463 100644 --- a/Example/PLShortVideoKitDemo/UI+Tools/PLScreenRecorderManager.m +++ b/Example/PLShortVideoKitDemo/UI+Tools/PLScreenRecorderManager.m @@ -59,19 +59,34 @@ - (void)startRecording { } } completionHandler:^(NSError * _Nullable error) { if (error) { - dispatch_async(dispatch_get_main_queue(), ^{ - if ([weakSelf.delegate respondsToSelector:@selector(screenRecorderManager:errorOccur:)]) { - [weakSelf.delegate screenRecorderManager:weakSelf errorOccur:error]; - } - [weakSelf cancelRecording]; - }); + if ([NSThread isMainThread]) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [weakSelf.shortVideoRecorder deleteAllFiles]; + [weakSelf.shortVideoRecorder startRecording]; + }else { + dispatch_async(dispatch_get_main_queue(), ^{ + if ([weakSelf.delegate respondsToSelector:@selector(screenRecorderManager:errorOccur:)]) { + [weakSelf.delegate screenRecorderManager:weakSelf errorOccur:error]; + } + [weakSelf cancelRecording]; + }); + } } else { - dispatch_sync(dispatch_get_main_queue(), ^{ +// dispatch_sync(dispatch_get_main_queue(), ^{ // 注意: [shortVideoRecorder startRecording] 需要再主线程中执行,不然拍的时长会不正确 - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; + if ([NSThread isMainThread]) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [weakSelf.shortVideoRecorder deleteAllFiles]; [weakSelf.shortVideoRecorder startRecording]; - }); + }else { + dispatch_sync(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [weakSelf.shortVideoRecorder deleteAllFiles]; + [weakSelf.shortVideoRecorder startRecording]; + }); + } + +// } }]; } else { diff --git a/Example/PLShortVideoKitDemo/VideoMixViewController.m b/Example/PLShortVideoKitDemo/VideoMixViewController.m index d6cb3552..3647e197 100644 --- a/Example/PLShortVideoKitDemo/VideoMixViewController.m +++ b/Example/PLShortVideoKitDemo/VideoMixViewController.m @@ -129,6 +129,7 @@ - (void)nextButtonClick { EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; videoEditViewController.filesURLArray = @[url]; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [weakSelf presentViewController:videoEditViewController animated:YES completion:nil]; }; self.mulitVideoMixer.failureBlock = ^(NSError *error) { diff --git a/Example/PLShortVideoKitDemo/VideoSelectViewController.m b/Example/PLShortVideoKitDemo/VideoSelectViewController.m index c7527cf4..da85ba09 100644 --- a/Example/PLShortVideoKitDemo/VideoSelectViewController.m +++ b/Example/PLShortVideoKitDemo/VideoSelectViewController.m @@ -46,13 +46,40 @@ - (void)nextButtonClick:(UIButton *)sender { VideoMixViewController *mulitMixViewController = [[VideoMixViewController alloc] init]; mulitMixViewController.urls = urls; + mulitMixViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:mulitMixViewController animated:YES completion:nil]; } else if (enumVideoNextActionRecording == self.actionType) { - MixRecordViewController *recordViewController = [[MixRecordViewController alloc] init]; - recordViewController.mixURL = urls[0]; - [self presentViewController:recordViewController animated:YES completion:nil]; + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"选择合拍的样式" message:nil preferredStyle:(UIAlertControllerStyleAlert)]; + UIAlertAction *leftRight = [UIAlertAction actionWithTitle:@"左右分屏" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) { + MixRecordViewController *recordViewController = [[MixRecordViewController alloc] init]; + recordViewController.mixURL = urls[0]; + recordViewController.mixType = enumMixTypeLeftRight; + recordViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:recordViewController animated:YES completion:nil]; + + }]; + UIAlertAction *updown = [UIAlertAction actionWithTitle:@"素材在上(画中画)" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) { + MixRecordViewController *recordViewController = [[MixRecordViewController alloc] init]; + recordViewController.mixURL = urls[0]; + recordViewController.mixType = enumMixTypeUpdown; + recordViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:recordViewController animated:YES completion:nil]; + }]; + UIAlertAction *downup = [UIAlertAction actionWithTitle:@"素材在下(画中画)" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) { + MixRecordViewController *recordViewController = [[MixRecordViewController alloc] init]; + recordViewController.mixURL = urls[0]; + recordViewController.mixType = enumMixTypeDownup; + recordViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:recordViewController animated:YES completion:nil]; + }]; + + [alert addAction:leftRight]; + [alert addAction:updown]; + [alert addAction:downup]; + + [self presentViewController:alert animated:YES completion:nil]; } } diff --git a/Example/PLShortVideoKitDemo/ViewController.m b/Example/PLShortVideoKitDemo/ViewController.m index e844ea7d..49cedd03 100644 --- a/Example/PLShortVideoKitDemo/ViewController.m +++ b/Example/PLShortVideoKitDemo/ViewController.m @@ -7,19 +7,25 @@ // #import "ViewController.h" +#import "PLSListFunctionTableViewCell.h" + +#import "MatterImportViewController.h" + #import "RecordViewController.h" #import "PhotoAlbumViewController.h" -#import "MulitPhotoAlbumViewController.h" -#import "H265MovieViewController.h" -#import "ImageRotateViewController.h" +#import "VideoSelectViewController.h" #import "MultiVideoViewController.h" +#import "ImageRotateViewController.h" #import "VersionViewController.h" -#import "ImageVideoMixViewController.h" -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] -@interface ViewController () -@property (nonatomic, strong) UIImpactFeedbackGenerator *clickFeedback; +@interface ViewController () +< +UITableViewDelegate, +UITableViewDataSource +> +@property (nonatomic, strong) UITableView *functionTableView; +@property (nonatomic, strong) NSArray *functionArray; @end @implementation ViewController @@ -28,73 +34,15 @@ - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. - if (@available(iOS 10.0, *)) { - self.clickFeedback = [[UIImpactFeedbackGenerator alloc] initWithStyle:(UIImpactFeedbackStyleMedium)]; - } - - self.view.backgroundColor = PLS_RGBCOLOR(25, 24, 36); - - CGFloat height = 64; - if (UIScreen.mainScreen.bounds.size.height < 667) { - height = 54; - } - int index = 0; - - UIButton *recordButton = [[UIButton alloc] initWithFrame:CGRectMake(0, height + index * (height + 10), self.view.bounds.size.width, height)]; - [recordButton setTitle:@"短视频录制" forState:UIControlStateNormal]; - recordButton.backgroundColor = [UIColor grayColor]; - [recordButton addTarget:self action:@selector(pressRecordButtonEvent:) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:recordButton]; - - index ++; - UIButton *imagesToMovieButton = [[UIButton alloc] initWithFrame:CGRectMake(0, height + index * (height + 10), self.view.bounds.size.width, height)]; - [imagesToMovieButton setTitle:@"图片合成视频" forState:UIControlStateNormal]; - imagesToMovieButton.backgroundColor = [UIColor grayColor]; - [imagesToMovieButton addTarget:self action:@selector(imagesToMovieButtonEvent:) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:imagesToMovieButton]; - - index ++; - UIButton *cutMediaButton = [[UIButton alloc] initWithFrame:CGRectMake(0, height + index * (height + 10), self.view.bounds.size.width, height)]; - [cutMediaButton setTitle:@"视频切割" forState:UIControlStateNormal]; - cutMediaButton.backgroundColor = [UIColor grayColor]; - [cutMediaButton addTarget:self action:@selector(cutMediaButtonEvent:) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:cutMediaButton]; + self.navigationItem.title = @"PLShortVideo"; + self.navigationController.navigationBar.barTintColor = PLS_RGBCOLOR(65, 154, 208); + [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]; - index ++; - UIButton *importH265VideoButton = [[UIButton alloc] initWithFrame:CGRectMake(0, height + index * (height + 10), self.view.bounds.size.width, height)]; - [importH265VideoButton setTitle:@"导入H.265视频" forState:UIControlStateNormal]; - importH265VideoButton.backgroundColor = [UIColor grayColor]; - [importH265VideoButton addTarget:self action:@selector(importH265VideoButtonEvent:) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:importH265VideoButton]; + self.view.backgroundColor = PLS_RGBCOLOR(242, 242, 242); - index ++; - UIButton *imageRotateRecordButton = [[UIButton alloc] initWithFrame:CGRectMake(0, height + index * (height + 10), self.view.bounds.size.width, height)]; - [imageRotateRecordButton setTitle:@"图片旋转录制" forState:UIControlStateNormal]; - imageRotateRecordButton.backgroundColor = [UIColor grayColor]; - [imageRotateRecordButton addTarget:self action:@selector(imageRotateRecordButtonEvent:) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:imageRotateRecordButton]; + self.functionArray = @[@[@"视频拍摄", @"屏幕录制", @"素材导入编辑"], @[@"制作视频合拍", @"制作视频拼图", @"制作音乐唱片", @"制作图片电影"], @[@"版本信息"]]; - index ++; - UIButton *mulitRecordButton = [[UIButton alloc] initWithFrame:CGRectMake(0, height + index * (height + 10), self.view.bounds.size.width, height)]; - [mulitRecordButton setTitle:@"多屏视频" forState:UIControlStateNormal]; - mulitRecordButton.backgroundColor = [UIColor grayColor]; - [mulitRecordButton addTarget:self action:@selector(mulitVideoButtonEvent:) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:mulitRecordButton]; - - index ++; - UIButton *imageVideoButton = [[UIButton alloc] initWithFrame:CGRectMake(0, height + index * (height + 10), self.view.bounds.size.width, height)]; - [imageVideoButton setTitle:@"图片视频混排" forState:UIControlStateNormal]; - imageVideoButton.backgroundColor = [UIColor grayColor]; - [imageVideoButton addTarget:self action:@selector(imageVideoButtonEvent:) forControlEvents:UIControlEventTouchDown]; - [self.view addSubview:imageVideoButton]; - - UIButton *versionButton = [UIButton buttonWithType:(UIButtonTypeSystem)]; - [versionButton setTitle:@"查看版本信息" forState:(UIControlStateNormal)]; - [versionButton setTintColor:[UIColor whiteColor]]; - [versionButton addTarget:self action:@selector(versionButtonEvent:) forControlEvents:(UIControlEventTouchUpInside)]; - [versionButton sizeToFit]; - versionButton.center = CGPointMake(self.view.center.x, self.view.bounds.size.height - 30); - [self.view addSubview:versionButton]; + [self setupFunctionTableView]; }; - (void)didReceiveMemoryWarning { @@ -102,72 +50,112 @@ - (void)didReceiveMemoryWarning { // Dispose of any resources that can be recreated. } -// 短视频录制 -- (void)pressRecordButtonEvent:(id)sender { - [self.clickFeedback impactOccurred]; - - RecordViewController *recordViewController = [[RecordViewController alloc] init]; - [self presentViewController:recordViewController animated:YES completion:nil]; +- (void)setupFunctionTableView { + self.functionTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; + self.functionTableView.backgroundColor = PLS_RGBCOLOR(242, 242, 242); + self.functionTableView.delegate = self; + self.functionTableView.dataSource = self; + self.functionTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + [self.functionTableView registerClass:[PLSListFunctionTableViewCell class] forCellReuseIdentifier:@"functionCell"]; + [self.view addSubview:_functionTableView]; } -// 图片合成视频 -- (void)imagesToMovieButtonEvent:(id)sender { - [self.clickFeedback impactOccurred]; - - PhotoAlbumViewController *photoAlbumViewController = [[PhotoAlbumViewController alloc] init]; - photoAlbumViewController.mediaType = PHAssetMediaTypeImage; - photoAlbumViewController.maxSelectCount = 10; - [self presentViewController:photoAlbumViewController animated:YES completion:nil]; +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return _functionArray.count; } -// 切割视频 -- (void)cutMediaButtonEvent:(id)sender { - [self.clickFeedback impactOccurred]; - - MulitPhotoAlbumViewController *mulitPhotoAlbumViewController = [[MulitPhotoAlbumViewController alloc] init]; - mulitPhotoAlbumViewController.mediaType = PHAssetMediaTypeVideo; - mulitPhotoAlbumViewController.maxSelectCount = 10; - [self presentViewController:mulitPhotoAlbumViewController animated:YES completion:nil]; +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + NSArray *rowArray = _functionArray[section]; + return rowArray.count; } -// 导入H.265视频 -- (void)importH265VideoButtonEvent:(id)sender { - [self.clickFeedback impactOccurred]; - - H265MovieViewController *h265MovieViewController = [[H265MovieViewController alloc] init]; - UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:h265MovieViewController]; - [self presentViewController:navigationController animated:YES completion:nil]; +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + PLSListFunctionTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"functionCell"]; + NSArray *rowArray = _functionArray[indexPath.section]; + cell.titlelabel.text = rowArray[indexPath.row]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + return cell; } -// 图片动画录制 -- (void)imageRotateRecordButtonEvent:(id)sender { - [self.clickFeedback impactOccurred]; - - ImageRotateViewController *imageRotateViewController = [[ImageRotateViewController alloc] init]; - [self presentViewController:imageRotateViewController animated:YES completion:nil]; +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + dispatch_async(dispatch_get_main_queue(), ^{ + if (indexPath.section == 0) { + if (indexPath.row == 0) { + // 拍摄录制 + RecordViewController *recordViewController = [[RecordViewController alloc] init]; + recordViewController.screenRecord = NO; + recordViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:recordViewController animated:YES completion:nil]; + } + if (indexPath.row == 1) { + // 录屏 + RecordViewController *recordViewController = [[RecordViewController alloc] init]; + recordViewController.screenRecord = YES; + recordViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:recordViewController animated:YES completion:nil]; + } + if (indexPath.row == 2) { + // 素材导入编辑 + MatterImportViewController *importViewController = [[MatterImportViewController alloc] init]; + importViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self.navigationController pushViewController:importViewController animated:YES]; + } + } else if (indexPath.section == 1) { + if (indexPath.row == 0) { + // 视频合拍 + VideoSelectViewController *videoSelectViewController = [[VideoSelectViewController alloc] init]; + videoSelectViewController.actionType = enumVideoNextActionRecording; + videoSelectViewController.needVideoCount = 1; + videoSelectViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:videoSelectViewController animated:YES completion:nil]; + } + if (indexPath.row == 1) { + // 视频拼图 + MultiVideoViewController *multiVideoViewController = [[MultiVideoViewController alloc] init]; + multiVideoViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:multiVideoViewController animated:YES completion:nil]; + } + if (indexPath.row == 2) { + // 图片动画录制 + ImageRotateViewController *imageRotateViewController = [[ImageRotateViewController alloc] init]; + imageRotateViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:imageRotateViewController animated:YES completion:nil]; + } + if (indexPath.row == 3) { + // 图片合成电影 + PhotoAlbumViewController *photoAlbumViewController = [[PhotoAlbumViewController alloc] init]; + photoAlbumViewController.mediaType = PHAssetMediaTypeImage; + photoAlbumViewController.maxSelectCount = 10; + photoAlbumViewController.modalPresentationStyle = UIModalPresentationFullScreen; + [self presentViewController:photoAlbumViewController animated:YES completion:nil]; + } + }else if (indexPath.section == 2) { + // 查看版本信息 + VersionViewController *versionViewController = [[VersionViewController alloc] init]; + [self presentViewController:versionViewController animated:YES completion:nil]; + } + }); } -// 多屏视频 -- (void)mulitVideoButtonEvent:(id)sender { - [self.clickFeedback impactOccurred]; - - MultiVideoViewController *multiVideoViewController = [[MultiVideoViewController alloc] init]; - [self presentViewController:multiVideoViewController animated:YES completion:nil]; +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 58; } -// 查看版本信息 -- (void)versionButtonEvent:(id)sender { - [self.clickFeedback impactOccurred]; +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0.5, CGRectGetWidth(self.view.frame), 19)]; + footerView.backgroundColor = PLS_RGBCOLOR(242, 242, 242); - VersionViewController *versionViewController = [[VersionViewController alloc] init]; - [self presentViewController:versionViewController animated:YES completion:nil]; + UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 19.5, CGRectGetWidth(self.view.frame), 0.5)]; + line.backgroundColor = [UIColor lightGrayColor]; + [footerView addSubview:line]; + return footerView; } -- (void)imageVideoButtonEvent:(id)sender { - [self.clickFeedback impactOccurred]; - - ImageVideoMixViewController *imageVideoMixViewController = [[ImageVideoMixViewController alloc] init]; - [self presentViewController:imageVideoMixViewController animated:YES completion:nil]; +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + if (section == _functionArray.count - 1) { + return 0; + } + return 20; } - (void)dealloc { diff --git a/Example/PLShortVideoKitDemo/ViewRecordViewController.m b/Example/PLShortVideoKitDemo/ViewRecordViewController.m index ac150123..7a0182b1 100644 --- a/Example/PLShortVideoKitDemo/ViewRecordViewController.m +++ b/Example/PLShortVideoKitDemo/ViewRecordViewController.m @@ -14,12 +14,8 @@ #import "FLAnimatedImage.h" #import "PLShortVideoKit/PLShortVideoKit.h" -#define AlertViewShow(msg) [[[UIAlertView alloc] initWithTitle:@"warning" message:[NSString stringWithFormat:@"%@", msg] delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil] show] -#define PLS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] -#define PLS_RGBCOLOR_ALPHA(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)] + #define PLS_BaseToolboxView_HEIGHT 64 -#define PLS_SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds) -#define PLS_SCREEN_HEIGHT CGRectGetHeight([UIScreen mainScreen].bounds) @interface ViewRecordViewController () < @@ -334,6 +330,7 @@ - (void)nextButtonEvent:(id)sender { EditViewController *videoEditViewController = [[EditViewController alloc] init]; videoEditViewController.settings = outputSettings; videoEditViewController.filesURLArray = filesURLArray; + videoEditViewController.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:videoEditViewController animated:YES completion:nil]; } diff --git a/Example/PLShortVideoKitDemo/images/btn_record_a.png b/Example/PLShortVideoKitDemo/images/btn_record_a.png deleted file mode 100755 index 385670fa..00000000 Binary files a/Example/PLShortVideoKitDemo/images/btn_record_a.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/images/draft_video.png b/Example/PLShortVideoKitDemo/images/draft_video.png deleted file mode 100644 index 1d15f34d..00000000 Binary files a/Example/PLShortVideoKitDemo/images/draft_video.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/images/easyar_AR.png b/Example/PLShortVideoKitDemo/images/easyar_AR.png deleted file mode 100644 index 4e12e6ce..00000000 Binary files a/Example/PLShortVideoKitDemo/images/easyar_AR.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/images/file_path.png b/Example/PLShortVideoKitDemo/images/file_path.png deleted file mode 100644 index bc151d96..00000000 Binary files a/Example/PLShortVideoKitDemo/images/file_path.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/images/flash_close.png b/Example/PLShortVideoKitDemo/images/flash_close.png deleted file mode 100755 index 65a4df22..00000000 Binary files a/Example/PLShortVideoKitDemo/images/flash_close.png and /dev/null differ diff --git a/Example/PLShortVideoKitDemo/images/flash_open.png b/Example/PLShortVideoKitDemo/images/flash_open.png deleted file mode 100755 index a1615e2f..00000000 Binary files a/Example/PLShortVideoKitDemo/images/flash_open.png and /dev/null differ diff --git a/Example/Podfile.lock b/Example/Podfile.lock index a794fa80..c69cc1f5 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -3,15 +3,15 @@ PODS: - Fabric (~> 1.6.3) - Fabric (1.6.11) - FLAnimatedImage (1.0.12) - - HappyDNS (0.3.14) + - HappyDNS (0.3.15) - Masonry (1.0.2) - - PLShortVideoKit (2.2.0): - - PLShortVideoKit/ex-libMuseProcessor (= 2.2.0) - - PLShortVideoKit/libMuseProcessor (= 2.2.0) + - PLShortVideoKit (3.0.0): + - PLShortVideoKit/ex-libMuseProcessor (= 3.0.0) + - PLShortVideoKit/libMuseProcessor (= 3.0.0) - Qiniu (= 7.2.5) - - PLShortVideoKit/ex-libMuseProcessor (2.2.0): + - PLShortVideoKit/ex-libMuseProcessor (3.0.0): - Qiniu (= 7.2.5) - - PLShortVideoKit/libMuseProcessor (2.2.0): + - PLShortVideoKit/libMuseProcessor (3.0.0): - Qiniu (= 7.2.5) - Qiniu (7.2.5): - HappyDNS (~> 0.3) @@ -41,11 +41,11 @@ SPEC CHECKSUMS: Crashlytics: 79e236942ca1e7fc641df1feb9a275360a78ab6a Fabric: 5911403591946b8228ab1c51d98f1d7137e863c6 FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31 - HappyDNS: dc6a164ee81979093123c241c6353bcf0218add6 + HappyDNS: 00c15e651a347206e58a20503a32a5564589b56a Masonry: 7c429b56da9d4ee0bbb3ed77a5ea710d6a5df39e - PLShortVideoKit: 2cd567eaa83a4451945a2db630dfae95c1d5f763 + PLShortVideoKit: 901da81b11ae8e397f530bf3d4014921426cbf4c Qiniu: 909b408ee489ea54827e9717be90b94bc9dfbc48 PODFILE CHECKSUM: 464a1d9cdafee0a2337603af681aa59f2814b116 -COCOAPODS: 1.7.2 +COCOAPODS: 1.7.5 diff --git a/Example/Pods/HappyDNS/HappyDNS/Http/QNNiuDns.h b/Example/Pods/HappyDNS/HappyDNS/Http/QNNiuDns.h deleted file mode 100644 index b21add86..00000000 --- a/Example/Pods/HappyDNS/HappyDNS/Http/QNNiuDns.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// QNNiuDns.h -// HappyDNS -// -// Created by 何昊宇 on 2018/3/8. -// Copyright © 2018年 Qiniu Cloud Storage. All rights reserved. -// - -#import "QNResolverDelegate.h" -#import - -@interface QNNiuDns : NSObject -- (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error; - -@property (nonatomic, strong, readonly) NSString *accountId; - -@property (nonatomic, strong, readonly) NSString *encryptKey; - -/** - * 单位 s - */ -@property (nonatomic, assign, readonly) long expireTime; - - -@property (nonatomic, assign, readonly) BOOL isHttps; - -@property (nonatomic, assign, readonly) BOOL isNeedEncrypted; - -/** - * http DNS 加密初始化 - */ -- (instancetype)initWithAccountId:(NSString *)accountId - encryptKey:(NSString *)encryptKey - expireTime:(long)expireTime - isHttps:(BOOL)isHttps - isNeedEncrypted:(BOOL)isNeedEncrypted; - -@end diff --git a/Example/Pods/HappyDNS/HappyDNS/Http/QNNiuDns.m b/Example/Pods/HappyDNS/HappyDNS/Http/QNNiuDns.m deleted file mode 100644 index 9f408f34..00000000 --- a/Example/Pods/HappyDNS/HappyDNS/Http/QNNiuDns.m +++ /dev/null @@ -1,127 +0,0 @@ -// -// QNNiuDns.m -// HappyDNS -// -// Created by 何昊宇 on 2018/3/8. -// Copyright © 2018年 Qiniu Cloud Storage. All rights reserved. -// - -#import "QNNiuDns.h" -#import "QNDes.h" -#import "QNDomain.h" -#import "QNHex.h" -#import "QNNetworkInfo.h" -#import "QNRecord.h" -#import "QNMD5.h" - -#define ENDPOINT_SSL @"https://httpdns.qnydns.net:18443/" -#define ENDPOINT @"http://httpdns.qnydns.net:18302/" - -@interface QNNiuDns () - -@property (nonatomic, strong) QNDes *des; - -@end - -@implementation QNNiuDns - -- (instancetype)initWithAccountId:(NSString *)accountId - encryptKey:(NSString *)encryptKey - expireTime:(long)expireTime - isHttps:(BOOL)isHttps - isNeedEncrypted:(BOOL)isNeedEncrypted { - if (self = [super init]) { - _accountId = accountId; - _expireTime = expireTime; - _isHttps = isHttps; - _isNeedEncrypted = isNeedEncrypted; - if (encryptKey) { - _encryptKey = encryptKey; - _des = [[QNDes alloc] init:[encryptKey dataUsingEncoding:NSUTF8StringEncoding]]; - } - } - return self; -} - -- (NSString *)encrypt:(NSString *)domain { - NSData *data = [_des encrypt:[domain dataUsingEncoding:NSUTF8StringEncoding]]; - if (data == nil) { - return nil; - } - NSString *str = [QNHex encodeHexData:data]; - return str; -} - -- (NSArray *)decrypt:(NSString *)raw { - NSData *enc = [QNHex decodeHexString:raw]; - if (enc == nil) { - return nil; - } - NSData *data = [_des decrpyt:enc]; - if (data == nil) { - return nil; - } - return [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]; -} - -- (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error { - - NSString *realDomain = domain.domain; - if (self.isNeedEncrypted) { - realDomain = [self encrypt:[NSString stringWithFormat:@"%@", domain.domain]]; - if (realDomain == nil) { - if (error != nil) { - *error = [[NSError alloc] initWithDomain:domain.domain code:kQN_ENCRYPT_FAILED userInfo:nil]; - } - return nil; - } - } - NSString * md = [NSString stringWithFormat:@"%@-%@-%ld",domain.domain,self.encryptKey,self.expireTime]; - NSString *s = [QNMD5 MD5:md]; - NSString *url = [NSString stringWithFormat:@"%@%@/d?dn=%@&e=%@&s=%@&ttl=1&echo=1", self.isHttps? ENDPOINT_SSL : ENDPOINT, self.accountId, realDomain,[NSString stringWithFormat:@"%ld",self.expireTime],s]; - NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:QN_DNS_DEFAULT_TIMEOUT]; - NSHTTPURLResponse *response = nil; - NSError *httpError = nil; - NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest - returningResponse:&response - error:&httpError]; - - if (httpError != nil) { - if (error != nil) { - *error = httpError; - } - return nil; - } - if (response.statusCode != 200) { - return nil; - } - - NSDictionary *raw = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]; - if (raw == nil) { - if (error != nil) { - *error = [[NSError alloc] initWithDomain:domain.domain code:kQN_DECRYPT_FAILED userInfo:nil]; - } - return nil; - } - NSArray *rawArray; - if (self.isNeedEncrypted) { - rawArray = [self decrypt:raw[@"data"]][0]; - } else { - rawArray = raw[@"data"][0]; - } - if (rawArray.count <= 0) { - return nil; - } - NSMutableArray *ret = [[NSMutableArray alloc] initWithCapacity:rawArray.count]; - for (int i = 0; i < rawArray.count; i++) { - NSDictionary *dataDic = [rawArray objectAtIndex:i]; - if ([[dataDic objectForKey:@"TTL"] longValue] <= 0) { - continue; - } - QNRecord *record = [[QNRecord alloc] init:[dataDic objectForKey:@"data"] ttl:[[dataDic objectForKey:@"TTL"] intValue] type:kQNTypeA]; - [ret addObject:record]; - } - return ret; -} - -@end diff --git a/Example/Pods/Headers/Private/HappyDNS/QNNiuDns.h b/Example/Pods/Headers/Private/HappyDNS/QNNiuDns.h deleted file mode 120000 index 5d078c20..00000000 --- a/Example/Pods/Headers/Private/HappyDNS/QNNiuDns.h +++ /dev/null @@ -1 +0,0 @@ -../../../HappyDNS/HappyDNS/Http/QNNiuDns.h \ No newline at end of file diff --git a/Example/Pods/Headers/Public/HappyDNS/QNNiuDns.h b/Example/Pods/Headers/Public/HappyDNS/QNNiuDns.h deleted file mode 120000 index 5d078c20..00000000 --- a/Example/Pods/Headers/Public/HappyDNS/QNNiuDns.h +++ /dev/null @@ -1 +0,0 @@ -../../../HappyDNS/HappyDNS/Http/QNNiuDns.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 4edd877e..01206868 100644 --- a/Example/Pods/Local Podspecs/PLShortVideoKit.podspec.json +++ b/Example/Pods/Local Podspecs/PLShortVideoKit.podspec.json @@ -1,6 +1,6 @@ { "name": "PLShortVideoKit", - "version": "2.2.0", + "version": "3.0.0", "summary": "PILI iOS short video record SDK", "homepage": "https://github.com/pili-engineering/PLShortVideoKit", "license": "Apache License 2.0", @@ -8,7 +8,7 @@ "pili": "pili@qiniu.com" }, "source": { - "http": "https://sdk-release.qnsdk.com/PLShortVideoKit-profession-v2.2.0.zip" + "http": "https://sdk-release.qnsdk.com/PLShortVideoKit-profession-v3.0.0.zip" }, "platforms": { "ios": "8.0" diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index a794fa80..c69cc1f5 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -3,15 +3,15 @@ PODS: - Fabric (~> 1.6.3) - Fabric (1.6.11) - FLAnimatedImage (1.0.12) - - HappyDNS (0.3.14) + - HappyDNS (0.3.15) - Masonry (1.0.2) - - PLShortVideoKit (2.2.0): - - PLShortVideoKit/ex-libMuseProcessor (= 2.2.0) - - PLShortVideoKit/libMuseProcessor (= 2.2.0) + - PLShortVideoKit (3.0.0): + - PLShortVideoKit/ex-libMuseProcessor (= 3.0.0) + - PLShortVideoKit/libMuseProcessor (= 3.0.0) - Qiniu (= 7.2.5) - - PLShortVideoKit/ex-libMuseProcessor (2.2.0): + - PLShortVideoKit/ex-libMuseProcessor (3.0.0): - Qiniu (= 7.2.5) - - PLShortVideoKit/libMuseProcessor (2.2.0): + - PLShortVideoKit/libMuseProcessor (3.0.0): - Qiniu (= 7.2.5) - Qiniu (7.2.5): - HappyDNS (~> 0.3) @@ -41,11 +41,11 @@ SPEC CHECKSUMS: Crashlytics: 79e236942ca1e7fc641df1feb9a275360a78ab6a Fabric: 5911403591946b8228ab1c51d98f1d7137e863c6 FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31 - HappyDNS: dc6a164ee81979093123c241c6353bcf0218add6 + HappyDNS: 00c15e651a347206e58a20503a32a5564589b56a Masonry: 7c429b56da9d4ee0bbb3ed77a5ea710d6a5df39e - PLShortVideoKit: 2cd567eaa83a4451945a2db630dfae95c1d5f763 + PLShortVideoKit: 901da81b11ae8e397f530bf3d4014921426cbf4c Qiniu: 909b408ee489ea54827e9717be90b94bc9dfbc48 PODFILE CHECKSUM: 464a1d9cdafee0a2337603af681aa59f2814b116 -COCOAPODS: 1.7.2 +COCOAPODS: 1.7.5 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 4b6f0974..ec6d0728 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -39,132 +39,130 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 001D8DEA226B1EEF8AEF5ED8D9EBC03E /* QNHosts.m in Sources */ = {isa = PBXBuildFile; fileRef = D8F4A5B8558E68780DCA5BBB6836B119 /* QNHosts.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 03F0CB5DC5A93F4995430671164F8289 /* QNPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = EB428682DE7D7AC9F6A40CA4D20E87D4 /* QNPipeline.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 049C72D59655A408144C7302F38E4A3B /* HappyDNS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A543C347DCED12E2411545716C370D1 /* HappyDNS.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0506161ED8DFB14E80E3A645C8FCFD0E /* QNRecorderDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 04B1F8B746EFC83F11E8890D5DBDC9B4 /* QNRecorderDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 055359B6E5778374720C30F1ABFB4D9F /* QNFormUpload.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7B46FA531047A26C57D2C16BEA4243 /* QNFormUpload.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 065BB443AD2836956E88A9919E23E5A4 /* QNPipeline.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D00981DA1EC762D3F9F6191AE06D7D1 /* QNPipeline.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0A34F4D5241243879C8650623C9CF56C /* QNUploadManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D6C5A3E6B085354F15BCA52EB126DD4 /* QNUploadManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0AD8D53C5245C96AF567CE88BB19E84E /* Qiniu-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EA031A6536B25544D25B760AD1DB8EC2 /* Qiniu-dummy.m */; }; - 0E8A86C42E90907F71C35D6DBFE73685 /* QNHttpDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0368138DC69AB564D1226C9D5A7BA2FF /* QNHttpDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 107C68FEFE366330F32D876226A7208E /* QNUploadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 36BB14AFEC9874B05E9B179B60997BF9 /* QNUploadManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 108D4601277E1B7A23AEF3C65C933EA5 /* QNPHAssetResource.h in Headers */ = {isa = PBXBuildFile; fileRef = 606E2668409C5AADC816CEA621704FFA /* QNPHAssetResource.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 115ACCE253A886181B55773DDC70D6ED /* MASViewConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = F2AC09E3C47B5BE73C5DB9320DDA2024 /* MASViewConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 11F9B8FEFDA4F82DA2C335AA3F512419 /* QNNiuDns.h in Headers */ = {isa = PBXBuildFile; fileRef = 066E515A3F5D7DEC8797D64762224A09 /* QNNiuDns.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 1427A7143E9A2233D877C5983826ED38 /* QNResponseInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D007BB64566319240C8CE6A10FE3C60 /* QNResponseInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 165BE042D8AE27116E0C467F3D047D9E /* QNUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = BE76AB5EC5A2DFD9872CABD115BCB5A3 /* QNUserAgent.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 181B2691FF506F26F7F71F711C724B81 /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = C5974EED459E3547D39C6B2B9F8B448D /* MASConstraintMaker.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 18215DEC82E6C7DE502F02F4003F1788 /* FLAnimatedImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4042BE7BC2CAB768E4E7F7999137A814 /* FLAnimatedImage-dummy.m */; }; - 18A705E9F6D779E2EE2317763FFC55FD /* QNFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 949EA1C142526933535106A3F96B4B2F /* QNFile.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1B3F936992CCBB41CB5E96491FB05E76 /* QNDomain.h in Headers */ = {isa = PBXBuildFile; fileRef = 0590017E2114863B3416C5F2101428BE /* QNDomain.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 1D71081556919F97A59595E226955DB2 /* QNPHAssetFile.h in Headers */ = {isa = PBXBuildFile; fileRef = BD2DA2AAFD22FDD51DDF6656C1C1CE70 /* QNPHAssetFile.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 1E2B03A80923D9AA09213103132247C4 /* QNALAssetFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 922F42E2170928F4F33420C710D858F2 /* QNALAssetFile.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 204145CCC4E9112B54FCD334FBBD9E42 /* QNALAssetFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 7564ECB1BE548098EA82717AE1428436 /* QNALAssetFile.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 20D3664A1DC8397D4C263663883709A1 /* QNIP.h in Headers */ = {isa = PBXBuildFile; fileRef = 4102119BB577809706CD9807D512A81A /* QNIP.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 20E2F8001CC8A41A0E1B50694BE7875D /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 80FEBF8EDB6F5A42D38F9BF5D293340C /* NSArray+MASAdditions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 232321420D4E786E3A874FF061FE99BC /* QNNetworkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51CB2C9D11B0382BC645CF9DEABAD01A /* QNNetworkInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 262642A3FC3E59826CC759F56E886F10 /* QNConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CD61B5E61D2705FCBDF0E2FD06D3764 /* QNConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2E5F3B41BD51ACE4EE3B422BB67E51DF /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCAD8EF0CF9ABBBE260F99D3DFCCF5B /* MASViewAttribute.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2EF5EAF19497CFF0A22A1BDEDF48CF20 /* QNUploadOption+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0E03E41B27017F8264E37B4A69CD17 /* QNUploadOption+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2F0A7DB8C1FA0FB9349F791E683B2566 /* QNHijackingDetectWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 62798C8D70EEBBBD2FDFB65A89442DFF /* QNHijackingDetectWrapper.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 31064475EC704EC31BC3E2DE0DAFC72C /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 14737354608E32510CFD9F907F5ED324 /* MASViewConstraint.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 3430321D06CBCF49F5A7DF6A70D9BB91 /* Masonry-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6112B38D2494947997368BFF51A4D453 /* Masonry-dummy.m */; }; - 3567E54BF3DDC0C115C5FB58CF3403D7 /* QiniuSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = F05DEBBFC3FF6D474C85B2945C3AC55A /* QiniuSDK.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 390E8375B19FF12764C5AA730AF0F0F4 /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 781066C5AC71BC86276C51735727C18C /* View+MASAdditions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 403EA1260328FA911D6A1662A775EA7B /* QNResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F6A0685DEECD46087AADA5C475A3A35 /* QNResolver.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 42947699890A199B08A896144A878D80 /* MASViewAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FBD8ECB98692FA39A12D024B762A297 /* MASViewAttribute.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 431E20FB6A3867B7678A12F589F706EB /* QNUrlSafeBase64.h in Headers */ = {isa = PBXBuildFile; fileRef = E7CD8EEE5B00BD8DBCD2EFD4C10C1AF0 /* QNUrlSafeBase64.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 438F57293439D5A8976D86ECED777598 /* QNFileRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CA65FF87C695B148ED228D17735C4C3 /* QNFileRecorder.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 43DF36988AE7D8D1B18417AD518D439A /* QNResumeUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 707B3A46C129C0610EFFE5EA956C6287 /* QNResumeUpload.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 444E181D40FE34D7077E34FF1CEEBDC0 /* QN_GTM_Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F57C42060317FE87EB1BB3E9A4F4A70 /* QN_GTM_Base64.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 44A3B1A5D2C513F8FD238E3B64E4C6CF /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA671D69DFEBF53E08341519314810DB /* NSLayoutConstraint+MASDebugAdditions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 46692A2E77157B00827182C8DC686F72 /* View+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = F718BDD5A550507B5B4DFDA42E62EF2B /* View+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 46704DAA07F3E4BB41422B3A9109A893 /* QNHosts.h in Headers */ = {isa = PBXBuildFile; fileRef = AF75B54E10AF065CFD3E07D963E057B2 /* QNHosts.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 46E3449855456D779144D3A3031510F8 /* QNResponseInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0954AB11364886615FED979B28080F6F /* QNResponseInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 48128E051E42D841A2AA90D1182191E0 /* QNLruCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 19C915FDA8D4EA64E92B9E4E70E9D701 /* QNLruCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 489646CE094DC2C5F763BDE39A52060A /* QNSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1303E37C7134A366D8ECD959C852EE5 /* QNSessionManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4AB9EE75B45CB020100A2898AF960277 /* QNVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = F0ACB793E106836346FF14E6C2887C3E /* QNVersion.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4CE091F886EC6324673EFE0AEBBEA0FE /* MASConstraint+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 55CDED97E866A21F98798C86CDCA8E1F /* MASConstraint+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 56BBC602BF0C0F844D3235AA27FBCCD7 /* QNResolverDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8DC37D82CD6B6AF3E894BAF5BC372B94 /* QNResolverDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5BE94CDBD489AE23B3505C4F3AECEDE3 /* QNCrc32.h in Headers */ = {isa = PBXBuildFile; fileRef = 04E2183A218091F317D6124CBF08A9DE /* QNCrc32.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5C3A074F9ACA976E4CCC70BB915E3B5D /* QNUrlSafeBase64.m in Sources */ = {isa = PBXBuildFile; fileRef = 130A3033AF8956D7ACE795B982A7BD9D /* QNUrlSafeBase64.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5C5C77BBF83B793B82713296519751DA /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5763011EAF2D09C0F745FC936AFD8802 /* ViewController+MASAdditions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5E361429615E19B96BBA8E1F788C55C1 /* QNFileDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC2CB3E25E9E66C7414C8CF8627413B /* QNFileDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 610AA6B1793EE47811C5ED9649518CB0 /* QNConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = A2D92E08FE845D7108F467E957D11D79 /* QNConfiguration.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 62A75019E4F15005EA641F2828D640C9 /* QNRefresher.m in Sources */ = {isa = PBXBuildFile; fileRef = C95F5EB7F401CE8A957D59358992445C /* QNRefresher.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 62CB484C994EBFF213FC25E4741B34A4 /* QNEtag.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AD760BB91407C3C81F3ABE2B4EEDC58 /* QNEtag.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 630D9929FF3E2CA7E4F6DCF72E42877F /* QNDnspodEnterprise.h in Headers */ = {isa = PBXBuildFile; fileRef = 7125FE0ADDC9EBAA36B3D5504D03903C /* QNDnspodEnterprise.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 65E88072A2BDC576BFC85E67EF9FBBC6 /* MASUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 50A3E4BCDDB3A71E486D4B982E1FC5DA /* MASUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 662B660ECD532CFF2BAEFB3B213EABA3 /* QNTxtResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B1FD9B2AE2BAEB934281DC75A5EEF23 /* QNTxtResolver.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 68734B2FD4E55F9A95D5B416C075074A /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B374127F515C31F50DEDABDD4822BF /* MASLayoutConstraint.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 6AE6B4B97D65D5B51F8936DEF90D86C1 /* QNUploadOption.m in Sources */ = {isa = PBXBuildFile; fileRef = 276FA87254F0EC58970AE6C3352D8800 /* QNUploadOption.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 6BA2C73D840F98A0621442AB74976554 /* QNRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 2992C522F75BC6F2E7782C166611D474 /* QNRecord.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 72CD374FD089082CDB26721D6733D8DE /* QNAssessment.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EB16A7B39ACCBFF9FF8162047F6AFF5 /* QNAssessment.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7CF2AC7A3B3ED03B30C1E4ED662B0551 /* MASLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = E924F91E17089AD18AF06FEB6806C406 /* MASLayoutConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7E273D8F34CE76767C65B1B8A4C3E488 /* QNEtag.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BA95F8C9277D267EADC95252D10EA61 /* QNEtag.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 7F0E1A708087C4B300FC79FF1F89BF31 /* QNUpToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A1A3F685B43444F89639ADC31C75633 /* QNUpToken.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 7FB5CF5472606834CCD665024166C392 /* QNHex.h in Headers */ = {isa = PBXBuildFile; fileRef = D16E266C1B93449EE4050912CD64F934 /* QNHex.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 80E647A750311CE63C0D6408A1985831 /* QNSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F5EB4DD9CBE509E638A8B9B66D57B12 /* QNSessionManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 81F811A56B6724F7E8E2D25364E595E3 /* NSArray+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = EDB23A9B2722BA77023CBDAC8B0AF60B /* NSArray+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 83656390DFBD5E40863BD628D5F9A46A /* QNRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 4743FF73E5E40D32B83469BB782EF4F7 /* QNRecord.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 85A5B6C5DB2824107D8E1E2DF6FCC545 /* QNDnsManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 97B351E8B9D7D0971B925CFBD9E65E86 /* QNDnsManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 872A770D9F8EE265E8C232A6FFD6CE0A /* QNCrc32.m in Sources */ = {isa = PBXBuildFile; fileRef = B6F620341FEA9BBEA045B308C60430E9 /* QNCrc32.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 89B5378FEF108D21CB8FF754552AEB6E /* QN_GTM_Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BFAFA72BAED0EB1F693AA077935AFA0 /* QN_GTM_Base64.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8C4D69016542BAF09D544CB7E6C43DF2 /* QNGetAddrInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 6372348C9CBCC484FC15B206BF839C42 /* QNGetAddrInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8EABAB29E43027057B847DEBCF44CF71 /* QNUploadOption.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AD6D3A8C177CAB6555315C35D76C9FF /* QNUploadOption.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9194B58ACE900ED6BAE6AD92E24A2CFF /* MASConstraintMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 1761496D72C307EFDD9EDD62B4B592F7 /* MASConstraintMaker.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 92BF70E9D3285561EB404A7C4A4A6DEE /* MASCompositeConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = BD2397AD6246DE36FDBBFF91694CF6C3 /* MASCompositeConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9A541CBF97F3E553259291B3BFDCBA0C /* QNAssessment.m in Sources */ = {isa = PBXBuildFile; fileRef = 0948776AB9F038B34F6E8D171A9DC9E1 /* QNAssessment.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9B369AAD43832AEDBBDA8A0DF0856B4C /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C1B09B668B6635F9E63DDF38D4CAED1 /* MASCompositeConstraint.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9EDEDD1974DDEBA5577DCB3A52868051 /* QNFormUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 81954B9704062F42BEEB2B32DAD6AB71 /* QNFormUpload.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A0724C13490E433BADA7C09D1D0E691B /* QNRefresher.h in Headers */ = {isa = PBXBuildFile; fileRef = 98B4981EB0449B93511D38E7EECE606B /* QNRefresher.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A3307B8FB6EE0A049DBAE3AA4D2C6DA0 /* View+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = B03F915A88F21D8BB7C5C5F9ED3E4A51 /* View+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A4CED055F89DF5BBC853AF5315712804 /* QNFileRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 99B37CEB6E7890CAFCCFC98213AEE7FA /* QNFileRecorder.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A65CE94FAA9E3AA9181DE3E28BBD2FC9 /* QNHijackingDetectWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = F15A57E93F14D2B52AA9EAFAD9F7CF5F /* QNHijackingDetectWrapper.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A6A8D26650C41453BF5465D6323FEAA9 /* QNResolvUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 616A9B8A95D05602A7C3AB65BFA8FA2C /* QNResolvUtil.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A759F099AAFFAB954F3C7CA478124154 /* QNMD5.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BF668BE143F24CFB5DCF7E2EF65B694 /* QNMD5.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A7BB51DA5602DDA8CA392C605500CE7F /* QNDnsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B76388BE36B9B4EA707F4CC6D3EFA90A /* QNDnsManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - A855EFF54D728B8D3DC2071D81B75073 /* QNFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CDAC700BDCE8CE4BB7541970F74C973 /* QNFile.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A92CDFD1720534B4EDB269CCCD7ECF0C /* QNNetworkInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DC5780C10EF06CE1B7C79B7135FB4AB /* QNNetworkInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - AA93BE522FAFFD0E3560DD348FA9BA8F /* QNNiuDns.m in Sources */ = {isa = PBXBuildFile; fileRef = 30D742796965426E10F87542550C06BF /* QNNiuDns.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - AE19C2A5BF53E7B11231AC79D81EB153 /* QNSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 01D58F57B5EA09A711930FF5BCB81EA7 /* QNSystem.h */; settings = {ATTRIBUTES = (Project, ); }; }; - AED8E5FC30FF7EA27E0EA5E39AA2341F /* QNDomain.m in Sources */ = {isa = PBXBuildFile; fileRef = 4030E9756D6612DAE1B2111D9591AB8E /* QNDomain.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - AFEAD2E989FDC4BBB2CCA262700D7A8C /* QNSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 8182DEA6FC5EF5AB87D0DA284574EE91 /* QNSystem.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B0C40A6195EE239E2F9B78FA89CEB289 /* HappyDNS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EC7D773547E63E83CD022000A211F04 /* HappyDNS-dummy.m */; }; - B1D27B882152A7224EEAD558D293CAC7 /* QNDes.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C789F6B08F93A8A25DB4C7D2EA7D57C /* QNDes.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B20A0E5D8F9BCED1A82793C4BE9E7258 /* Masonry.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CF6C85085282224310FF7EB9A526528 /* Masonry.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B2D473ECD52217A35F50382B265B10EE /* QNAsyncRun.m in Sources */ = {isa = PBXBuildFile; fileRef = 718B3EC939241DAF2BD44F90089E875F /* QNAsyncRun.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B59751092FF5EE107A9682BFA8B9FF42 /* QNMD5.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C7C330AB16CA1A1D339D7A9FF93DB0B /* QNMD5.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B9EDA07E65A834E9EE13C86B5E97D7D3 /* QNIpModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EC9788E7CE0F5B9DD37A36DBA564BFB /* QNIpModel.h */; settings = {ATTRIBUTES = (Project, ); }; }; - BDDFDB62428E1B9911B0C27E936BBEB0 /* QNResolvUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EC1D629E35762544A3AF76329C596F4 /* QNResolvUtil.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C09407360B2CA7E9FC6B9ED1DDD30B6C /* QNResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = EB66B62C366B34234E1E677B2F8CBA69 /* QNResolver.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C0FDAE269713CCE674298FE70A2F3B7A /* QNHex.m in Sources */ = {isa = PBXBuildFile; fileRef = 93FB08446352700BF861FD4132A75935 /* QNHex.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C200AEB67D3540FD87EC3249EC929525 /* QNDes.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D62DC3985963E3DADB4781DF6F8F0E7 /* QNDes.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C6D9D33FF29766B05FAB9FFE86A83246 /* QNIP.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CEA2F31CFECC8753DF165972567DA95 /* QNIP.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C74D2E856ADC8139CD00DBD184061B23 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = C053720B15E527CAA832410A617C05E6 /* NSLayoutConstraint+MASDebugAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C9B2F8E482E5A42882ABDB5416C3184A /* QNPHAssetResource.m in Sources */ = {isa = PBXBuildFile; fileRef = 29BD5A5D14DEDA9430D27CD301654B53 /* QNPHAssetResource.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - CA231C4FDAA90356774A050004DFB489 /* QNPHAssetFile.m in Sources */ = {isa = PBXBuildFile; fileRef = ACAE3DDC2CB6C6DD872B74119CE23219 /* QNPHAssetFile.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - CAEA05C442E1556ABDDB634213B2812A /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 621109AAF2C0D7A0D57A1CC1959C5B48 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - CAEAE192F8DD7A52702B96B87D238267 /* QNLruCache.m in Sources */ = {isa = PBXBuildFile; fileRef = E4C8A6405530F9547AD0B26AAFA5C7B7 /* QNLruCache.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - CCC4224C0B97913E99A9CDF8633D6351 /* QNIpModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 80293F9176725CD1B877779AF2A0D765 /* QNIpModel.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - CF3DDB06547EC1A30633781E66B67AA4 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = A3434E951BBD43E7B663C40674F5776E /* FLAnimatedImage.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D631BC92AD923A758BF7318E2D42986B /* QNAsyncRun.h in Headers */ = {isa = PBXBuildFile; fileRef = EC7209EAC7ED814D4E7336D6F6C6BE46 /* QNAsyncRun.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D65722AE5FFA04DBA5429BE359EF3C02 /* QNResumeUpload.h in Headers */ = {isa = PBXBuildFile; fileRef = 57103069BF70B2AC884EC1CFAA620A8D /* QNResumeUpload.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D74E19C40335D318C539A7363C6C1A5D /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DE4D0D6A9512AE92730F168E054B09B /* FLAnimatedImageView.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D783A8A5A426DBF85162B92142651218 /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 33C531193DCEC89A11A171742430000C /* MASConstraint.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E03284656F15525BC13EB8C5BA2799F2 /* QNDnspodFree.h in Headers */ = {isa = PBXBuildFile; fileRef = 589247593CC6D20DA3C3D985B84D1A77 /* QNDnspodFree.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E0920F60C1305980AD484FF6A53FE117 /* QNDnspodEnterprise.m in Sources */ = {isa = PBXBuildFile; fileRef = 63AC1F0E19EE8E0C6E6793860A00412A /* QNDnspodEnterprise.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E16A819D2F5392EE050D83317C18723A /* QNDnspodFree.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E111713FC71C86A36AE4187F575EC8E /* QNDnspodFree.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E3DEAADCF19C228BF606BEB14AF625DB /* QNTxtResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = 18CD98380FFBFC73BF79790911B1335E /* QNTxtResolver.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E76935CFF4AF327F8D9A7C1935F7D900 /* ViewController+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = A4B9717971FE72688E98D42CB68079C2 /* ViewController+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E862EC31ED39B1F1397A1156CD39DA34 /* QNUpToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E902ECD6C53BB02D2C0DFE4ED1DFB80 /* QNUpToken.h */; settings = {ATTRIBUTES = (Project, ); }; }; - EB663E3E1EB4BB670DC29B77DB330135 /* MASConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BBB37654FA6FFA35DF6F467EA9DAE41 /* MASConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F1B75048874B8773E5568E6D3ACA12E4 /* NSArray+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CE5C8D45CB8C2286EE24D02A5EFD2144 /* NSArray+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F3C726A690EF93FEF9EA010D80FF076F /* QNGetAddrInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = B813E8FC530CD9A48F62751D23CD3FD9 /* QNGetAddrInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - F4FD7E920FF8D52218C23DB3AD8BE9EB /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 031946BAC6C82F111FA4F25F48F36269 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0223F398FACF9030477C16C6A33EE8AF /* QNHex.m in Sources */ = {isa = PBXBuildFile; fileRef = 42FF2484EAF6FEF0325DB25C1CB5BAF4 /* QNHex.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 03F0CB5DC5A93F4995430671164F8289 /* QNPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC74062F17EEB0BAADD96596F4E5FCD /* QNPipeline.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0506161ED8DFB14E80E3A645C8FCFD0E /* QNRecorderDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = D8A96AFF0F2A525224C3A8B963BD4927 /* QNRecorderDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 055359B6E5778374720C30F1ABFB4D9F /* QNFormUpload.h in Headers */ = {isa = PBXBuildFile; fileRef = FA33CA8A3E73BA93F7D6B18627CE3CC3 /* QNFormUpload.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 065BB443AD2836956E88A9919E23E5A4 /* QNPipeline.m in Sources */ = {isa = PBXBuildFile; fileRef = D46D802FE3C5E604F8A2767EF9748175 /* QNPipeline.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 07D908C85D7CF125E2646CB0D8DEE030 /* QNResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = A38C637A2D50C60A866B95BD8AC30484 /* QNResolver.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0A34F4D5241243879C8650623C9CF56C /* QNUploadManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD23AD04B39F7887A670CEFE81BE163 /* QNUploadManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0AD8D53C5245C96AF567CE88BB19E84E /* Qiniu-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 251F8EDBD3E9AF3E670C1425D0C45296 /* Qiniu-dummy.m */; }; + 0B05BB82BBD2A997A620C50235A71992 /* QNIpModel.h in Headers */ = {isa = PBXBuildFile; fileRef = BEC33CDC2ACA958C49EA91B4BACD8160 /* QNIpModel.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0C349F150B29AC0C7ADE49387BC0399F /* QNResolverDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 12EF988943C29980A1178B61413B5F3F /* QNResolverDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0E2726233F99F246F9D39A7D774838F2 /* QNIP.m in Sources */ = {isa = PBXBuildFile; fileRef = 139A4C4EB18B71AD8EB9F1D4F821AA9B /* QNIP.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0E8A86C42E90907F71C35D6DBFE73685 /* QNHttpDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C75D8BA3309A5F386A48D3F6E14C672 /* QNHttpDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 107C68FEFE366330F32D876226A7208E /* QNUploadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F630B4755D91C52906292957E62819BD /* QNUploadManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 108D4601277E1B7A23AEF3C65C933EA5 /* QNPHAssetResource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B3F301781932578FC05A1D0864BC2EC /* QNPHAssetResource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 115ACCE253A886181B55773DDC70D6ED /* MASViewConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = DD349AB189A1E5758E75E8B2897676B8 /* MASViewConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1427A7143E9A2233D877C5983826ED38 /* QNResponseInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 5654DBA48FB304557D4DACC995FBADBB /* QNResponseInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 165BE042D8AE27116E0C467F3D047D9E /* QNUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 608CD01CAC4391C72BA2E675FC29BF26 /* QNUserAgent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 167909CD6A1BDC01A77005C42CD52941 /* HappyDNS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D668294813E0CF5DE57A8233F7B17B88 /* HappyDNS-dummy.m */; }; + 181B2691FF506F26F7F71F711C724B81 /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = D773FD178D07A41E68533B0937962979 /* MASConstraintMaker.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 18215DEC82E6C7DE502F02F4003F1788 /* FLAnimatedImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 85D47D6C7E51F98FFC1D2EAFD8209196 /* FLAnimatedImage-dummy.m */; }; + 18302B78A66A212BF674473DEC745E32 /* QNRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 43526337E35FB3BB252E45F6BEC9C569 /* QNRecord.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 18A705E9F6D779E2EE2317763FFC55FD /* QNFile.m in Sources */ = {isa = PBXBuildFile; fileRef = BF676F6DD9D700C91555D8010C1FCF26 /* QNFile.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1D71081556919F97A59595E226955DB2 /* QNPHAssetFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 01BE9317737637B79043B5F949ADFF92 /* QNPHAssetFile.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1E2B03A80923D9AA09213103132247C4 /* QNALAssetFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 09312936769EA6035C18A2C96EDE30D9 /* QNALAssetFile.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 20262DEB7FF7AABF747162A0129A899F /* QNAssessment.h in Headers */ = {isa = PBXBuildFile; fileRef = 42AE1D47AE1D8B3DAE9DA8ED142F88EA /* QNAssessment.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 204145CCC4E9112B54FCD334FBBD9E42 /* QNALAssetFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 9714C19A9136067C9ED213AD51D77EAA /* QNALAssetFile.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 20E2F8001CC8A41A0E1B50694BE7875D /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 032C153C332B2B8D25ADA36F195EC9CF /* NSArray+MASAdditions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 259A1A7649AA53CC59A83DE503863152 /* QNResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A523B1A0A3A9E8A8BB6BE60BD53CD9 /* QNResolver.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 262642A3FC3E59826CC759F56E886F10 /* QNConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9C35EA96F4725A017A16E6389CD622 /* QNConfiguration.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2A8331FB2BABA373C9C71FF466606A37 /* QNIpModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8460438A26D0367F7D3CE49786DA1DD0 /* QNIpModel.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2B36C0B8E5A23201375FC2EBBE791ECF /* QNDnspodEnterprise.m in Sources */ = {isa = PBXBuildFile; fileRef = 8688CFBCF706554DE3367922E5E9CD52 /* QNDnspodEnterprise.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2E5F3B41BD51ACE4EE3B422BB67E51DF /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E80B420B1341F48DF1706C2B542A85A /* MASViewAttribute.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2EF5EAF19497CFF0A22A1BDEDF48CF20 /* QNUploadOption+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 82D92D94FC52D6A000A4D1066F6DF508 /* QNUploadOption+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2FDCD3DB86841EC84712A9AE2E9FAEB8 /* QNRefresher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E2A5576C37F28A939ED652B047745CC /* QNRefresher.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 31064475EC704EC31BC3E2DE0DAFC72C /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 8DA5FE137AE88B7BB25977E652F257B8 /* MASViewConstraint.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3430321D06CBCF49F5A7DF6A70D9BB91 /* Masonry-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8ADF73A50A85B63D4EF41CC7D1954CA0 /* Masonry-dummy.m */; }; + 3567E54BF3DDC0C115C5FB58CF3403D7 /* QiniuSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BFCADF436E54CC59821AA9B9B624C1 /* QiniuSDK.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 390E8375B19FF12764C5AA730AF0F0F4 /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B5CB0E6E4B4B8E44B69E49C591DA5864 /* View+MASAdditions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3A30C57E0F6DB15E96E5A5BAE6220660 /* HappyDNS.h in Headers */ = {isa = PBXBuildFile; fileRef = C590A06B9F577CCE570E4E3A80D6AB8F /* HappyDNS.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3FDEFBFAD03902FC2A2D8578C1792AEE /* QNMD5.m in Sources */ = {isa = PBXBuildFile; fileRef = 20442E5BFB56F56A9072F4BD663A4EED /* QNMD5.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 42947699890A199B08A896144A878D80 /* MASViewAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B3B537C850F8E51E91990B55E501E75 /* MASViewAttribute.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 431E20FB6A3867B7678A12F589F706EB /* QNUrlSafeBase64.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E16BBA92A5B6529D014ADDDE17F014D /* QNUrlSafeBase64.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 438F57293439D5A8976D86ECED777598 /* QNFileRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 09F7A6BC25BBB6D1DF658105E77B14A1 /* QNFileRecorder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 43DF36988AE7D8D1B18417AD518D439A /* QNResumeUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 17922463B96260F824CFF5E91203923D /* QNResumeUpload.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 444E181D40FE34D7077E34FF1CEEBDC0 /* QN_GTM_Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CF730D761429A7F8849FBB2CA49DCCF /* QN_GTM_Base64.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 44A3B1A5D2C513F8FD238E3B64E4C6CF /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = C709789B5055201867A874848095D363 /* NSLayoutConstraint+MASDebugAdditions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 46692A2E77157B00827182C8DC686F72 /* View+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E1E3A45DB377DACA3FE75A9A07CD6395 /* View+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 46E3449855456D779144D3A3031510F8 /* QNResponseInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BA2607093FE849A63BF1F69833036E77 /* QNResponseInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4763919978EBF8FBEEBA930600B12FAA /* QNResolvUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 5313BA876CB1D4681FDDA13A26E10002 /* QNResolvUtil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 489646CE094DC2C5F763BDE39A52060A /* QNSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A6A9F8E7FE0F7C0123643FC1BDD6A29 /* QNSessionManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4AB9EE75B45CB020100A2898AF960277 /* QNVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 19D6A5B395CF4E5AB8B136F32EB9BD06 /* QNVersion.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4CE091F886EC6324673EFE0AEBBEA0FE /* MASConstraint+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1230171C576B2F951A1CAD3F27EDCF90 /* MASConstraint+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5BE94CDBD489AE23B3505C4F3AECEDE3 /* QNCrc32.h in Headers */ = {isa = PBXBuildFile; fileRef = 0077DFA11FDC2DF135DA7EB0F02632FA /* QNCrc32.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5C3A074F9ACA976E4CCC70BB915E3B5D /* QNUrlSafeBase64.m in Sources */ = {isa = PBXBuildFile; fileRef = E5878ADB6016978EFD90EE0A9B6501B7 /* QNUrlSafeBase64.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5C5C77BBF83B793B82713296519751DA /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F869468CDE07F5E40AC6E29DDADE73A /* ViewController+MASAdditions.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5E361429615E19B96BBA8E1F788C55C1 /* QNFileDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 447D861479B080EC63347D1F4EF383F2 /* QNFileDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 608E4C47DFAC69D71415C4C931A79E9C /* QNTxtResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B6F987C9FDE37575316A8DB0F0941F1 /* QNTxtResolver.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 610AA6B1793EE47811C5ED9649518CB0 /* QNConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 47BE44ABC1A3B9BFFEF227B7E7E3D9D4 /* QNConfiguration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 62CB484C994EBFF213FC25E4741B34A4 /* QNEtag.h in Headers */ = {isa = PBXBuildFile; fileRef = CE995301A30D9B57DDFE6B33E2BE157A /* QNEtag.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 65E88072A2BDC576BFC85E67EF9FBBC6 /* MASUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C1D8572AA962398E2A78E1D82782A55B /* MASUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 68734B2FD4E55F9A95D5B416C075074A /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 75131083A9B1D59EB273333512ECE0C6 /* MASLayoutConstraint.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6AE6B4B97D65D5B51F8936DEF90D86C1 /* QNUploadOption.m in Sources */ = {isa = PBXBuildFile; fileRef = CD19F6C3DCAC760FDEDFFB6EDAF233FD /* QNUploadOption.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6CFF1A337A614B48DEB4C71F221D4101 /* QNDes.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CC75A9169678CAF21F1CF4C44433B6F /* QNDes.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6DBF91EDE27C1994D366A7B54CEA6A05 /* QNAssessment.m in Sources */ = {isa = PBXBuildFile; fileRef = 660E1D19373892344199324D5F6D3A23 /* QNAssessment.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6DC91EFD9C630978FEF145A2ABD0CAD9 /* QNDnspodFree.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB1E299DE364D97EBEAE5F41D3855C4 /* QNDnspodFree.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6E67FD4BBC929A2D587FA49A7191275B /* QNDes.h in Headers */ = {isa = PBXBuildFile; fileRef = 92123AE036F69D7EA0BF32850DF13DF3 /* QNDes.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 71317EC60579F9D721A520E0D72A7FCC /* QNLruCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 89153FC28F023DCA84E0987948F84ABC /* QNLruCache.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7CF2AC7A3B3ED03B30C1E4ED662B0551 /* MASLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = FFD6FAD25E0AA62411389988F3B597E9 /* MASLayoutConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7D0FE4BC0CF22BC5FB0E0D56CCE0EB64 /* QNMD5.h in Headers */ = {isa = PBXBuildFile; fileRef = E75009F865E16D0B1B0EA7638FD7F949 /* QNMD5.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7D8CCC6C645A5185A68C2936754F6E3B /* QNHijackingDetectWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = D6F974108EFF133767377DF2F08F5F99 /* QNHijackingDetectWrapper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7E273D8F34CE76767C65B1B8A4C3E488 /* QNEtag.m in Sources */ = {isa = PBXBuildFile; fileRef = 1005AB0C0724543C6C6001A71C0010FA /* QNEtag.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7F0E1A708087C4B300FC79FF1F89BF31 /* QNUpToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 74D5FC77A796B0482942D08C217EE235 /* QNUpToken.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 80107EC7249A2C4727A661B6398A41D2 /* QNNetworkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7037AE5CE36B38B4E6173CA5585CFCA6 /* QNNetworkInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 80E647A750311CE63C0D6408A1985831 /* QNSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 860A8F6891F22794F5BEC558FBDBB0D3 /* QNSessionManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 81F811A56B6724F7E8E2D25364E595E3 /* NSArray+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = B1382A7E4DB5C4EADFCDD6B627AE1A50 /* NSArray+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 872A770D9F8EE265E8C232A6FFD6CE0A /* QNCrc32.m in Sources */ = {isa = PBXBuildFile; fileRef = 26E43CE4FB85E79C3D43AB5E40B402A0 /* QNCrc32.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 875B9C8AEBF475A93634436A151CAE3D /* QNDnspodEnterprise.h in Headers */ = {isa = PBXBuildFile; fileRef = 35437E1EA5219063C84B009ADC2115F6 /* QNDnspodEnterprise.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 87C322375DF7F1BF0BE9CBF42E52AB2F /* QNDnspodFree.h in Headers */ = {isa = PBXBuildFile; fileRef = C47809242B96C3D91746FE9EEAA38FC4 /* QNDnspodFree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 89B5378FEF108D21CB8FF754552AEB6E /* QN_GTM_Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF775BB281F4084526B8E1C45A6F621 /* QN_GTM_Base64.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8B99A2C79839BE0B9E85AFE9EDCE2938 /* QNHex.h in Headers */ = {isa = PBXBuildFile; fileRef = B0887D6DF568D65EA573778236BB5038 /* QNHex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8EABAB29E43027057B847DEBCF44CF71 /* QNUploadOption.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E1EE499A55DA3EE1A5685121A01E3B9 /* QNUploadOption.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9194B58ACE900ED6BAE6AD92E24A2CFF /* MASConstraintMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 684CCF34C91F59D771326975A7A1F2FB /* MASConstraintMaker.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 92BF70E9D3285561EB404A7C4A4A6DEE /* MASCompositeConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 18ED4995A3FDFDE88CC16C19E95552CA /* MASCompositeConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9B369AAD43832AEDBBDA8A0DF0856B4C /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 48F88630B329225653DB8B6B5BBD7B8D /* MASCompositeConstraint.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9D1886BF92B53141C422FD60D2447387 /* QNDnsManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 39D3C7D319C1B9DD0D3A9828AAD0B159 /* QNDnsManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9DBBFC86DAAAD727157BA6A34F817592 /* QNResolvUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 4FF76B3F3C58BAA41ED057BF477CBEE6 /* QNResolvUtil.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9EDEDD1974DDEBA5577DCB3A52868051 /* QNFormUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = FF2EDD3F480E1A0F2132A86BE3600604 /* QNFormUpload.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A3307B8FB6EE0A049DBAE3AA4D2C6DA0 /* View+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E98FC7E1E7FFC4B4532CEEEF0CCA07D7 /* View+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A4CED055F89DF5BBC853AF5315712804 /* QNFileRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = DEB4FC639569329AD524E5F676F8CD35 /* QNFileRecorder.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A5F40CB8E2A9A377EA61C8165C614276 /* QNLruCache.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD5384CB8CDABBEE50EBE45A6F7EC17 /* QNLruCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A855EFF54D728B8D3DC2071D81B75073 /* QNFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C0A6B662D2221D19320D1A91F0CBEAF /* QNFile.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AD1A880F8D70C400A8128D173D338FD1 /* QNRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 3532D6A894AD959CF03160FDF7D3E96F /* QNRecord.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AE19C2A5BF53E7B11231AC79D81EB153 /* QNSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 6748B8D214DA3086517660AFA4F9E663 /* QNSystem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AFEAD2E989FDC4BBB2CCA262700D7A8C /* QNSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 0385C2702D631D59F50927E94EBED0F2 /* QNSystem.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B1C3F81704ED34BEC59ED93E6B588CAE /* QNDomain.m in Sources */ = {isa = PBXBuildFile; fileRef = BC6341B97CE57312C97E3DEB241AF14B /* QNDomain.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B20A0E5D8F9BCED1A82793C4BE9E7258 /* Masonry.h in Headers */ = {isa = PBXBuildFile; fileRef = D9C0A5840EE29894065B9CAA3CD9BC47 /* Masonry.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B2D473ECD52217A35F50382B265B10EE /* QNAsyncRun.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B2C0A12476E208F6B93D19352F051E4 /* QNAsyncRun.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B3E0E5C146898F993C1172F263EAFE20 /* QNDomain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7182743DE2E37EFE069F4052BD27B1AB /* QNDomain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B4D99CCC2DF6E36BAA183606945147CF /* QNDnsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1958F44E7748938ED4BF775FF03EE59F /* QNDnsManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + BFCF31C2FE8858041CBD281750CDEAC9 /* QNHosts.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A936A47D933D7DD1316F8C76C6C6594 /* QNHosts.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C2419F0D058F489D0C161AEDEFF14C34 /* QNHijackingDetectWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 397063E3861E91347F31BCEA0AC695C5 /* QNHijackingDetectWrapper.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C74D2E856ADC8139CD00DBD184061B23 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 99CC6F2E5292F44FB8A8C9DA15376430 /* NSLayoutConstraint+MASDebugAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C8F337A161E101252BB63498F830F4E2 /* QNGetAddrInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C7A211FD26AA0FEE95BD85DFE258031 /* QNGetAddrInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C9B2F8E482E5A42882ABDB5416C3184A /* QNPHAssetResource.m in Sources */ = {isa = PBXBuildFile; fileRef = 1714829E65E727602005B5E20B3FB1BC /* QNPHAssetResource.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CA231C4FDAA90356774A050004DFB489 /* QNPHAssetFile.m in Sources */ = {isa = PBXBuildFile; fileRef = DDA13A5BBA068AC1E5BE0BFAD0B968EC /* QNPHAssetFile.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CAEA05C442E1556ABDDB634213B2812A /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = B80E7FFDBC83E89EA351972762440AD7 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CF3DDB06547EC1A30633781E66B67AA4 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D3977D017B02841C80744BC4C2953854 /* FLAnimatedImage.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D1FF72DCA476246D61CA1F52FC30EC7A /* QNHosts.h in Headers */ = {isa = PBXBuildFile; fileRef = 884B179B888EB933B0C3526DB4AB5D38 /* QNHosts.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D631BC92AD923A758BF7318E2D42986B /* QNAsyncRun.h in Headers */ = {isa = PBXBuildFile; fileRef = E0450788FF31FD3EC901447DD2454F82 /* QNAsyncRun.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D65722AE5FFA04DBA5429BE359EF3C02 /* QNResumeUpload.h in Headers */ = {isa = PBXBuildFile; fileRef = B7021275D95CB1B28E0D0504F60504EC /* QNResumeUpload.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D74E19C40335D318C539A7363C6C1A5D /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 002EBBE97F186FC69A82F51430450554 /* FLAnimatedImageView.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D783A8A5A426DBF85162B92142651218 /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 40152D4AA776DE3EA4E94CA8C5A45779 /* MASConstraint.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DA6C7CE62D0E4E67E1644EC6C63A9962 /* QNGetAddrInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F61DA42452759D7331D87AF76A01D2A7 /* QNGetAddrInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E76935CFF4AF327F8D9A7C1935F7D900 /* ViewController+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C1C6B863A30E60F32470D90AB671147 /* ViewController+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E862EC31ED39B1F1397A1156CD39DA34 /* QNUpToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE394E0FF4ACA1E57C586603AECF003 /* QNUpToken.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EA8FBE880DD634AAE2461880E6C837E2 /* QNIP.h in Headers */ = {isa = PBXBuildFile; fileRef = D3CA70BE4154092A3B58B8703BAA1628 /* QNIP.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EB663E3E1EB4BB670DC29B77DB330135 /* MASConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B9DB2F18A0B57E0B6A5BFA2BB8AD674 /* MASConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; + ED738B69225DB9D84BA1F49EDFFE9815 /* QNTxtResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = ABAE64BB345694B597A6989424E0261A /* QNTxtResolver.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F1B75048874B8773E5568E6D3ACA12E4 /* NSArray+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F07C1AD06F5448E124503B4F3B99F9 /* NSArray+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F4FD7E920FF8D52218C23DB3AD8BE9EB /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 82100F8AE00F077DA3F75291F16B2C3D /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Project, ); }; }; F532AFEFB9B296A8A61FA931F1F0D51C /* Pods-PLShortVideoKitDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D355385615BF3BDA15D02119FF901C7 /* Pods-PLShortVideoKitDemo-dummy.m */; }; - FAA7320A82603CFC2D8C3EEFDE09DCC1 /* QNUserAgent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5468E5645E1AFBE700837DB27EDB12BF /* QNUserAgent.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F5EA11D2C0C897302E4C916D913C4643 /* QNRefresher.h in Headers */ = {isa = PBXBuildFile; fileRef = C7D95CB6DFD898284CB7B3201C6C6490 /* QNRefresher.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F916166E7B62F41F5021B27430F6AC41 /* QNNetworkInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = C3D9E3862136736072BD591291B17CB0 /* QNNetworkInfo.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FAA7320A82603CFC2D8C3EEFDE09DCC1 /* QNUserAgent.m in Sources */ = {isa = PBXBuildFile; fileRef = 17827DBF5B339FF1D4A49AF4EB5DB7A6 /* QNUserAgent.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -241,167 +239,165 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 01D58F57B5EA09A711930FF5BCB81EA7 /* QNSystem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNSystem.h; path = QiniuSDK/Common/QNSystem.h; sourceTree = ""; }; - 031946BAC6C82F111FA4F25F48F36269 /* FLAnimatedImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImageView.h; path = FLAnimatedImage/FLAnimatedImageView.h; sourceTree = ""; }; - 0368138DC69AB564D1226C9D5A7BA2FF /* QNHttpDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNHttpDelegate.h; path = QiniuSDK/Http/QNHttpDelegate.h; sourceTree = ""; }; - 04B1F8B746EFC83F11E8890D5DBDC9B4 /* QNRecorderDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNRecorderDelegate.h; path = QiniuSDK/Recorder/QNRecorderDelegate.h; sourceTree = ""; }; - 04E2183A218091F317D6124CBF08A9DE /* QNCrc32.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNCrc32.h; path = QiniuSDK/Common/QNCrc32.h; sourceTree = ""; }; - 0590017E2114863B3416C5F2101428BE /* QNDomain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDomain.h; path = HappyDNS/Common/QNDomain.h; sourceTree = ""; }; - 066E515A3F5D7DEC8797D64762224A09 /* QNNiuDns.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNNiuDns.h; path = HappyDNS/Http/QNNiuDns.h; sourceTree = ""; }; - 0811287B2386E5BF99443E6B3DF4651E /* CLSLogging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSLogging.h; path = iOS/Crashlytics.framework/Headers/CLSLogging.h; sourceTree = ""; }; - 0948776AB9F038B34F6E8D171A9DC9E1 /* QNAssessment.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNAssessment.m; path = HappyDNS/Assessment/QNAssessment.m; sourceTree = ""; }; - 0954AB11364886615FED979B28080F6F /* QNResponseInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResponseInfo.h; path = QiniuSDK/Http/QNResponseInfo.h; sourceTree = ""; }; - 09ED1A59AFE3363CCB2121888660C306 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = iOS/Crashlytics.framework; sourceTree = ""; }; - 0A1A3F685B43444F89639ADC31C75633 /* QNUpToken.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUpToken.m; path = QiniuSDK/Storage/QNUpToken.m; sourceTree = ""; }; - 0E902ECD6C53BB02D2C0DFE4ED1DFB80 /* QNUpToken.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUpToken.h; path = QiniuSDK/Storage/QNUpToken.h; sourceTree = ""; }; - 0EC7D773547E63E83CD022000A211F04 /* HappyDNS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HappyDNS-dummy.m"; sourceTree = ""; }; - 0F57C42060317FE87EB1BB3E9A4F4A70 /* QN_GTM_Base64.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QN_GTM_Base64.m; path = QiniuSDK/Common/QN_GTM_Base64.m; sourceTree = ""; }; - 130A3033AF8956D7ACE795B982A7BD9D /* QNUrlSafeBase64.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUrlSafeBase64.m; path = QiniuSDK/Common/QNUrlSafeBase64.m; sourceTree = ""; }; - 14737354608E32510CFD9F907F5ED324 /* MASViewConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewConstraint.m; path = Masonry/MASViewConstraint.m; sourceTree = ""; }; - 14F7F4C6B9E632A87F2D43189F6ED3F4 /* Masonry-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-prefix.pch"; sourceTree = ""; }; - 1761496D72C307EFDD9EDD62B4B592F7 /* MASConstraintMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraintMaker.h; path = Masonry/MASConstraintMaker.h; sourceTree = ""; }; - 1810CF6A6B37A2657A156481418D1E1C /* Crashlytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Crashlytics.xcconfig; sourceTree = ""; }; - 18CD98380FFBFC73BF79790911B1335E /* QNTxtResolver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNTxtResolver.m; path = HappyDNS/Local/QNTxtResolver.m; sourceTree = ""; }; - 19C915FDA8D4EA64E92B9E4E70E9D701 /* QNLruCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNLruCache.h; path = HappyDNS/Common/QNLruCache.h; sourceTree = ""; }; - 1B1FD9B2AE2BAEB934281DC75A5EEF23 /* QNTxtResolver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNTxtResolver.h; path = HappyDNS/Local/QNTxtResolver.h; sourceTree = ""; }; - 1BA95F8C9277D267EADC95252D10EA61 /* QNEtag.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNEtag.m; path = QiniuSDK/Common/QNEtag.m; sourceTree = ""; }; - 1C7C330AB16CA1A1D339D7A9FF93DB0B /* QNMD5.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNMD5.m; path = HappyDNS/Util/QNMD5.m; sourceTree = ""; }; - 1CDAC700BDCE8CE4BB7541970F74C973 /* QNFile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNFile.h; path = QiniuSDK/Common/QNFile.h; sourceTree = ""; }; - 1D62DC3985963E3DADB4781DF6F8F0E7 /* QNDes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDes.h; path = HappyDNS/Util/QNDes.h; sourceTree = ""; }; - 1DC5780C10EF06CE1B7C79B7135FB4AB /* QNNetworkInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNNetworkInfo.m; path = HappyDNS/Common/QNNetworkInfo.m; sourceTree = ""; }; + 002EBBE97F186FC69A82F51430450554 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImageView.m; path = FLAnimatedImage/FLAnimatedImageView.m; sourceTree = ""; }; + 0077DFA11FDC2DF135DA7EB0F02632FA /* QNCrc32.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNCrc32.h; path = QiniuSDK/Common/QNCrc32.h; sourceTree = ""; }; + 01BE9317737637B79043B5F949ADFF92 /* QNPHAssetFile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNPHAssetFile.h; path = QiniuSDK/Common/QNPHAssetFile.h; sourceTree = ""; }; + 032C153C332B2B8D25ADA36F195EC9CF /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MASAdditions.m"; path = "Masonry/NSArray+MASAdditions.m"; sourceTree = ""; }; + 0385C2702D631D59F50927E94EBED0F2 /* QNSystem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNSystem.m; path = QiniuSDK/Common/QNSystem.m; sourceTree = ""; }; + 09312936769EA6035C18A2C96EDE30D9 /* QNALAssetFile.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNALAssetFile.m; path = QiniuSDK/Common/QNALAssetFile.m; sourceTree = ""; }; + 09F7A6BC25BBB6D1DF658105E77B14A1 /* QNFileRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNFileRecorder.h; path = QiniuSDK/Recorder/QNFileRecorder.h; sourceTree = ""; }; + 0CC75A9169678CAF21F1CF4C44433B6F /* QNDes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDes.m; path = HappyDNS/Util/QNDes.m; sourceTree = ""; }; + 0F869468CDE07F5E40AC6E29DDADE73A /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "ViewController+MASAdditions.m"; path = "Masonry/ViewController+MASAdditions.m"; sourceTree = ""; }; + 1005AB0C0724543C6C6001A71C0010FA /* QNEtag.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNEtag.m; path = QiniuSDK/Common/QNEtag.m; sourceTree = ""; }; + 1230171C576B2F951A1CAD3F27EDCF90 /* MASConstraint+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MASConstraint+Private.h"; path = "Masonry/MASConstraint+Private.h"; sourceTree = ""; }; + 12EF988943C29980A1178B61413B5F3F /* QNResolverDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResolverDelegate.h; path = HappyDNS/Common/QNResolverDelegate.h; sourceTree = ""; }; + 139A4C4EB18B71AD8EB9F1D4F821AA9B /* QNIP.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNIP.m; path = HappyDNS/Util/QNIP.m; sourceTree = ""; }; + 147FF0BFE084607E0DEDC8294D7176FF /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = iOS/Fabric.framework; sourceTree = ""; }; + 14BFCADF436E54CC59821AA9B9B624C1 /* QiniuSDK.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QiniuSDK.h; path = QiniuSDK/QiniuSDK.h; sourceTree = ""; }; + 1714829E65E727602005B5E20B3FB1BC /* QNPHAssetResource.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNPHAssetResource.m; path = QiniuSDK/Common/QNPHAssetResource.m; sourceTree = ""; }; + 17827DBF5B339FF1D4A49AF4EB5DB7A6 /* QNUserAgent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUserAgent.m; path = QiniuSDK/Http/QNUserAgent.m; sourceTree = ""; }; + 17922463B96260F824CFF5E91203923D /* QNResumeUpload.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNResumeUpload.m; path = QiniuSDK/Storage/QNResumeUpload.m; sourceTree = ""; }; + 18ED4995A3FDFDE88CC16C19E95552CA /* MASCompositeConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASCompositeConstraint.h; path = Masonry/MASCompositeConstraint.h; sourceTree = ""; }; + 18FAC25C1AD69EA222A9050A962AC5C1 /* FLAnimatedImage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FLAnimatedImage.xcconfig; sourceTree = ""; }; + 1958F44E7748938ED4BF775FF03EE59F /* QNDnsManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDnsManager.m; path = HappyDNS/Common/QNDnsManager.m; sourceTree = ""; }; + 19D6A5B395CF4E5AB8B136F32EB9BD06 /* QNVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNVersion.h; path = QiniuSDK/Common/QNVersion.h; sourceTree = ""; }; + 1A936A47D933D7DD1316F8C76C6C6594 /* QNHosts.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNHosts.m; path = HappyDNS/Local/QNHosts.m; sourceTree = ""; }; + 1EF775BB281F4084526B8E1C45A6F621 /* QN_GTM_Base64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QN_GTM_Base64.h; path = QiniuSDK/Common/QN_GTM_Base64.h; sourceTree = ""; }; 1FFED36A657123030ABB700256D73F15 /* libMasonry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libMasonry.a; path = libMasonry.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 276FA87254F0EC58970AE6C3352D8800 /* QNUploadOption.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUploadOption.m; path = QiniuSDK/Storage/QNUploadOption.m; sourceTree = ""; }; - 2992C522F75BC6F2E7782C166611D474 /* QNRecord.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNRecord.m; path = HappyDNS/Common/QNRecord.m; sourceTree = ""; }; - 29BD5A5D14DEDA9430D27CD301654B53 /* QNPHAssetResource.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNPHAssetResource.m; path = QiniuSDK/Common/QNPHAssetResource.m; sourceTree = ""; }; - 2CB647AF6ED8CE53ADCB2349EADB6F3C /* FLAnimatedImage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FLAnimatedImage.xcconfig; sourceTree = ""; }; - 30D742796965426E10F87542550C06BF /* QNNiuDns.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNNiuDns.m; path = HappyDNS/Http/QNNiuDns.m; sourceTree = ""; }; + 20442E5BFB56F56A9072F4BD663A4EED /* QNMD5.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNMD5.m; path = HappyDNS/Util/QNMD5.m; sourceTree = ""; }; + 21A523B1A0A3A9E8A8BB6BE60BD53CD9 /* QNResolver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResolver.h; path = HappyDNS/Local/QNResolver.h; sourceTree = ""; }; + 251F8EDBD3E9AF3E670C1425D0C45296 /* Qiniu-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Qiniu-dummy.m"; sourceTree = ""; }; + 26E43CE4FB85E79C3D43AB5E40B402A0 /* QNCrc32.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNCrc32.m; path = QiniuSDK/Common/QNCrc32.m; sourceTree = ""; }; + 2B2C0A12476E208F6B93D19352F051E4 /* QNAsyncRun.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNAsyncRun.m; path = QiniuSDK/Common/QNAsyncRun.m; sourceTree = ""; }; + 2B9DB2F18A0B57E0B6A5BFA2BB8AD674 /* MASConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraint.h; path = Masonry/MASConstraint.h; sourceTree = ""; }; + 2C0A6B662D2221D19320D1A91F0CBEAF /* QNFile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNFile.h; path = QiniuSDK/Common/QNFile.h; sourceTree = ""; }; + 2C43C89D041898ADFA61467FF4CFCC9E /* CLSReport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSReport.h; path = iOS/Crashlytics.framework/Headers/CLSReport.h; sourceTree = ""; }; + 2CCADDB26BCC08DCF21B7B007CF78A9C /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = iOS/Crashlytics.framework; sourceTree = ""; }; 334B5E40A637359D268670FA1764C897 /* Pods-PLShortVideoKitDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PLShortVideoKitDemo.release.xcconfig"; sourceTree = ""; }; - 33C531193DCEC89A11A171742430000C /* MASConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraint.m; path = Masonry/MASConstraint.m; sourceTree = ""; }; + 3532D6A894AD959CF03160FDF7D3E96F /* QNRecord.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNRecord.h; path = HappyDNS/Common/QNRecord.h; sourceTree = ""; }; + 35437E1EA5219063C84B009ADC2115F6 /* QNDnspodEnterprise.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDnspodEnterprise.h; path = HappyDNS/Http/QNDnspodEnterprise.h; sourceTree = ""; }; 3667B5F6798CDC2ADA1BBC70D052FF68 /* libHappyDNS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libHappyDNS.a; path = libHappyDNS.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 36BB14AFEC9874B05E9B179B60997BF9 /* QNUploadManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUploadManager.m; path = QiniuSDK/Storage/QNUploadManager.m; sourceTree = ""; }; - 3A075D22DB6C1C0A90F79A4059168670 /* HappyDNS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HappyDNS-prefix.pch"; sourceTree = ""; }; - 3AD6D3A8C177CAB6555315C35D76C9FF /* QNUploadOption.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUploadOption.h; path = QiniuSDK/Storage/QNUploadOption.h; sourceTree = ""; }; - 3BF668BE143F24CFB5DCF7E2EF65B694 /* QNMD5.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNMD5.h; path = HappyDNS/Util/QNMD5.h; sourceTree = ""; }; - 3BFAFA72BAED0EB1F693AA077935AFA0 /* QN_GTM_Base64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QN_GTM_Base64.h; path = QiniuSDK/Common/QN_GTM_Base64.h; sourceTree = ""; }; - 3C1B09B668B6635F9E63DDF38D4CAED1 /* MASCompositeConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASCompositeConstraint.m; path = Masonry/MASCompositeConstraint.m; sourceTree = ""; }; - 3CA65FF87C695B148ED228D17735C4C3 /* QNFileRecorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNFileRecorder.h; path = QiniuSDK/Recorder/QNFileRecorder.h; sourceTree = ""; }; + 397063E3861E91347F31BCEA0AC695C5 /* QNHijackingDetectWrapper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNHijackingDetectWrapper.m; path = HappyDNS/Local/QNHijackingDetectWrapper.m; sourceTree = ""; }; + 39D3C7D319C1B9DD0D3A9828AAD0B159 /* QNDnsManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDnsManager.h; path = HappyDNS/Common/QNDnsManager.h; sourceTree = ""; }; + 3A6A9F8E7FE0F7C0123643FC1BDD6A29 /* QNSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNSessionManager.m; path = QiniuSDK/Http/QNSessionManager.m; sourceTree = ""; }; + 3B3F301781932578FC05A1D0864BC2EC /* QNPHAssetResource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNPHAssetResource.h; path = QiniuSDK/Common/QNPHAssetResource.h; sourceTree = ""; }; 3D355385615BF3BDA15D02119FF901C7 /* Pods-PLShortVideoKitDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PLShortVideoKitDemo-dummy.m"; sourceTree = ""; }; - 3FBD8ECB98692FA39A12D024B762A297 /* MASViewAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewAttribute.h; path = Masonry/MASViewAttribute.h; sourceTree = ""; }; - 4030E9756D6612DAE1B2111D9591AB8E /* QNDomain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDomain.m; path = HappyDNS/Common/QNDomain.m; sourceTree = ""; }; - 4042BE7BC2CAB768E4E7F7999137A814 /* FLAnimatedImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FLAnimatedImage-dummy.m"; sourceTree = ""; }; - 4102119BB577809706CD9807D512A81A /* QNIP.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNIP.h; path = HappyDNS/Util/QNIP.h; sourceTree = ""; }; - 4743FF73E5E40D32B83469BB782EF4F7 /* QNRecord.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNRecord.h; path = HappyDNS/Common/QNRecord.h; sourceTree = ""; }; - 4B0E03E41B27017F8264E37B4A69CD17 /* QNUploadOption+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "QNUploadOption+Private.h"; path = "QiniuSDK/Storage/QNUploadOption+Private.h"; sourceTree = ""; }; - 4B3138CDB4F01659791AC010864C730A /* Answers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Answers.h; path = iOS/Crashlytics.framework/Headers/Answers.h; sourceTree = ""; }; - 4C7B46FA531047A26C57D2C16BEA4243 /* QNFormUpload.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNFormUpload.h; path = QiniuSDK/Storage/QNFormUpload.h; sourceTree = ""; }; - 4CBDD03638D0B4E09983F0731BCC6244 /* CLSReport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSReport.h; path = iOS/Crashlytics.framework/Headers/CLSReport.h; sourceTree = ""; }; - 4CD61B5E61D2705FCBDF0E2FD06D3764 /* QNConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNConfiguration.m; path = QiniuSDK/Storage/QNConfiguration.m; sourceTree = ""; }; - 4CEA2F31CFECC8753DF165972567DA95 /* QNIP.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNIP.m; path = HappyDNS/Util/QNIP.m; sourceTree = ""; }; + 40152D4AA776DE3EA4E94CA8C5A45779 /* MASConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraint.m; path = Masonry/MASConstraint.m; sourceTree = ""; }; + 42AE1D47AE1D8B3DAE9DA8ED142F88EA /* QNAssessment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNAssessment.h; path = HappyDNS/Assessment/QNAssessment.h; sourceTree = ""; }; + 42FF2484EAF6FEF0325DB25C1CB5BAF4 /* QNHex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNHex.m; path = HappyDNS/Util/QNHex.m; sourceTree = ""; }; + 43526337E35FB3BB252E45F6BEC9C569 /* QNRecord.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNRecord.m; path = HappyDNS/Common/QNRecord.m; sourceTree = ""; }; + 447D861479B080EC63347D1F4EF383F2 /* QNFileDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNFileDelegate.h; path = QiniuSDK/Common/QNFileDelegate.h; sourceTree = ""; }; + 47BE44ABC1A3B9BFFEF227B7E7E3D9D4 /* QNConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNConfiguration.h; path = QiniuSDK/Storage/QNConfiguration.h; sourceTree = ""; }; + 48F88630B329225653DB8B6B5BBD7B8D /* MASCompositeConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASCompositeConstraint.m; path = Masonry/MASCompositeConstraint.m; sourceTree = ""; }; + 4C7A211FD26AA0FEE95BD85DFE258031 /* QNGetAddrInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNGetAddrInfo.m; path = HappyDNS/Util/QNGetAddrInfo.m; sourceTree = ""; }; + 4CF730D761429A7F8849FBB2CA49DCCF /* QN_GTM_Base64.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QN_GTM_Base64.m; path = QiniuSDK/Common/QN_GTM_Base64.m; sourceTree = ""; }; 4E7F41B08CC41191A77E71DE91266680 /* PLShortVideoKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PLShortVideoKit.xcconfig; sourceTree = ""; }; - 50A3E4BCDDB3A71E486D4B982E1FC5DA /* MASUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASUtilities.h; path = Masonry/MASUtilities.h; sourceTree = ""; }; - 51CB2C9D11B0382BC645CF9DEABAD01A /* QNNetworkInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNNetworkInfo.h; path = HappyDNS/Common/QNNetworkInfo.h; sourceTree = ""; }; - 5468E5645E1AFBE700837DB27EDB12BF /* QNUserAgent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUserAgent.m; path = QiniuSDK/Http/QNUserAgent.m; sourceTree = ""; }; + 4FF76B3F3C58BAA41ED057BF477CBEE6 /* QNResolvUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNResolvUtil.m; path = HappyDNS/Local/QNResolvUtil.m; sourceTree = ""; }; + 5313BA876CB1D4681FDDA13A26E10002 /* QNResolvUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResolvUtil.h; path = HappyDNS/Local/QNResolvUtil.h; sourceTree = ""; }; + 53C89494F59D7562B6CCCBD355AC9361 /* Masonry.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.xcconfig; sourceTree = ""; }; 5579F3C731610F7627DDB5D504E78D8A /* Pods-PLShortVideoKitDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PLShortVideoKitDemo-acknowledgements.markdown"; sourceTree = ""; }; - 55CDED97E866A21F98798C86CDCA8E1F /* MASConstraint+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MASConstraint+Private.h"; path = "Masonry/MASConstraint+Private.h"; sourceTree = ""; }; - 57103069BF70B2AC884EC1CFAA620A8D /* QNResumeUpload.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResumeUpload.h; path = QiniuSDK/Storage/QNResumeUpload.h; sourceTree = ""; }; - 5763011EAF2D09C0F745FC936AFD8802 /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "ViewController+MASAdditions.m"; path = "Masonry/ViewController+MASAdditions.m"; sourceTree = ""; }; - 589247593CC6D20DA3C3D985B84D1A77 /* QNDnspodFree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDnspodFree.h; path = HappyDNS/Http/QNDnspodFree.h; sourceTree = ""; }; - 58DCFDD6DDA971FB8589C74F927A2324 /* Fabric.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Fabric.xcconfig; sourceTree = ""; }; - 5BBB37654FA6FFA35DF6F467EA9DAE41 /* MASConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraint.h; path = Masonry/MASConstraint.h; sourceTree = ""; }; - 5D6C5A3E6B085354F15BCA52EB126DD4 /* QNUploadManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUploadManager.h; path = QiniuSDK/Storage/QNUploadManager.h; sourceTree = ""; }; - 5DE4D0D6A9512AE92730F168E054B09B /* FLAnimatedImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImageView.m; path = FLAnimatedImage/FLAnimatedImageView.m; sourceTree = ""; }; - 606E2668409C5AADC816CEA621704FFA /* QNPHAssetResource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNPHAssetResource.h; path = QiniuSDK/Common/QNPHAssetResource.h; sourceTree = ""; }; - 60F2581C079F942A9F1ECC9517592FC6 /* CLSAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSAttributes.h; path = iOS/Crashlytics.framework/Headers/CLSAttributes.h; sourceTree = ""; }; - 6112B38D2494947997368BFF51A4D453 /* Masonry-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Masonry-dummy.m"; sourceTree = ""; }; - 616A9B8A95D05602A7C3AB65BFA8FA2C /* QNResolvUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNResolvUtil.m; path = HappyDNS/Local/QNResolvUtil.m; sourceTree = ""; }; - 621109AAF2C0D7A0D57A1CC1959C5B48 /* FLAnimatedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImage.h; path = FLAnimatedImage/FLAnimatedImage.h; sourceTree = ""; }; - 62798C8D70EEBBBD2FDFB65A89442DFF /* QNHijackingDetectWrapper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNHijackingDetectWrapper.h; path = HappyDNS/Local/QNHijackingDetectWrapper.h; sourceTree = ""; }; - 6372348C9CBCC484FC15B206BF839C42 /* QNGetAddrInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNGetAddrInfo.h; path = HappyDNS/Util/QNGetAddrInfo.h; sourceTree = ""; }; - 63AC1F0E19EE8E0C6E6793860A00412A /* QNDnspodEnterprise.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDnspodEnterprise.m; path = HappyDNS/Http/QNDnspodEnterprise.m; sourceTree = ""; }; - 6D007BB64566319240C8CE6A10FE3C60 /* QNResponseInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNResponseInfo.m; path = QiniuSDK/Http/QNResponseInfo.m; sourceTree = ""; }; - 6EC9788E7CE0F5B9DD37A36DBA564BFB /* QNIpModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNIpModel.h; path = HappyDNS/Assessment/QNIpModel.h; sourceTree = ""; }; - 707B3A46C129C0610EFFE5EA956C6287 /* QNResumeUpload.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNResumeUpload.m; path = QiniuSDK/Storage/QNResumeUpload.m; sourceTree = ""; }; - 7125FE0ADDC9EBAA36B3D5504D03903C /* QNDnspodEnterprise.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDnspodEnterprise.h; path = HappyDNS/Http/QNDnspodEnterprise.h; sourceTree = ""; }; - 718B3EC939241DAF2BD44F90089E875F /* QNAsyncRun.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNAsyncRun.m; path = QiniuSDK/Common/QNAsyncRun.m; sourceTree = ""; }; + 5654DBA48FB304557D4DACC995FBADBB /* QNResponseInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNResponseInfo.m; path = QiniuSDK/Http/QNResponseInfo.m; sourceTree = ""; }; + 5B6F987C9FDE37575316A8DB0F0941F1 /* QNTxtResolver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNTxtResolver.h; path = HappyDNS/Local/QNTxtResolver.h; sourceTree = ""; }; + 608CD01CAC4391C72BA2E675FC29BF26 /* QNUserAgent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUserAgent.h; path = QiniuSDK/Http/QNUserAgent.h; sourceTree = ""; }; + 6296D8C7CA0FF181715EF1C7782B5E4C /* Qiniu.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Qiniu.xcconfig; sourceTree = ""; }; + 660E1D19373892344199324D5F6D3A23 /* QNAssessment.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNAssessment.m; path = HappyDNS/Assessment/QNAssessment.m; sourceTree = ""; }; + 6748B8D214DA3086517660AFA4F9E663 /* QNSystem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNSystem.h; path = QiniuSDK/Common/QNSystem.h; sourceTree = ""; }; + 684CCF34C91F59D771326975A7A1F2FB /* MASConstraintMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraintMaker.h; path = Masonry/MASConstraintMaker.h; sourceTree = ""; }; + 69CC7F0099A810CC74C11DD20D18CD34 /* HappyDNS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HappyDNS.xcconfig; sourceTree = ""; }; + 6E1EE499A55DA3EE1A5685121A01E3B9 /* QNUploadOption.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUploadOption.h; path = QiniuSDK/Storage/QNUploadOption.h; sourceTree = ""; }; + 6EE394E0FF4ACA1E57C586603AECF003 /* QNUpToken.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUpToken.h; path = QiniuSDK/Storage/QNUpToken.h; sourceTree = ""; }; + 7037AE5CE36B38B4E6173CA5585CFCA6 /* QNNetworkInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNNetworkInfo.h; path = HappyDNS/Common/QNNetworkInfo.h; sourceTree = ""; }; + 70F6C61E75E25D3DDB3A8D28DCA8C130 /* Crashlytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Crashlytics.xcconfig; sourceTree = ""; }; + 7182743DE2E37EFE069F4052BD27B1AB /* QNDomain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDomain.h; path = HappyDNS/Common/QNDomain.h; sourceTree = ""; }; 72D48CA3ED920AA850982997878E45CC /* libPods-PLShortVideoKitDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-PLShortVideoKitDemo.a"; path = "libPods-PLShortVideoKitDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 7564ECB1BE548098EA82717AE1428436 /* QNALAssetFile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNALAssetFile.h; path = QiniuSDK/Common/QNALAssetFile.h; sourceTree = ""; }; - 781066C5AC71BC86276C51735727C18C /* View+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "View+MASAdditions.m"; path = "Masonry/View+MASAdditions.m"; sourceTree = ""; }; - 7C789F6B08F93A8A25DB4C7D2EA7D57C /* QNDes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDes.m; path = HappyDNS/Util/QNDes.m; sourceTree = ""; }; - 7F6A0685DEECD46087AADA5C475A3A35 /* QNResolver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNResolver.m; path = HappyDNS/Local/QNResolver.m; sourceTree = ""; }; - 80293F9176725CD1B877779AF2A0D765 /* QNIpModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNIpModel.m; path = HappyDNS/Assessment/QNIpModel.m; sourceTree = ""; }; - 80FEBF8EDB6F5A42D38F9BF5D293340C /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MASAdditions.m"; path = "Masonry/NSArray+MASAdditions.m"; sourceTree = ""; }; - 8182DEA6FC5EF5AB87D0DA284574EE91 /* QNSystem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNSystem.m; path = QiniuSDK/Common/QNSystem.m; sourceTree = ""; }; - 81954B9704062F42BEEB2B32DAD6AB71 /* QNFormUpload.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNFormUpload.m; path = QiniuSDK/Storage/QNFormUpload.m; sourceTree = ""; }; - 85E05EE6F0191CE3CB4B2FE46B389691 /* Crashlytics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Crashlytics.h; path = iOS/Crashlytics.framework/Headers/Crashlytics.h; sourceTree = ""; }; - 8BCAD8EF0CF9ABBBE260F99D3DFCCF5B /* MASViewAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewAttribute.m; path = Masonry/MASViewAttribute.m; sourceTree = ""; }; + 74D5FC77A796B0482942D08C217EE235 /* QNUpToken.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUpToken.m; path = QiniuSDK/Storage/QNUpToken.m; sourceTree = ""; }; + 75131083A9B1D59EB273333512ECE0C6 /* MASLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASLayoutConstraint.m; path = Masonry/MASLayoutConstraint.m; sourceTree = ""; }; + 7BD23AD04B39F7887A670CEFE81BE163 /* QNUploadManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUploadManager.h; path = QiniuSDK/Storage/QNUploadManager.h; sourceTree = ""; }; + 7C75D8BA3309A5F386A48D3F6E14C672 /* QNHttpDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNHttpDelegate.h; path = QiniuSDK/Http/QNHttpDelegate.h; sourceTree = ""; }; + 7E16BBA92A5B6529D014ADDDE17F014D /* QNUrlSafeBase64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUrlSafeBase64.h; path = QiniuSDK/Common/QNUrlSafeBase64.h; sourceTree = ""; }; + 82100F8AE00F077DA3F75291F16B2C3D /* FLAnimatedImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImageView.h; path = FLAnimatedImage/FLAnimatedImageView.h; sourceTree = ""; }; + 82D92D94FC52D6A000A4D1066F6DF508 /* QNUploadOption+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "QNUploadOption+Private.h"; path = "QiniuSDK/Storage/QNUploadOption+Private.h"; sourceTree = ""; }; + 8460438A26D0367F7D3CE49786DA1DD0 /* QNIpModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNIpModel.m; path = HappyDNS/Assessment/QNIpModel.m; sourceTree = ""; }; + 85D47D6C7E51F98FFC1D2EAFD8209196 /* FLAnimatedImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FLAnimatedImage-dummy.m"; sourceTree = ""; }; + 860A8F6891F22794F5BEC558FBDBB0D3 /* QNSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNSessionManager.h; path = QiniuSDK/Http/QNSessionManager.h; sourceTree = ""; }; + 8688CFBCF706554DE3367922E5E9CD52 /* QNDnspodEnterprise.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDnspodEnterprise.m; path = HappyDNS/Http/QNDnspodEnterprise.m; sourceTree = ""; }; + 884B179B888EB933B0C3526DB4AB5D38 /* QNHosts.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNHosts.h; path = HappyDNS/Local/QNHosts.h; sourceTree = ""; }; + 89153FC28F023DCA84E0987948F84ABC /* QNLruCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNLruCache.m; path = HappyDNS/Common/QNLruCache.m; sourceTree = ""; }; + 89F271E31589466917DBD2B9365F320C /* ANSCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ANSCompatibility.h; path = iOS/Crashlytics.framework/Headers/ANSCompatibility.h; sourceTree = ""; }; + 8ADF73A50A85B63D4EF41CC7D1954CA0 /* Masonry-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Masonry-dummy.m"; sourceTree = ""; }; 8C55477752104B0F2EA3957FAC6D49F6 /* PLShortVideoKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PLShortVideoKit.framework; path = Pod/Library/Profession/PLShortVideoKit.framework; sourceTree = ""; }; - 8DC37D82CD6B6AF3E894BAF5BC372B94 /* QNResolverDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResolverDelegate.h; path = HappyDNS/Common/QNResolverDelegate.h; sourceTree = ""; }; + 8DA5FE137AE88B7BB25977E652F257B8 /* MASViewConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewConstraint.m; path = Masonry/MASViewConstraint.m; sourceTree = ""; }; 8E381B81BB109C1FF86D62185BD6047A /* Pods-PLShortVideoKitDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PLShortVideoKitDemo.debug.xcconfig"; sourceTree = ""; }; - 8EB16A7B39ACCBFF9FF8162047F6AFF5 /* QNAssessment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNAssessment.h; path = HappyDNS/Assessment/QNAssessment.h; sourceTree = ""; }; - 8EC1D629E35762544A3AF76329C596F4 /* QNResolvUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResolvUtil.h; path = HappyDNS/Local/QNResolvUtil.h; sourceTree = ""; }; - 8F5EB4DD9CBE509E638A8B9B66D57B12 /* QNSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNSessionManager.h; path = QiniuSDK/Http/QNSessionManager.h; sourceTree = ""; }; - 922F42E2170928F4F33420C710D858F2 /* QNALAssetFile.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNALAssetFile.m; path = QiniuSDK/Common/QNALAssetFile.m; sourceTree = ""; }; - 93FB08446352700BF861FD4132A75935 /* QNHex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNHex.m; path = HappyDNS/Util/QNHex.m; sourceTree = ""; }; - 949EA1C142526933535106A3F96B4B2F /* QNFile.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNFile.m; path = QiniuSDK/Common/QNFile.m; sourceTree = ""; }; - 97B351E8B9D7D0971B925CFBD9E65E86 /* QNDnsManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDnsManager.h; path = HappyDNS/Common/QNDnsManager.h; sourceTree = ""; }; - 98B4981EB0449B93511D38E7EECE606B /* QNRefresher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNRefresher.h; path = HappyDNS/QNRefresher.h; sourceTree = ""; }; - 99B37CEB6E7890CAFCCFC98213AEE7FA /* QNFileRecorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNFileRecorder.m; path = QiniuSDK/Recorder/QNFileRecorder.m; sourceTree = ""; }; - 99F2E9F6105215C3D71E6724F748B581 /* Qiniu-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Qiniu-prefix.pch"; sourceTree = ""; }; - 9A543C347DCED12E2411545716C370D1 /* HappyDNS.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HappyDNS.h; path = HappyDNS/HappyDNS.h; sourceTree = ""; }; - 9AD760BB91407C3C81F3ABE2B4EEDC58 /* QNEtag.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNEtag.h; path = QiniuSDK/Common/QNEtag.h; sourceTree = ""; }; - 9CF6C85085282224310FF7EB9A526528 /* Masonry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Masonry.h; path = Masonry/Masonry.h; sourceTree = ""; }; - 9D00981DA1EC762D3F9F6191AE06D7D1 /* QNPipeline.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNPipeline.m; path = QiniuSDK/BigData/QNPipeline.m; sourceTree = ""; }; + 8E80B420B1341F48DF1706C2B542A85A /* MASViewAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewAttribute.m; path = Masonry/MASViewAttribute.m; sourceTree = ""; }; + 92123AE036F69D7EA0BF32850DF13DF3 /* QNDes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDes.h; path = HappyDNS/Util/QNDes.h; sourceTree = ""; }; + 9714C19A9136067C9ED213AD51D77EAA /* QNALAssetFile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNALAssetFile.h; path = QiniuSDK/Common/QNALAssetFile.h; sourceTree = ""; }; + 99CC6F2E5292F44FB8A8C9DA15376430 /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+MASDebugAdditions.h"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = ""; }; + 9B3B537C850F8E51E91990B55E501E75 /* MASViewAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewAttribute.h; path = Masonry/MASViewAttribute.h; sourceTree = ""; }; + 9C1C6B863A30E60F32470D90AB671147 /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ViewController+MASAdditions.h"; path = "Masonry/ViewController+MASAdditions.h"; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9E111713FC71C86A36AE4187F575EC8E /* QNDnspodFree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDnspodFree.m; path = HappyDNS/Http/QNDnspodFree.m; sourceTree = ""; }; - A2D92E08FE845D7108F467E957D11D79 /* QNConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNConfiguration.h; path = QiniuSDK/Storage/QNConfiguration.h; sourceTree = ""; }; - A3434E951BBD43E7B663C40674F5776E /* FLAnimatedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImage.m; path = FLAnimatedImage/FLAnimatedImage.m; sourceTree = ""; }; - A3BA7EE9DDDAEA34B2717A3F24D7CCD3 /* Masonry.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.xcconfig; sourceTree = ""; }; - A4B9717971FE72688E98D42CB68079C2 /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ViewController+MASAdditions.h"; path = "Masonry/ViewController+MASAdditions.h"; sourceTree = ""; }; + 9D9C35EA96F4725A017A16E6389CD622 /* QNConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNConfiguration.m; path = QiniuSDK/Storage/QNConfiguration.m; sourceTree = ""; }; + 9E2A5576C37F28A939ED652B047745CC /* QNRefresher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNRefresher.m; path = HappyDNS/QNRefresher.m; sourceTree = ""; }; + A38C637A2D50C60A866B95BD8AC30484 /* QNResolver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNResolver.m; path = HappyDNS/Local/QNResolver.m; sourceTree = ""; }; + A3F07C1AD06F5448E124503B4F3B99F9 /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASAdditions.h"; path = "Masonry/NSArray+MASAdditions.h"; sourceTree = ""; }; A7B82792B39240C408DA7D6FEB677DA6 /* libQiniu.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libQiniu.a; path = libQiniu.a; sourceTree = BUILT_PRODUCTS_DIR; }; - ACAE3DDC2CB6C6DD872B74119CE23219 /* QNPHAssetFile.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNPHAssetFile.m; path = QiniuSDK/Common/QNPHAssetFile.m; sourceTree = ""; }; - ACC2CB3E25E9E66C7414C8CF8627413B /* QNFileDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNFileDelegate.h; path = QiniuSDK/Common/QNFileDelegate.h; sourceTree = ""; }; - AF75B54E10AF065CFD3E07D963E057B2 /* QNHosts.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNHosts.h; path = HappyDNS/Local/QNHosts.h; sourceTree = ""; }; - B03F915A88F21D8BB7C5C5F9ED3E4A51 /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASShorthandAdditions.h"; path = "Masonry/View+MASShorthandAdditions.h"; sourceTree = ""; }; - B3682D5BADEA95326A2820C635C81CC9 /* Qiniu.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Qiniu.xcconfig; sourceTree = ""; }; - B6B374127F515C31F50DEDABDD4822BF /* MASLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASLayoutConstraint.m; path = Masonry/MASLayoutConstraint.m; sourceTree = ""; }; - B6F620341FEA9BBEA045B308C60430E9 /* QNCrc32.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNCrc32.m; path = QiniuSDK/Common/QNCrc32.m; sourceTree = ""; }; - B76388BE36B9B4EA707F4CC6D3EFA90A /* QNDnsManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDnsManager.m; path = HappyDNS/Common/QNDnsManager.m; sourceTree = ""; }; - B813E8FC530CD9A48F62751D23CD3FD9 /* QNGetAddrInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNGetAddrInfo.m; path = HappyDNS/Util/QNGetAddrInfo.m; sourceTree = ""; }; + ABAE64BB345694B597A6989424E0261A /* QNTxtResolver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNTxtResolver.m; path = HappyDNS/Local/QNTxtResolver.m; sourceTree = ""; }; + AFF87D17EAB169B65F6286BEE9F25BB4 /* HappyDNS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HappyDNS-prefix.pch"; sourceTree = ""; }; + B0887D6DF568D65EA573778236BB5038 /* QNHex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNHex.h; path = HappyDNS/Util/QNHex.h; sourceTree = ""; }; + B1382A7E4DB5C4EADFCDD6B627AE1A50 /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASShorthandAdditions.h"; path = "Masonry/NSArray+MASShorthandAdditions.h"; sourceTree = ""; }; + B24A9C041B597234CBC2E57644964FA7 /* Masonry-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-prefix.pch"; sourceTree = ""; }; + B5CB0E6E4B4B8E44B69E49C591DA5864 /* View+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "View+MASAdditions.m"; path = "Masonry/View+MASAdditions.m"; sourceTree = ""; }; + B6DB9F92212910227CD5FCB98EA57495 /* Fabric.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Fabric.xcconfig; sourceTree = ""; }; + B7021275D95CB1B28E0D0504F60504EC /* QNResumeUpload.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResumeUpload.h; path = QiniuSDK/Storage/QNResumeUpload.h; sourceTree = ""; }; + B80E7FFDBC83E89EA351972762440AD7 /* FLAnimatedImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImage.h; path = FLAnimatedImage/FLAnimatedImage.h; sourceTree = ""; }; + BA2607093FE849A63BF1F69833036E77 /* QNResponseInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResponseInfo.h; path = QiniuSDK/Http/QNResponseInfo.h; sourceTree = ""; }; BB5A0B174267347AABAC8D1F9FD83A53 /* PLShortVideoKit.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = PLShortVideoKit.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - BD2397AD6246DE36FDBBFF91694CF6C3 /* MASCompositeConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASCompositeConstraint.h; path = Masonry/MASCompositeConstraint.h; sourceTree = ""; }; - BD2DA2AAFD22FDD51DDF6656C1C1CE70 /* QNPHAssetFile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNPHAssetFile.h; path = QiniuSDK/Common/QNPHAssetFile.h; sourceTree = ""; }; - BE76AB5EC5A2DFD9872CABD115BCB5A3 /* QNUserAgent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUserAgent.h; path = QiniuSDK/Http/QNUserAgent.h; sourceTree = ""; }; - C053720B15E527CAA832410A617C05E6 /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+MASDebugAdditions.h"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = ""; }; - C26E1B98E1F5D5504D7ED2E547E90F37 /* HappyDNS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HappyDNS.xcconfig; sourceTree = ""; }; - C2A19703B0A0B660AF9664C8D0AA7217 /* CLSStackFrame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSStackFrame.h; path = iOS/Crashlytics.framework/Headers/CLSStackFrame.h; sourceTree = ""; }; - C5974EED459E3547D39C6B2B9F8B448D /* MASConstraintMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraintMaker.m; path = Masonry/MASConstraintMaker.m; sourceTree = ""; }; - C95F5EB7F401CE8A957D59358992445C /* QNRefresher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNRefresher.m; path = HappyDNS/QNRefresher.m; sourceTree = ""; }; - CE5C8D45CB8C2286EE24D02A5EFD2144 /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASAdditions.h"; path = "Masonry/NSArray+MASAdditions.h"; sourceTree = ""; }; - D16E266C1B93449EE4050912CD64F934 /* QNHex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNHex.h; path = HappyDNS/Util/QNHex.h; sourceTree = ""; }; + BC6341B97CE57312C97E3DEB241AF14B /* QNDomain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDomain.m; path = HappyDNS/Common/QNDomain.m; sourceTree = ""; }; + BEC33CDC2ACA958C49EA91B4BACD8160 /* QNIpModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNIpModel.h; path = HappyDNS/Assessment/QNIpModel.h; sourceTree = ""; }; + BF676F6DD9D700C91555D8010C1FCF26 /* QNFile.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNFile.m; path = QiniuSDK/Common/QNFile.m; sourceTree = ""; }; + C0903D8E9B128FA2FEE12B50FC612EB9 /* CLSLogging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSLogging.h; path = iOS/Crashlytics.framework/Headers/CLSLogging.h; sourceTree = ""; }; + C1D8572AA962398E2A78E1D82782A55B /* MASUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASUtilities.h; path = Masonry/MASUtilities.h; sourceTree = ""; }; + C3D9E3862136736072BD591291B17CB0 /* QNNetworkInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNNetworkInfo.m; path = HappyDNS/Common/QNNetworkInfo.m; sourceTree = ""; }; + C47809242B96C3D91746FE9EEAA38FC4 /* QNDnspodFree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNDnspodFree.h; path = HappyDNS/Http/QNDnspodFree.h; sourceTree = ""; }; + C4A3A709049888F014C412B8FA59BF36 /* Answers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Answers.h; path = iOS/Crashlytics.framework/Headers/Answers.h; sourceTree = ""; }; + C590A06B9F577CCE570E4E3A80D6AB8F /* HappyDNS.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = HappyDNS.h; path = HappyDNS/HappyDNS.h; sourceTree = ""; }; + C709789B5055201867A874848095D363 /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+MASDebugAdditions.m"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; + C7D95CB6DFD898284CB7B3201C6C6490 /* QNRefresher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNRefresher.h; path = HappyDNS/QNRefresher.h; sourceTree = ""; }; + CC010D04B72B7DD0F22993B73864F957 /* FLAnimatedImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImage-prefix.pch"; sourceTree = ""; }; + CC17B440BE6B509275668EDD7418DC8C /* CLSStackFrame.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSStackFrame.h; path = iOS/Crashlytics.framework/Headers/CLSStackFrame.h; sourceTree = ""; }; + CD19F6C3DCAC760FDEDFFB6EDAF233FD /* QNUploadOption.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUploadOption.m; path = QiniuSDK/Storage/QNUploadOption.m; sourceTree = ""; }; + CDD5384CB8CDABBEE50EBE45A6F7EC17 /* QNLruCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNLruCache.h; path = HappyDNS/Common/QNLruCache.h; sourceTree = ""; }; + CE995301A30D9B57DDFE6B33E2BE157A /* QNEtag.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNEtag.h; path = QiniuSDK/Common/QNEtag.h; sourceTree = ""; }; + D3977D017B02841C80744BC4C2953854 /* FLAnimatedImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImage.m; path = FLAnimatedImage/FLAnimatedImage.m; sourceTree = ""; }; + D3CA70BE4154092A3B58B8703BAA1628 /* QNIP.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNIP.h; path = HappyDNS/Util/QNIP.h; sourceTree = ""; }; + D46D802FE3C5E604F8A2767EF9748175 /* QNPipeline.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNPipeline.m; path = QiniuSDK/BigData/QNPipeline.m; sourceTree = ""; }; + D4A90B126B9D4290D3B35B8A6AFBFDBA /* CLSAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CLSAttributes.h; path = iOS/Crashlytics.framework/Headers/CLSAttributes.h; sourceTree = ""; }; D4E158DE8091D82A1452AB48B8C4AE02 /* libMuseProcessor.a */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = archive.ar; name = libMuseProcessor.a; path = Pod/Library/Profession/libMuseProcessor.a; sourceTree = ""; }; - D777BCBC6F4C1473473D7300BACDBD01 /* FABAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FABAttributes.h; path = iOS/Fabric.framework/Headers/FABAttributes.h; sourceTree = ""; }; - D7E2B0A2A567EA2415149EF6CFB13565 /* ANSCompatibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = ANSCompatibility.h; path = iOS/Crashlytics.framework/Headers/ANSCompatibility.h; sourceTree = ""; }; - D8F4A5B8558E68780DCA5BBB6836B119 /* QNHosts.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNHosts.m; path = HappyDNS/Local/QNHosts.m; sourceTree = ""; }; - DA671D69DFEBF53E08341519314810DB /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+MASDebugAdditions.m"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; - DFAF98E5FD5F96A1CEF46CC308082A3A /* FLAnimatedImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImage-prefix.pch"; sourceTree = ""; }; - E15E757053D61F351AA57F4CDA6D9545 /* Fabric.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Fabric.h; path = iOS/Fabric.framework/Headers/Fabric.h; sourceTree = ""; }; - E3FF427C0704CEAE4CA021E3DB40C2A9 /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = iOS/Fabric.framework; sourceTree = ""; }; - E4C8A6405530F9547AD0B26AAFA5C7B7 /* QNLruCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNLruCache.m; path = HappyDNS/Common/QNLruCache.m; sourceTree = ""; }; - E7CD8EEE5B00BD8DBCD2EFD4C10C1AF0 /* QNUrlSafeBase64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNUrlSafeBase64.h; path = QiniuSDK/Common/QNUrlSafeBase64.h; sourceTree = ""; }; - E924F91E17089AD18AF06FEB6806C406 /* MASLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASLayoutConstraint.h; path = Masonry/MASLayoutConstraint.h; sourceTree = ""; }; - EA031A6536B25544D25B760AD1DB8EC2 /* Qiniu-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Qiniu-dummy.m"; sourceTree = ""; }; - EB428682DE7D7AC9F6A40CA4D20E87D4 /* QNPipeline.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNPipeline.h; path = QiniuSDK/BigData/QNPipeline.h; sourceTree = ""; }; - EB66B62C366B34234E1E677B2F8CBA69 /* QNResolver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNResolver.h; path = HappyDNS/Local/QNResolver.h; sourceTree = ""; }; + D668294813E0CF5DE57A8233F7B17B88 /* HappyDNS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HappyDNS-dummy.m"; sourceTree = ""; }; + D6F974108EFF133767377DF2F08F5F99 /* QNHijackingDetectWrapper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNHijackingDetectWrapper.h; path = HappyDNS/Local/QNHijackingDetectWrapper.h; sourceTree = ""; }; + D773FD178D07A41E68533B0937962979 /* MASConstraintMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraintMaker.m; path = Masonry/MASConstraintMaker.m; sourceTree = ""; }; + D8A96AFF0F2A525224C3A8B963BD4927 /* QNRecorderDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNRecorderDelegate.h; path = QiniuSDK/Recorder/QNRecorderDelegate.h; sourceTree = ""; }; + D9C0A5840EE29894065B9CAA3CD9BC47 /* Masonry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Masonry.h; path = Masonry/Masonry.h; sourceTree = ""; }; + DAC74062F17EEB0BAADD96596F4E5FCD /* QNPipeline.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNPipeline.h; path = QiniuSDK/BigData/QNPipeline.h; sourceTree = ""; }; + DD349AB189A1E5758E75E8B2897676B8 /* MASViewConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewConstraint.h; path = Masonry/MASViewConstraint.h; sourceTree = ""; }; + DDA13A5BBA068AC1E5BE0BFAD0B968EC /* QNPHAssetFile.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNPHAssetFile.m; path = QiniuSDK/Common/QNPHAssetFile.m; sourceTree = ""; }; + DEB4FC639569329AD524E5F676F8CD35 /* QNFileRecorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNFileRecorder.m; path = QiniuSDK/Recorder/QNFileRecorder.m; sourceTree = ""; }; + E0450788FF31FD3EC901447DD2454F82 /* QNAsyncRun.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNAsyncRun.h; path = QiniuSDK/Common/QNAsyncRun.h; sourceTree = ""; }; + E1E3A45DB377DACA3FE75A9A07CD6395 /* View+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASAdditions.h"; path = "Masonry/View+MASAdditions.h"; sourceTree = ""; }; + E5878ADB6016978EFD90EE0A9B6501B7 /* QNUrlSafeBase64.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUrlSafeBase64.m; path = QiniuSDK/Common/QNUrlSafeBase64.m; sourceTree = ""; }; + E71410E33B46B6767E77DF93AE24C767 /* FABAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FABAttributes.h; path = iOS/Fabric.framework/Headers/FABAttributes.h; sourceTree = ""; }; + E75009F865E16D0B1B0EA7638FD7F949 /* QNMD5.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNMD5.h; path = HappyDNS/Util/QNMD5.h; sourceTree = ""; }; + E98FC7E1E7FFC4B4532CEEEF0CCA07D7 /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASShorthandAdditions.h"; path = "Masonry/View+MASShorthandAdditions.h"; sourceTree = ""; }; + EAAE8CEE74A317A7A8597118DEC786B9 /* Crashlytics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Crashlytics.h; path = iOS/Crashlytics.framework/Headers/Crashlytics.h; sourceTree = ""; }; EBF39508BF42D8E066083DE328CE7EEB /* Pods-PLShortVideoKitDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PLShortVideoKitDemo-acknowledgements.plist"; sourceTree = ""; }; - EC7209EAC7ED814D4E7336D6F6C6BE46 /* QNAsyncRun.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNAsyncRun.h; path = QiniuSDK/Common/QNAsyncRun.h; sourceTree = ""; }; - EDB23A9B2722BA77023CBDAC8B0AF60B /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASShorthandAdditions.h"; path = "Masonry/NSArray+MASShorthandAdditions.h"; sourceTree = ""; }; - F05DEBBFC3FF6D474C85B2945C3AC55A /* QiniuSDK.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QiniuSDK.h; path = QiniuSDK/QiniuSDK.h; sourceTree = ""; }; - F0ACB793E106836346FF14E6C2887C3E /* QNVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNVersion.h; path = QiniuSDK/Common/QNVersion.h; sourceTree = ""; }; - F1303E37C7134A366D8ECD959C852EE5 /* QNSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNSessionManager.m; path = QiniuSDK/Http/QNSessionManager.m; sourceTree = ""; }; - F15A57E93F14D2B52AA9EAFAD9F7CF5F /* QNHijackingDetectWrapper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNHijackingDetectWrapper.m; path = HappyDNS/Local/QNHijackingDetectWrapper.m; sourceTree = ""; }; - F2AC09E3C47B5BE73C5DB9320DDA2024 /* MASViewConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewConstraint.h; path = Masonry/MASViewConstraint.h; sourceTree = ""; }; - F718BDD5A550507B5B4DFDA42E62EF2B /* View+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASAdditions.h"; path = "Masonry/View+MASAdditions.h"; sourceTree = ""; }; + EFB1E299DE364D97EBEAE5F41D3855C4 /* QNDnspodFree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNDnspodFree.m; path = HappyDNS/Http/QNDnspodFree.m; sourceTree = ""; }; + F1917DF56EC0B83127A3C25DB501319E /* Fabric.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Fabric.h; path = iOS/Fabric.framework/Headers/Fabric.h; sourceTree = ""; }; + F61DA42452759D7331D87AF76A01D2A7 /* QNGetAddrInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNGetAddrInfo.h; path = HappyDNS/Util/QNGetAddrInfo.h; sourceTree = ""; }; + F630B4755D91C52906292957E62819BD /* QNUploadManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNUploadManager.m; path = QiniuSDK/Storage/QNUploadManager.m; sourceTree = ""; }; + F64696430B072FD1B2B57FFB46C962DD /* Qiniu-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Qiniu-prefix.pch"; sourceTree = ""; }; + FA33CA8A3E73BA93F7D6B18627CE3CC3 /* QNFormUpload.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QNFormUpload.h; path = QiniuSDK/Storage/QNFormUpload.h; sourceTree = ""; }; FAA5F2D71B90788C908800A94534AA92 /* libFLAnimatedImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libFLAnimatedImage.a; path = libFLAnimatedImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; + FF2EDD3F480E1A0F2132A86BE3600604 /* QNFormUpload.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QNFormUpload.m; path = QiniuSDK/Storage/QNFormUpload.m; sourceTree = ""; }; + FFD6FAD25E0AA62411389988F3B597E9 /* MASLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASLayoutConstraint.h; path = Masonry/MASLayoutConstraint.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -412,7 +408,7 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 651C5E06824F79F2904DC345C9460CA9 /* Frameworks */ = { + 98F3DB4FBBEBAF1E86305BF301AE5794 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -443,25 +439,55 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0C40F7B2F3ADF30351B26F17E9440BD5 /* Support Files */ = { + 0712FA7C6760354BE1CBE9F30F32C2E1 /* HappyDNS */ = { isa = PBXGroup; children = ( - 1810CF6A6B37A2657A156481418D1E1C /* Crashlytics.xcconfig */, + C590A06B9F577CCE570E4E3A80D6AB8F /* HappyDNS.h */, + 42AE1D47AE1D8B3DAE9DA8ED142F88EA /* QNAssessment.h */, + 660E1D19373892344199324D5F6D3A23 /* QNAssessment.m */, + 92123AE036F69D7EA0BF32850DF13DF3 /* QNDes.h */, + 0CC75A9169678CAF21F1CF4C44433B6F /* QNDes.m */, + 39D3C7D319C1B9DD0D3A9828AAD0B159 /* QNDnsManager.h */, + 1958F44E7748938ED4BF775FF03EE59F /* QNDnsManager.m */, + 35437E1EA5219063C84B009ADC2115F6 /* QNDnspodEnterprise.h */, + 8688CFBCF706554DE3367922E5E9CD52 /* QNDnspodEnterprise.m */, + C47809242B96C3D91746FE9EEAA38FC4 /* QNDnspodFree.h */, + EFB1E299DE364D97EBEAE5F41D3855C4 /* QNDnspodFree.m */, + 7182743DE2E37EFE069F4052BD27B1AB /* QNDomain.h */, + BC6341B97CE57312C97E3DEB241AF14B /* QNDomain.m */, + F61DA42452759D7331D87AF76A01D2A7 /* QNGetAddrInfo.h */, + 4C7A211FD26AA0FEE95BD85DFE258031 /* QNGetAddrInfo.m */, + B0887D6DF568D65EA573778236BB5038 /* QNHex.h */, + 42FF2484EAF6FEF0325DB25C1CB5BAF4 /* QNHex.m */, + D6F974108EFF133767377DF2F08F5F99 /* QNHijackingDetectWrapper.h */, + 397063E3861E91347F31BCEA0AC695C5 /* QNHijackingDetectWrapper.m */, + 884B179B888EB933B0C3526DB4AB5D38 /* QNHosts.h */, + 1A936A47D933D7DD1316F8C76C6C6594 /* QNHosts.m */, + D3CA70BE4154092A3B58B8703BAA1628 /* QNIP.h */, + 139A4C4EB18B71AD8EB9F1D4F821AA9B /* QNIP.m */, + BEC33CDC2ACA958C49EA91B4BACD8160 /* QNIpModel.h */, + 8460438A26D0367F7D3CE49786DA1DD0 /* QNIpModel.m */, + CDD5384CB8CDABBEE50EBE45A6F7EC17 /* QNLruCache.h */, + 89153FC28F023DCA84E0987948F84ABC /* QNLruCache.m */, + E75009F865E16D0B1B0EA7638FD7F949 /* QNMD5.h */, + 20442E5BFB56F56A9072F4BD663A4EED /* QNMD5.m */, + 7037AE5CE36B38B4E6173CA5585CFCA6 /* QNNetworkInfo.h */, + C3D9E3862136736072BD591291B17CB0 /* QNNetworkInfo.m */, + 3532D6A894AD959CF03160FDF7D3E96F /* QNRecord.h */, + 43526337E35FB3BB252E45F6BEC9C569 /* QNRecord.m */, + C7D95CB6DFD898284CB7B3201C6C6490 /* QNRefresher.h */, + 9E2A5576C37F28A939ED652B047745CC /* QNRefresher.m */, + 21A523B1A0A3A9E8A8BB6BE60BD53CD9 /* QNResolver.h */, + A38C637A2D50C60A866B95BD8AC30484 /* QNResolver.m */, + 12EF988943C29980A1178B61413B5F3F /* QNResolverDelegate.h */, + 5313BA876CB1D4681FDDA13A26E10002 /* QNResolvUtil.h */, + 4FF76B3F3C58BAA41ED057BF477CBEE6 /* QNResolvUtil.m */, + 5B6F987C9FDE37575316A8DB0F0941F1 /* QNTxtResolver.h */, + ABAE64BB345694B597A6989424E0261A /* QNTxtResolver.m */, + 43D8D0C3AAFB0802D32689AFBA2AD42D /* Support Files */, ); - name = "Support Files"; - path = "../Target Support Files/Crashlytics"; - sourceTree = ""; - }; - 0E83979600B39EB6428857AE7180F88A /* Fabric */ = { - isa = PBXGroup; - children = ( - D777BCBC6F4C1473473D7300BACDBD01 /* FABAttributes.h */, - E15E757053D61F351AA57F4CDA6D9545 /* Fabric.h */, - B14A126155F143623B4F9475BB4B2E30 /* Frameworks */, - 759378731797EB1C256E483F9F1A463B /* Support Files */, - ); - name = Fabric; - path = Fabric; + name = HappyDNS; + path = HappyDNS; sourceTree = ""; }; 1ADA409B2F9483708DC9C23A64505DE3 /* libMuseProcessor */ = { @@ -504,189 +530,206 @@ name = Products; sourceTree = ""; }; - 340577E67DC93AF1FC10DAA41C6D8207 /* ex-libMuseProcessor */ = { + 2C7275CC525B91B4F2833E5C03CA3A90 /* FLAnimatedImage */ = { isa = PBXGroup; children = ( - CBFEE85EF4AE60F730DB4509D3AAA216 /* Frameworks */, + B80E7FFDBC83E89EA351972762440AD7 /* FLAnimatedImage.h */, + D3977D017B02841C80744BC4C2953854 /* FLAnimatedImage.m */, + 82100F8AE00F077DA3F75291F16B2C3D /* FLAnimatedImageView.h */, + 002EBBE97F186FC69A82F51430450554 /* FLAnimatedImageView.m */, + 96F3AD8047EBEF813C0188396C9F9422 /* Support Files */, ); - name = "ex-libMuseProcessor"; + name = FLAnimatedImage; + path = FLAnimatedImage; sourceTree = ""; }; - 48ACB284AE2E021B9A5E1AB6F3975735 /* Support Files */ = { + 340577E67DC93AF1FC10DAA41C6D8207 /* ex-libMuseProcessor */ = { isa = PBXGroup; children = ( - B3682D5BADEA95326A2820C635C81CC9 /* Qiniu.xcconfig */, - EA031A6536B25544D25B760AD1DB8EC2 /* Qiniu-dummy.m */, - 99F2E9F6105215C3D71E6724F748B581 /* Qiniu-prefix.pch */, + CBFEE85EF4AE60F730DB4509D3AAA216 /* Frameworks */, ); - name = "Support Files"; - path = "../Target Support Files/Qiniu"; + name = "ex-libMuseProcessor"; sourceTree = ""; }; - 4F843F40F26E177559A2FB712E129CA6 /* Qiniu */ = { + 4097A6C724A9E51AA488C8FB5AE83D0F /* Qiniu */ = { isa = PBXGroup; children = ( - F05DEBBFC3FF6D474C85B2945C3AC55A /* QiniuSDK.h */, - 3BFAFA72BAED0EB1F693AA077935AFA0 /* QN_GTM_Base64.h */, - 0F57C42060317FE87EB1BB3E9A4F4A70 /* QN_GTM_Base64.m */, - 7564ECB1BE548098EA82717AE1428436 /* QNALAssetFile.h */, - 922F42E2170928F4F33420C710D858F2 /* QNALAssetFile.m */, - EC7209EAC7ED814D4E7336D6F6C6BE46 /* QNAsyncRun.h */, - 718B3EC939241DAF2BD44F90089E875F /* QNAsyncRun.m */, - A2D92E08FE845D7108F467E957D11D79 /* QNConfiguration.h */, - 4CD61B5E61D2705FCBDF0E2FD06D3764 /* QNConfiguration.m */, - 04E2183A218091F317D6124CBF08A9DE /* QNCrc32.h */, - B6F620341FEA9BBEA045B308C60430E9 /* QNCrc32.m */, - 9AD760BB91407C3C81F3ABE2B4EEDC58 /* QNEtag.h */, - 1BA95F8C9277D267EADC95252D10EA61 /* QNEtag.m */, - 1CDAC700BDCE8CE4BB7541970F74C973 /* QNFile.h */, - 949EA1C142526933535106A3F96B4B2F /* QNFile.m */, - ACC2CB3E25E9E66C7414C8CF8627413B /* QNFileDelegate.h */, - 3CA65FF87C695B148ED228D17735C4C3 /* QNFileRecorder.h */, - 99B37CEB6E7890CAFCCFC98213AEE7FA /* QNFileRecorder.m */, - 4C7B46FA531047A26C57D2C16BEA4243 /* QNFormUpload.h */, - 81954B9704062F42BEEB2B32DAD6AB71 /* QNFormUpload.m */, - 0368138DC69AB564D1226C9D5A7BA2FF /* QNHttpDelegate.h */, - BD2DA2AAFD22FDD51DDF6656C1C1CE70 /* QNPHAssetFile.h */, - ACAE3DDC2CB6C6DD872B74119CE23219 /* QNPHAssetFile.m */, - 606E2668409C5AADC816CEA621704FFA /* QNPHAssetResource.h */, - 29BD5A5D14DEDA9430D27CD301654B53 /* QNPHAssetResource.m */, - EB428682DE7D7AC9F6A40CA4D20E87D4 /* QNPipeline.h */, - 9D00981DA1EC762D3F9F6191AE06D7D1 /* QNPipeline.m */, - 04B1F8B746EFC83F11E8890D5DBDC9B4 /* QNRecorderDelegate.h */, - 0954AB11364886615FED979B28080F6F /* QNResponseInfo.h */, - 6D007BB64566319240C8CE6A10FE3C60 /* QNResponseInfo.m */, - 57103069BF70B2AC884EC1CFAA620A8D /* QNResumeUpload.h */, - 707B3A46C129C0610EFFE5EA956C6287 /* QNResumeUpload.m */, - 8F5EB4DD9CBE509E638A8B9B66D57B12 /* QNSessionManager.h */, - F1303E37C7134A366D8ECD959C852EE5 /* QNSessionManager.m */, - 01D58F57B5EA09A711930FF5BCB81EA7 /* QNSystem.h */, - 8182DEA6FC5EF5AB87D0DA284574EE91 /* QNSystem.m */, - 5D6C5A3E6B085354F15BCA52EB126DD4 /* QNUploadManager.h */, - 36BB14AFEC9874B05E9B179B60997BF9 /* QNUploadManager.m */, - 3AD6D3A8C177CAB6555315C35D76C9FF /* QNUploadOption.h */, - 276FA87254F0EC58970AE6C3352D8800 /* QNUploadOption.m */, - 4B0E03E41B27017F8264E37B4A69CD17 /* QNUploadOption+Private.h */, - 0E902ECD6C53BB02D2C0DFE4ED1DFB80 /* QNUpToken.h */, - 0A1A3F685B43444F89639ADC31C75633 /* QNUpToken.m */, - E7CD8EEE5B00BD8DBCD2EFD4C10C1AF0 /* QNUrlSafeBase64.h */, - 130A3033AF8956D7ACE795B982A7BD9D /* QNUrlSafeBase64.m */, - BE76AB5EC5A2DFD9872CABD115BCB5A3 /* QNUserAgent.h */, - 5468E5645E1AFBE700837DB27EDB12BF /* QNUserAgent.m */, - F0ACB793E106836346FF14E6C2887C3E /* QNVersion.h */, - 48ACB284AE2E021B9A5E1AB6F3975735 /* Support Files */, + 14BFCADF436E54CC59821AA9B9B624C1 /* QiniuSDK.h */, + 1EF775BB281F4084526B8E1C45A6F621 /* QN_GTM_Base64.h */, + 4CF730D761429A7F8849FBB2CA49DCCF /* QN_GTM_Base64.m */, + 9714C19A9136067C9ED213AD51D77EAA /* QNALAssetFile.h */, + 09312936769EA6035C18A2C96EDE30D9 /* QNALAssetFile.m */, + E0450788FF31FD3EC901447DD2454F82 /* QNAsyncRun.h */, + 2B2C0A12476E208F6B93D19352F051E4 /* QNAsyncRun.m */, + 47BE44ABC1A3B9BFFEF227B7E7E3D9D4 /* QNConfiguration.h */, + 9D9C35EA96F4725A017A16E6389CD622 /* QNConfiguration.m */, + 0077DFA11FDC2DF135DA7EB0F02632FA /* QNCrc32.h */, + 26E43CE4FB85E79C3D43AB5E40B402A0 /* QNCrc32.m */, + CE995301A30D9B57DDFE6B33E2BE157A /* QNEtag.h */, + 1005AB0C0724543C6C6001A71C0010FA /* QNEtag.m */, + 2C0A6B662D2221D19320D1A91F0CBEAF /* QNFile.h */, + BF676F6DD9D700C91555D8010C1FCF26 /* QNFile.m */, + 447D861479B080EC63347D1F4EF383F2 /* QNFileDelegate.h */, + 09F7A6BC25BBB6D1DF658105E77B14A1 /* QNFileRecorder.h */, + DEB4FC639569329AD524E5F676F8CD35 /* QNFileRecorder.m */, + FA33CA8A3E73BA93F7D6B18627CE3CC3 /* QNFormUpload.h */, + FF2EDD3F480E1A0F2132A86BE3600604 /* QNFormUpload.m */, + 7C75D8BA3309A5F386A48D3F6E14C672 /* QNHttpDelegate.h */, + 01BE9317737637B79043B5F949ADFF92 /* QNPHAssetFile.h */, + DDA13A5BBA068AC1E5BE0BFAD0B968EC /* QNPHAssetFile.m */, + 3B3F301781932578FC05A1D0864BC2EC /* QNPHAssetResource.h */, + 1714829E65E727602005B5E20B3FB1BC /* QNPHAssetResource.m */, + DAC74062F17EEB0BAADD96596F4E5FCD /* QNPipeline.h */, + D46D802FE3C5E604F8A2767EF9748175 /* QNPipeline.m */, + D8A96AFF0F2A525224C3A8B963BD4927 /* QNRecorderDelegate.h */, + BA2607093FE849A63BF1F69833036E77 /* QNResponseInfo.h */, + 5654DBA48FB304557D4DACC995FBADBB /* QNResponseInfo.m */, + B7021275D95CB1B28E0D0504F60504EC /* QNResumeUpload.h */, + 17922463B96260F824CFF5E91203923D /* QNResumeUpload.m */, + 860A8F6891F22794F5BEC558FBDBB0D3 /* QNSessionManager.h */, + 3A6A9F8E7FE0F7C0123643FC1BDD6A29 /* QNSessionManager.m */, + 6748B8D214DA3086517660AFA4F9E663 /* QNSystem.h */, + 0385C2702D631D59F50927E94EBED0F2 /* QNSystem.m */, + 7BD23AD04B39F7887A670CEFE81BE163 /* QNUploadManager.h */, + F630B4755D91C52906292957E62819BD /* QNUploadManager.m */, + 6E1EE499A55DA3EE1A5685121A01E3B9 /* QNUploadOption.h */, + CD19F6C3DCAC760FDEDFFB6EDAF233FD /* QNUploadOption.m */, + 82D92D94FC52D6A000A4D1066F6DF508 /* QNUploadOption+Private.h */, + 6EE394E0FF4ACA1E57C586603AECF003 /* QNUpToken.h */, + 74D5FC77A796B0482942D08C217EE235 /* QNUpToken.m */, + 7E16BBA92A5B6529D014ADDDE17F014D /* QNUrlSafeBase64.h */, + E5878ADB6016978EFD90EE0A9B6501B7 /* QNUrlSafeBase64.m */, + 608CD01CAC4391C72BA2E675FC29BF26 /* QNUserAgent.h */, + 17827DBF5B339FF1D4A49AF4EB5DB7A6 /* QNUserAgent.m */, + 19D6A5B395CF4E5AB8B136F32EB9BD06 /* QNVersion.h */, + B21F3E63464D3C1AEB8D827924AA1B52 /* Support Files */, ); name = Qiniu; path = Qiniu; sourceTree = ""; }; - 67E48B712D606C88A9DB673B84C9144F /* Pod */ = { + 43D8D0C3AAFB0802D32689AFBA2AD42D /* Support Files */ = { isa = PBXGroup; children = ( - BB5A0B174267347AABAC8D1F9FD83A53 /* PLShortVideoKit.podspec */, + 69CC7F0099A810CC74C11DD20D18CD34 /* HappyDNS.xcconfig */, + D668294813E0CF5DE57A8233F7B17B88 /* HappyDNS-dummy.m */, + AFF87D17EAB169B65F6286BEE9F25BB4 /* HappyDNS-prefix.pch */, ); - name = Pod; + name = "Support Files"; + path = "../Target Support Files/HappyDNS"; sourceTree = ""; }; - 759378731797EB1C256E483F9F1A463B /* Support Files */ = { + 4B656889DF7A57D533C8FFB100C8068F /* Masonry */ = { isa = PBXGroup; children = ( - 58DCFDD6DDA971FB8589C74F927A2324 /* Fabric.xcconfig */, + 18ED4995A3FDFDE88CC16C19E95552CA /* MASCompositeConstraint.h */, + 48F88630B329225653DB8B6B5BBD7B8D /* MASCompositeConstraint.m */, + 2B9DB2F18A0B57E0B6A5BFA2BB8AD674 /* MASConstraint.h */, + 40152D4AA776DE3EA4E94CA8C5A45779 /* MASConstraint.m */, + 1230171C576B2F951A1CAD3F27EDCF90 /* MASConstraint+Private.h */, + 684CCF34C91F59D771326975A7A1F2FB /* MASConstraintMaker.h */, + D773FD178D07A41E68533B0937962979 /* MASConstraintMaker.m */, + FFD6FAD25E0AA62411389988F3B597E9 /* MASLayoutConstraint.h */, + 75131083A9B1D59EB273333512ECE0C6 /* MASLayoutConstraint.m */, + D9C0A5840EE29894065B9CAA3CD9BC47 /* Masonry.h */, + C1D8572AA962398E2A78E1D82782A55B /* MASUtilities.h */, + 9B3B537C850F8E51E91990B55E501E75 /* MASViewAttribute.h */, + 8E80B420B1341F48DF1706C2B542A85A /* MASViewAttribute.m */, + DD349AB189A1E5758E75E8B2897676B8 /* MASViewConstraint.h */, + 8DA5FE137AE88B7BB25977E652F257B8 /* MASViewConstraint.m */, + A3F07C1AD06F5448E124503B4F3B99F9 /* NSArray+MASAdditions.h */, + 032C153C332B2B8D25ADA36F195EC9CF /* NSArray+MASAdditions.m */, + B1382A7E4DB5C4EADFCDD6B627AE1A50 /* NSArray+MASShorthandAdditions.h */, + 99CC6F2E5292F44FB8A8C9DA15376430 /* NSLayoutConstraint+MASDebugAdditions.h */, + C709789B5055201867A874848095D363 /* NSLayoutConstraint+MASDebugAdditions.m */, + E1E3A45DB377DACA3FE75A9A07CD6395 /* View+MASAdditions.h */, + B5CB0E6E4B4B8E44B69E49C591DA5864 /* View+MASAdditions.m */, + E98FC7E1E7FFC4B4532CEEEF0CCA07D7 /* View+MASShorthandAdditions.h */, + 9C1C6B863A30E60F32470D90AB671147 /* ViewController+MASAdditions.h */, + 0F869468CDE07F5E40AC6E29DDADE73A /* ViewController+MASAdditions.m */, + D2C016C04C2D0204240CE6625666D9EF /* Support Files */, ); - name = "Support Files"; - path = "../Target Support Files/Fabric"; + name = Masonry; + path = Masonry; sourceTree = ""; }; - 7664E73D010B1DD4CB868B8FE35B3755 /* Pods */ = { + 4D51BA5672D893F46A99253FF87ED0D2 /* Frameworks */ = { isa = PBXGroup; children = ( - 9AEEAF442F3A81C8F4371B8F26C9A59A /* Crashlytics */, - 0E83979600B39EB6428857AE7180F88A /* Fabric */, - 81015564029BF92D96201821F8F33C04 /* FLAnimatedImage */, - DCAE7FA489741454BACCBD709E8FEB14 /* HappyDNS */, - F892749027189A83B3DFB59BFE9DFD06 /* Masonry */, - 4F843F40F26E177559A2FB712E129CA6 /* Qiniu */, + 2CCADDB26BCC08DCF21B7B007CF78A9C /* Crashlytics.framework */, ); - name = Pods; + name = Frameworks; sourceTree = ""; }; - 7766DA44430A9FA32D57A6AA4494FDB8 /* Support Files */ = { + 512C74390EC6E646BB73BEB6209BEA3F /* Frameworks */ = { isa = PBXGroup; children = ( - C26E1B98E1F5D5504D7ED2E547E90F37 /* HappyDNS.xcconfig */, - 0EC7D773547E63E83CD022000A211F04 /* HappyDNS-dummy.m */, - 3A075D22DB6C1C0A90F79A4059168670 /* HappyDNS-prefix.pch */, + 147FF0BFE084607E0DEDC8294D7176FF /* Fabric.framework */, ); - name = "Support Files"; - path = "../Target Support Files/HappyDNS"; + name = Frameworks; sourceTree = ""; }; - 7C1C2C23B537314F78A54A0D17871F9A /* Targets Support Files */ = { + 67E48B712D606C88A9DB673B84C9144F /* Pod */ = { isa = PBXGroup; children = ( - CD4C6B79E82E8E43B2ECFD7C30361CCB /* Pods-PLShortVideoKitDemo */, + BB5A0B174267347AABAC8D1F9FD83A53 /* PLShortVideoKit.podspec */, ); - name = "Targets Support Files"; + name = Pod; sourceTree = ""; }; - 81015564029BF92D96201821F8F33C04 /* FLAnimatedImage */ = { + 7456AC53F29523B3336ABD8D219832C6 /* Pods */ = { isa = PBXGroup; children = ( - 621109AAF2C0D7A0D57A1CC1959C5B48 /* FLAnimatedImage.h */, - A3434E951BBD43E7B663C40674F5776E /* FLAnimatedImage.m */, - 031946BAC6C82F111FA4F25F48F36269 /* FLAnimatedImageView.h */, - 5DE4D0D6A9512AE92730F168E054B09B /* FLAnimatedImageView.m */, - 84ADE013712F392467D03C4494759993 /* Support Files */, + CC8B5D1B4CBCEFC26B3F60AABBDF06E8 /* Crashlytics */, + BAFF1E3B3DA030EFA0A0708E525E5ED7 /* Fabric */, + 2C7275CC525B91B4F2833E5C03CA3A90 /* FLAnimatedImage */, + 0712FA7C6760354BE1CBE9F30F32C2E1 /* HappyDNS */, + 4B656889DF7A57D533C8FFB100C8068F /* Masonry */, + 4097A6C724A9E51AA488C8FB5AE83D0F /* Qiniu */, ); - name = FLAnimatedImage; - path = FLAnimatedImage; + name = Pods; sourceTree = ""; }; - 84ADE013712F392467D03C4494759993 /* Support Files */ = { + 7C1C2C23B537314F78A54A0D17871F9A /* Targets Support Files */ = { isa = PBXGroup; children = ( - 2CB647AF6ED8CE53ADCB2349EADB6F3C /* FLAnimatedImage.xcconfig */, - 4042BE7BC2CAB768E4E7F7999137A814 /* FLAnimatedImage-dummy.m */, - DFAF98E5FD5F96A1CEF46CC308082A3A /* FLAnimatedImage-prefix.pch */, + CD4C6B79E82E8E43B2ECFD7C30361CCB /* Pods-PLShortVideoKitDemo */, ); - name = "Support Files"; - path = "../Target Support Files/FLAnimatedImage"; + name = "Targets Support Files"; sourceTree = ""; }; - 9AEEAF442F3A81C8F4371B8F26C9A59A /* Crashlytics */ = { + 96F3AD8047EBEF813C0188396C9F9422 /* Support Files */ = { isa = PBXGroup; children = ( - D7E2B0A2A567EA2415149EF6CFB13565 /* ANSCompatibility.h */, - 4B3138CDB4F01659791AC010864C730A /* Answers.h */, - 60F2581C079F942A9F1ECC9517592FC6 /* CLSAttributes.h */, - 0811287B2386E5BF99443E6B3DF4651E /* CLSLogging.h */, - 4CBDD03638D0B4E09983F0731BCC6244 /* CLSReport.h */, - C2A19703B0A0B660AF9664C8D0AA7217 /* CLSStackFrame.h */, - 85E05EE6F0191CE3CB4B2FE46B389691 /* Crashlytics.h */, - E01992BCCC2F5AE04DFFA4D12EF3A248 /* Frameworks */, - 0C40F7B2F3ADF30351B26F17E9440BD5 /* Support Files */, + 18FAC25C1AD69EA222A9050A962AC5C1 /* FLAnimatedImage.xcconfig */, + 85D47D6C7E51F98FFC1D2EAFD8209196 /* FLAnimatedImage-dummy.m */, + CC010D04B72B7DD0F22993B73864F957 /* FLAnimatedImage-prefix.pch */, ); - name = Crashlytics; - path = Crashlytics; + name = "Support Files"; + path = "../Target Support Files/FLAnimatedImage"; sourceTree = ""; }; - B06CC379EA865371FD5A3D47842C5D2A /* Support Files */ = { + B21F3E63464D3C1AEB8D827924AA1B52 /* Support Files */ = { isa = PBXGroup; children = ( - A3BA7EE9DDDAEA34B2717A3F24D7CCD3 /* Masonry.xcconfig */, - 6112B38D2494947997368BFF51A4D453 /* Masonry-dummy.m */, - 14F7F4C6B9E632A87F2D43189F6ED3F4 /* Masonry-prefix.pch */, + 6296D8C7CA0FF181715EF1C7782B5E4C /* Qiniu.xcconfig */, + 251F8EDBD3E9AF3E670C1425D0C45296 /* Qiniu-dummy.m */, + F64696430B072FD1B2B57FFB46C962DD /* Qiniu-prefix.pch */, ); name = "Support Files"; - path = "../Target Support Files/Masonry"; + path = "../Target Support Files/Qiniu"; sourceTree = ""; }; - B14A126155F143623B4F9475BB4B2E30 /* Frameworks */ = { + BAFF1E3B3DA030EFA0A0708E525E5ED7 /* Fabric */ = { isa = PBXGroup; children = ( - E3FF427C0704CEAE4CA021E3DB40C2A9 /* Fabric.framework */, + E71410E33B46B6767E77DF93AE24C767 /* FABAttributes.h */, + F1917DF56EC0B83127A3C25DB501319E /* Fabric.h */, + 512C74390EC6E646BB73BEB6209BEA3F /* Frameworks */, + FBF1CFEDA7CBA57A242AC4632D2BD1A8 /* Support Files */, ); - name = Frameworks; + name = Fabric; + path = Fabric; sourceTree = ""; }; CBFEE85EF4AE60F730DB4509D3AAA216 /* Frameworks */ = { @@ -697,6 +740,23 @@ name = Frameworks; sourceTree = ""; }; + CC8B5D1B4CBCEFC26B3F60AABBDF06E8 /* Crashlytics */ = { + isa = PBXGroup; + children = ( + 89F271E31589466917DBD2B9365F320C /* ANSCompatibility.h */, + C4A3A709049888F014C412B8FA59BF36 /* Answers.h */, + D4A90B126B9D4290D3B35B8A6AFBFDBA /* CLSAttributes.h */, + C0903D8E9B128FA2FEE12B50FC612EB9 /* CLSLogging.h */, + 2C43C89D041898ADFA61467FF4CFCC9E /* CLSReport.h */, + CC17B440BE6B509275668EDD7418DC8C /* CLSStackFrame.h */, + EAAE8CEE74A317A7A8597118DEC786B9 /* Crashlytics.h */, + 4D51BA5672D893F46A99253FF87ED0D2 /* Frameworks */, + F54B979BF5C4484D81BE87BC46FFB344 /* Support Files */, + ); + name = Crashlytics; + path = Crashlytics; + sourceTree = ""; + }; CD4C6B79E82E8E43B2ECFD7C30361CCB /* Pods-PLShortVideoKitDemo */ = { isa = PBXGroup; children = ( @@ -716,78 +776,37 @@ 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, FED93316065A8DA8CC760F8981471FDB /* Development Pods */, D89477F20FB1DE18A04690586D7808C4 /* Frameworks */, - 7664E73D010B1DD4CB868B8FE35B3755 /* Pods */, + 7456AC53F29523B3336ABD8D219832C6 /* Pods */, 256F825F2BEFA291D6B8896A223EBB78 /* Products */, 7C1C2C23B537314F78A54A0D17871F9A /* Targets Support Files */, ); sourceTree = ""; }; - D89477F20FB1DE18A04690586D7808C4 /* Frameworks */ = { + D2C016C04C2D0204240CE6625666D9EF /* Support Files */ = { isa = PBXGroup; children = ( + 53C89494F59D7562B6CCCBD355AC9361 /* Masonry.xcconfig */, + 8ADF73A50A85B63D4EF41CC7D1954CA0 /* Masonry-dummy.m */, + B24A9C041B597234CBC2E57644964FA7 /* Masonry-prefix.pch */, ); - name = Frameworks; + name = "Support Files"; + path = "../Target Support Files/Masonry"; sourceTree = ""; }; - DCAE7FA489741454BACCBD709E8FEB14 /* HappyDNS */ = { + D89477F20FB1DE18A04690586D7808C4 /* Frameworks */ = { isa = PBXGroup; children = ( - 9A543C347DCED12E2411545716C370D1 /* HappyDNS.h */, - 8EB16A7B39ACCBFF9FF8162047F6AFF5 /* QNAssessment.h */, - 0948776AB9F038B34F6E8D171A9DC9E1 /* QNAssessment.m */, - 1D62DC3985963E3DADB4781DF6F8F0E7 /* QNDes.h */, - 7C789F6B08F93A8A25DB4C7D2EA7D57C /* QNDes.m */, - 97B351E8B9D7D0971B925CFBD9E65E86 /* QNDnsManager.h */, - B76388BE36B9B4EA707F4CC6D3EFA90A /* QNDnsManager.m */, - 7125FE0ADDC9EBAA36B3D5504D03903C /* QNDnspodEnterprise.h */, - 63AC1F0E19EE8E0C6E6793860A00412A /* QNDnspodEnterprise.m */, - 589247593CC6D20DA3C3D985B84D1A77 /* QNDnspodFree.h */, - 9E111713FC71C86A36AE4187F575EC8E /* QNDnspodFree.m */, - 0590017E2114863B3416C5F2101428BE /* QNDomain.h */, - 4030E9756D6612DAE1B2111D9591AB8E /* QNDomain.m */, - 6372348C9CBCC484FC15B206BF839C42 /* QNGetAddrInfo.h */, - B813E8FC530CD9A48F62751D23CD3FD9 /* QNGetAddrInfo.m */, - D16E266C1B93449EE4050912CD64F934 /* QNHex.h */, - 93FB08446352700BF861FD4132A75935 /* QNHex.m */, - 62798C8D70EEBBBD2FDFB65A89442DFF /* QNHijackingDetectWrapper.h */, - F15A57E93F14D2B52AA9EAFAD9F7CF5F /* QNHijackingDetectWrapper.m */, - AF75B54E10AF065CFD3E07D963E057B2 /* QNHosts.h */, - D8F4A5B8558E68780DCA5BBB6836B119 /* QNHosts.m */, - 4102119BB577809706CD9807D512A81A /* QNIP.h */, - 4CEA2F31CFECC8753DF165972567DA95 /* QNIP.m */, - 6EC9788E7CE0F5B9DD37A36DBA564BFB /* QNIpModel.h */, - 80293F9176725CD1B877779AF2A0D765 /* QNIpModel.m */, - 19C915FDA8D4EA64E92B9E4E70E9D701 /* QNLruCache.h */, - E4C8A6405530F9547AD0B26AAFA5C7B7 /* QNLruCache.m */, - 3BF668BE143F24CFB5DCF7E2EF65B694 /* QNMD5.h */, - 1C7C330AB16CA1A1D339D7A9FF93DB0B /* QNMD5.m */, - 51CB2C9D11B0382BC645CF9DEABAD01A /* QNNetworkInfo.h */, - 1DC5780C10EF06CE1B7C79B7135FB4AB /* QNNetworkInfo.m */, - 066E515A3F5D7DEC8797D64762224A09 /* QNNiuDns.h */, - 30D742796965426E10F87542550C06BF /* QNNiuDns.m */, - 4743FF73E5E40D32B83469BB782EF4F7 /* QNRecord.h */, - 2992C522F75BC6F2E7782C166611D474 /* QNRecord.m */, - 98B4981EB0449B93511D38E7EECE606B /* QNRefresher.h */, - C95F5EB7F401CE8A957D59358992445C /* QNRefresher.m */, - EB66B62C366B34234E1E677B2F8CBA69 /* QNResolver.h */, - 7F6A0685DEECD46087AADA5C475A3A35 /* QNResolver.m */, - 8DC37D82CD6B6AF3E894BAF5BC372B94 /* QNResolverDelegate.h */, - 8EC1D629E35762544A3AF76329C596F4 /* QNResolvUtil.h */, - 616A9B8A95D05602A7C3AB65BFA8FA2C /* QNResolvUtil.m */, - 1B1FD9B2AE2BAEB934281DC75A5EEF23 /* QNTxtResolver.h */, - 18CD98380FFBFC73BF79790911B1335E /* QNTxtResolver.m */, - 7766DA44430A9FA32D57A6AA4494FDB8 /* Support Files */, ); - name = HappyDNS; - path = HappyDNS; + name = Frameworks; sourceTree = ""; }; - E01992BCCC2F5AE04DFFA4D12EF3A248 /* Frameworks */ = { + F54B979BF5C4484D81BE87BC46FFB344 /* Support Files */ = { isa = PBXGroup; children = ( - 09ED1A59AFE3363CCB2121888660C306 /* Crashlytics.framework */, + 70F6C61E75E25D3DDB3A8D28DCA8C130 /* Crashlytics.xcconfig */, ); - name = Frameworks; + name = "Support Files"; + path = "../Target Support Files/Crashlytics"; sourceTree = ""; }; F717B812337269BEFD0C63489D51A468 /* Support Files */ = { @@ -799,38 +818,13 @@ path = "Example/Pods/Target Support Files/PLShortVideoKit"; sourceTree = ""; }; - F892749027189A83B3DFB59BFE9DFD06 /* Masonry */ = { + FBF1CFEDA7CBA57A242AC4632D2BD1A8 /* Support Files */ = { isa = PBXGroup; children = ( - BD2397AD6246DE36FDBBFF91694CF6C3 /* MASCompositeConstraint.h */, - 3C1B09B668B6635F9E63DDF38D4CAED1 /* MASCompositeConstraint.m */, - 5BBB37654FA6FFA35DF6F467EA9DAE41 /* MASConstraint.h */, - 33C531193DCEC89A11A171742430000C /* MASConstraint.m */, - 55CDED97E866A21F98798C86CDCA8E1F /* MASConstraint+Private.h */, - 1761496D72C307EFDD9EDD62B4B592F7 /* MASConstraintMaker.h */, - C5974EED459E3547D39C6B2B9F8B448D /* MASConstraintMaker.m */, - E924F91E17089AD18AF06FEB6806C406 /* MASLayoutConstraint.h */, - B6B374127F515C31F50DEDABDD4822BF /* MASLayoutConstraint.m */, - 9CF6C85085282224310FF7EB9A526528 /* Masonry.h */, - 50A3E4BCDDB3A71E486D4B982E1FC5DA /* MASUtilities.h */, - 3FBD8ECB98692FA39A12D024B762A297 /* MASViewAttribute.h */, - 8BCAD8EF0CF9ABBBE260F99D3DFCCF5B /* MASViewAttribute.m */, - F2AC09E3C47B5BE73C5DB9320DDA2024 /* MASViewConstraint.h */, - 14737354608E32510CFD9F907F5ED324 /* MASViewConstraint.m */, - CE5C8D45CB8C2286EE24D02A5EFD2144 /* NSArray+MASAdditions.h */, - 80FEBF8EDB6F5A42D38F9BF5D293340C /* NSArray+MASAdditions.m */, - EDB23A9B2722BA77023CBDAC8B0AF60B /* NSArray+MASShorthandAdditions.h */, - C053720B15E527CAA832410A617C05E6 /* NSLayoutConstraint+MASDebugAdditions.h */, - DA671D69DFEBF53E08341519314810DB /* NSLayoutConstraint+MASDebugAdditions.m */, - F718BDD5A550507B5B4DFDA42E62EF2B /* View+MASAdditions.h */, - 781066C5AC71BC86276C51735727C18C /* View+MASAdditions.m */, - B03F915A88F21D8BB7C5C5F9ED3E4A51 /* View+MASShorthandAdditions.h */, - A4B9717971FE72688E98D42CB68079C2 /* ViewController+MASAdditions.h */, - 5763011EAF2D09C0F745FC936AFD8802 /* ViewController+MASAdditions.m */, - B06CC379EA865371FD5A3D47842C5D2A /* Support Files */, + B6DB9F92212910227CD5FCB98EA57495 /* Fabric.xcconfig */, ); - name = Masonry; - path = Masonry; + name = "Support Files"; + path = "../Target Support Files/Fabric"; sourceTree = ""; }; FED93316065A8DA8CC760F8981471FDB /* Development Pods */ = { @@ -851,36 +845,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1E4754E0A2C420C576DF211058E25D19 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 049C72D59655A408144C7302F38E4A3B /* HappyDNS.h in Headers */, - 72CD374FD089082CDB26721D6733D8DE /* QNAssessment.h in Headers */, - C200AEB67D3540FD87EC3249EC929525 /* QNDes.h in Headers */, - 85A5B6C5DB2824107D8E1E2DF6FCC545 /* QNDnsManager.h in Headers */, - 630D9929FF3E2CA7E4F6DCF72E42877F /* QNDnspodEnterprise.h in Headers */, - E03284656F15525BC13EB8C5BA2799F2 /* QNDnspodFree.h in Headers */, - 1B3F936992CCBB41CB5E96491FB05E76 /* QNDomain.h in Headers */, - 8C4D69016542BAF09D544CB7E6C43DF2 /* QNGetAddrInfo.h in Headers */, - 7FB5CF5472606834CCD665024166C392 /* QNHex.h in Headers */, - 2F0A7DB8C1FA0FB9349F791E683B2566 /* QNHijackingDetectWrapper.h in Headers */, - 46704DAA07F3E4BB41422B3A9109A893 /* QNHosts.h in Headers */, - 20D3664A1DC8397D4C263663883709A1 /* QNIP.h in Headers */, - B9EDA07E65A834E9EE13C86B5E97D7D3 /* QNIpModel.h in Headers */, - 48128E051E42D841A2AA90D1182191E0 /* QNLruCache.h in Headers */, - A759F099AAFFAB954F3C7CA478124154 /* QNMD5.h in Headers */, - 232321420D4E786E3A874FF061FE99BC /* QNNetworkInfo.h in Headers */, - 11F9B8FEFDA4F82DA2C335AA3F512419 /* QNNiuDns.h in Headers */, - 83656390DFBD5E40863BD628D5F9A46A /* QNRecord.h in Headers */, - A0724C13490E433BADA7C09D1D0E691B /* QNRefresher.h in Headers */, - C09407360B2CA7E9FC6B9ED1DDD30B6C /* QNResolver.h in Headers */, - 56BBC602BF0C0F844D3235AA27FBCCD7 /* QNResolverDelegate.h in Headers */, - BDDFDB62428E1B9911B0C27E936BBEB0 /* QNResolvUtil.h in Headers */, - 662B660ECD532CFF2BAEFB3B213EABA3 /* QNTxtResolver.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 2697A8D6B2989B073B236F7B4BF67F30 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -903,6 +867,35 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 336709FFABC1848073960F1D74D3C283 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A30C57E0F6DB15E96E5A5BAE6220660 /* HappyDNS.h in Headers */, + 20262DEB7FF7AABF747162A0129A899F /* QNAssessment.h in Headers */, + 6E67FD4BBC929A2D587FA49A7191275B /* QNDes.h in Headers */, + 9D1886BF92B53141C422FD60D2447387 /* QNDnsManager.h in Headers */, + 875B9C8AEBF475A93634436A151CAE3D /* QNDnspodEnterprise.h in Headers */, + 87C322375DF7F1BF0BE9CBF42E52AB2F /* QNDnspodFree.h in Headers */, + B3E0E5C146898F993C1172F263EAFE20 /* QNDomain.h in Headers */, + DA6C7CE62D0E4E67E1644EC6C63A9962 /* QNGetAddrInfo.h in Headers */, + 8B99A2C79839BE0B9E85AFE9EDCE2938 /* QNHex.h in Headers */, + 7D8CCC6C645A5185A68C2936754F6E3B /* QNHijackingDetectWrapper.h in Headers */, + D1FF72DCA476246D61CA1F52FC30EC7A /* QNHosts.h in Headers */, + EA8FBE880DD634AAE2461880E6C837E2 /* QNIP.h in Headers */, + 0B05BB82BBD2A997A620C50235A71992 /* QNIpModel.h in Headers */, + A5F40CB8E2A9A377EA61C8165C614276 /* QNLruCache.h in Headers */, + 7D0FE4BC0CF22BC5FB0E0D56CCE0EB64 /* QNMD5.h in Headers */, + 80107EC7249A2C4727A661B6398A41D2 /* QNNetworkInfo.h in Headers */, + AD1A880F8D70C400A8128D173D338FD1 /* QNRecord.h in Headers */, + F5EA11D2C0C897302E4C916D913C4643 /* QNRefresher.h in Headers */, + 259A1A7649AA53CC59A83DE503863152 /* QNResolver.h in Headers */, + 0C349F150B29AC0C7ADE49387BC0399F /* QNResolverDelegate.h in Headers */, + 4763919978EBF8FBEEBA930600B12FAA /* QNResolvUtil.h in Headers */, + 608E4C47DFAC69D71415C4C931A79E9C /* QNTxtResolver.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8A96599923B2C19B704BC869D36161A3 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -1009,11 +1002,11 @@ }; 96F820A9CBD7912A405650AC238D1F8E /* HappyDNS */ = { isa = PBXNativeTarget; - buildConfigurationList = 2E3B88327D2E625A83AEFD2F98800DE4 /* Build configuration list for PBXNativeTarget "HappyDNS" */; + buildConfigurationList = 07936FF6ABC799BED409A5E817EDA86C /* Build configuration list for PBXNativeTarget "HappyDNS" */; buildPhases = ( - 1E4754E0A2C420C576DF211058E25D19 /* Headers */, - 160C1A6F91A2369C69CFD020435E4C85 /* Sources */, - 651C5E06824F79F2904DC345C9460CA9 /* Frameworks */, + 336709FFABC1848073960F1D74D3C283 /* Headers */, + E5449B26BB6C908137CAE7F06765A334 /* Sources */, + 98F3DB4FBBEBAF1E86305BF301AE5794 /* Frameworks */, ); buildRules = ( ); @@ -1102,42 +1095,41 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 160C1A6F91A2369C69CFD020435E4C85 /* Sources */ = { + 70B657F26BAD23337EC4D19629BD17E3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B0C40A6195EE239E2F9B78FA89CEB289 /* HappyDNS-dummy.m in Sources */, - 9A541CBF97F3E553259291B3BFDCBA0C /* QNAssessment.m in Sources */, - B1D27B882152A7224EEAD558D293CAC7 /* QNDes.m in Sources */, - A7BB51DA5602DDA8CA392C605500CE7F /* QNDnsManager.m in Sources */, - E0920F60C1305980AD484FF6A53FE117 /* QNDnspodEnterprise.m in Sources */, - E16A819D2F5392EE050D83317C18723A /* QNDnspodFree.m in Sources */, - AED8E5FC30FF7EA27E0EA5E39AA2341F /* QNDomain.m in Sources */, - F3C726A690EF93FEF9EA010D80FF076F /* QNGetAddrInfo.m in Sources */, - C0FDAE269713CCE674298FE70A2F3B7A /* QNHex.m in Sources */, - A65CE94FAA9E3AA9181DE3E28BBD2FC9 /* QNHijackingDetectWrapper.m in Sources */, - 001D8DEA226B1EEF8AEF5ED8D9EBC03E /* QNHosts.m in Sources */, - C6D9D33FF29766B05FAB9FFE86A83246 /* QNIP.m in Sources */, - CCC4224C0B97913E99A9CDF8633D6351 /* QNIpModel.m in Sources */, - CAEAE192F8DD7A52702B96B87D238267 /* QNLruCache.m in Sources */, - B59751092FF5EE107A9682BFA8B9FF42 /* QNMD5.m in Sources */, - A92CDFD1720534B4EDB269CCCD7ECF0C /* QNNetworkInfo.m in Sources */, - AA93BE522FAFFD0E3560DD348FA9BA8F /* QNNiuDns.m in Sources */, - 6BA2C73D840F98A0621442AB74976554 /* QNRecord.m in Sources */, - 62A75019E4F15005EA641F2828D640C9 /* QNRefresher.m in Sources */, - 403EA1260328FA911D6A1662A775EA7B /* QNResolver.m in Sources */, - A6A8D26650C41453BF5465D6323FEAA9 /* QNResolvUtil.m in Sources */, - E3DEAADCF19C228BF606BEB14AF625DB /* QNTxtResolver.m in Sources */, + 18215DEC82E6C7DE502F02F4003F1788 /* FLAnimatedImage-dummy.m in Sources */, + CF3DDB06547EC1A30633781E66B67AA4 /* FLAnimatedImage.m in Sources */, + D74E19C40335D318C539A7363C6C1A5D /* FLAnimatedImageView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 70B657F26BAD23337EC4D19629BD17E3 /* Sources */ = { + E5449B26BB6C908137CAE7F06765A334 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 18215DEC82E6C7DE502F02F4003F1788 /* FLAnimatedImage-dummy.m in Sources */, - CF3DDB06547EC1A30633781E66B67AA4 /* FLAnimatedImage.m in Sources */, - D74E19C40335D318C539A7363C6C1A5D /* FLAnimatedImageView.m in Sources */, + 167909CD6A1BDC01A77005C42CD52941 /* HappyDNS-dummy.m in Sources */, + 6DBF91EDE27C1994D366A7B54CEA6A05 /* QNAssessment.m in Sources */, + 6CFF1A337A614B48DEB4C71F221D4101 /* QNDes.m in Sources */, + B4D99CCC2DF6E36BAA183606945147CF /* QNDnsManager.m in Sources */, + 2B36C0B8E5A23201375FC2EBBE791ECF /* QNDnspodEnterprise.m in Sources */, + 6DC91EFD9C630978FEF145A2ABD0CAD9 /* QNDnspodFree.m in Sources */, + B1C3F81704ED34BEC59ED93E6B588CAE /* QNDomain.m in Sources */, + C8F337A161E101252BB63498F830F4E2 /* QNGetAddrInfo.m in Sources */, + 0223F398FACF9030477C16C6A33EE8AF /* QNHex.m in Sources */, + C2419F0D058F489D0C161AEDEFF14C34 /* QNHijackingDetectWrapper.m in Sources */, + BFCF31C2FE8858041CBD281750CDEAC9 /* QNHosts.m in Sources */, + 0E2726233F99F246F9D39A7D774838F2 /* QNIP.m in Sources */, + 2A8331FB2BABA373C9C71FF466606A37 /* QNIpModel.m in Sources */, + 71317EC60579F9D721A520E0D72A7FCC /* QNLruCache.m in Sources */, + 3FDEFBFAD03902FC2A2D8578C1792AEE /* QNMD5.m in Sources */, + F916166E7B62F41F5021B27430F6AC41 /* QNNetworkInfo.m in Sources */, + 18302B78A66A212BF674473DEC745E32 /* QNRecord.m in Sources */, + 2FDCD3DB86841EC84712A9AE2E9FAEB8 /* QNRefresher.m in Sources */, + 07D908C85D7CF125E2646CB0D8DEE030 /* QNResolver.m in Sources */, + 9DBBFC86DAAAD727157BA6A34F817592 /* QNResolvUtil.m in Sources */, + ED738B69225DB9D84BA1F49EDFFE9815 /* QNTxtResolver.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1238,7 +1230,7 @@ /* Begin XCBuildConfiguration section */ 0629F9E1A6F77632744A11F8C094C0C2 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B3682D5BADEA95326A2820C635C81CC9 /* Qiniu.xcconfig */; + baseConfigurationReference = 6296D8C7CA0FF181715EF1C7782B5E4C /* Qiniu.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1281,9 +1273,33 @@ }; name = Release; }; + 252326EBA52C1601B19C23D2BBD39549 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 69CC7F0099A810CC74C11DD20D18CD34 /* HappyDNS.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/HappyDNS/HappyDNS-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = HappyDNS; + PRODUCT_NAME = HappyDNS; + PUBLIC_HEADERS_FOLDER_PATH = ""; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; 2864B8151371217E5A22C6412F492423 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A3BA7EE9DDDAEA34B2717A3F24D7CCD3 /* Masonry.xcconfig */; + baseConfigurationReference = 53C89494F59D7562B6CCCBD355AC9361 /* Masonry.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1305,9 +1321,9 @@ }; name = Release; }; - 2BD9B02E25A5B145E9F19C9347D4567C /* Debug */ = { + 371081151E8C7918D3CBCD80BA728216 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C26E1B98E1F5D5504D7ED2E547E90F37 /* HappyDNS.xcconfig */; + baseConfigurationReference = 69CC7F0099A810CC74C11DD20D18CD34 /* HappyDNS.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1330,7 +1346,7 @@ }; 3A95B31B6117E1F5C83813733BB834FD /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2CB647AF6ED8CE53ADCB2349EADB6F3C /* FLAnimatedImage.xcconfig */; + baseConfigurationReference = 18FAC25C1AD69EA222A9050A962AC5C1 /* FLAnimatedImage.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1354,7 +1370,7 @@ }; 426F34BA3E088DEB3B7D1C95643253D6 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B3682D5BADEA95326A2820C635C81CC9 /* Qiniu.xcconfig */; + baseConfigurationReference = 6296D8C7CA0FF181715EF1C7782B5E4C /* Qiniu.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1438,7 +1454,7 @@ }; 5D61DC43C7DC2F90C295C51D66EEE358 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A3BA7EE9DDDAEA34B2717A3F24D7CCD3 /* Masonry.xcconfig */; + baseConfigurationReference = 53C89494F59D7562B6CCCBD355AC9361 /* Masonry.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1544,33 +1560,9 @@ }; name = Debug; }; - 9A64EB947712A2B63D0FD8800534FD3E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C26E1B98E1F5D5504D7ED2E547E90F37 /* HappyDNS.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/HappyDNS/HappyDNS-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = HappyDNS; - PRODUCT_NAME = HappyDNS; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; AF304EB8F8D71CEDD16EAF8783D62D39 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2CB647AF6ED8CE53ADCB2349EADB6F3C /* FLAnimatedImage.xcconfig */; + baseConfigurationReference = 18FAC25C1AD69EA222A9050A962AC5C1 /* FLAnimatedImage.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1620,7 +1612,7 @@ }; F73A437C43110E62C482A26F493EA7F0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 1810CF6A6B37A2657A156481418D1E1C /* Crashlytics.xcconfig */; + baseConfigurationReference = 70F6C61E75E25D3DDB3A8D28DCA8C130 /* Crashlytics.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -1633,7 +1625,7 @@ }; F7DCB9A1E20AA4D1F5E050640DA39A0F /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 58DCFDD6DDA971FB8589C74F927A2324 /* Fabric.xcconfig */; + baseConfigurationReference = B6DB9F92212910227CD5FCB98EA57495 /* Fabric.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -1647,7 +1639,7 @@ }; FA4C1AC8F166340D990670E8DA1536CE /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 58DCFDD6DDA971FB8589C74F927A2324 /* Fabric.xcconfig */; + baseConfigurationReference = B6DB9F92212910227CD5FCB98EA57495 /* Fabric.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -1660,7 +1652,7 @@ }; FEABA568424B20154F4B4FC3715B9C4F /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 1810CF6A6B37A2657A156481418D1E1C /* Crashlytics.xcconfig */; + baseConfigurationReference = 70F6C61E75E25D3DDB3A8D28DCA8C130 /* Crashlytics.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -1675,29 +1667,29 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 0B9F7EAACDDA564EC328F53A4AB8CF85 /* Build configuration list for PBXNativeTarget "Masonry" */ = { + 07936FF6ABC799BED409A5E817EDA86C /* Build configuration list for PBXNativeTarget "HappyDNS" */ = { isa = XCConfigurationList; buildConfigurations = ( - 5D61DC43C7DC2F90C295C51D66EEE358 /* Debug */, - 2864B8151371217E5A22C6412F492423 /* Release */, + 371081151E8C7918D3CBCD80BA728216 /* Debug */, + 252326EBA52C1601B19C23D2BBD39549 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 13B185864087F75D556AC109B2D70BF7 /* Build configuration list for PBXAggregateTarget "Fabric" */ = { + 0B9F7EAACDDA564EC328F53A4AB8CF85 /* Build configuration list for PBXNativeTarget "Masonry" */ = { isa = XCConfigurationList; buildConfigurations = ( - FA4C1AC8F166340D990670E8DA1536CE /* Debug */, - F7DCB9A1E20AA4D1F5E050640DA39A0F /* Release */, + 5D61DC43C7DC2F90C295C51D66EEE358 /* Debug */, + 2864B8151371217E5A22C6412F492423 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 2E3B88327D2E625A83AEFD2F98800DE4 /* Build configuration list for PBXNativeTarget "HappyDNS" */ = { + 13B185864087F75D556AC109B2D70BF7 /* Build configuration list for PBXAggregateTarget "Fabric" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2BD9B02E25A5B145E9F19C9347D4567C /* Debug */, - 9A64EB947712A2B63D0FD8800534FD3E /* Release */, + FA4C1AC8F166340D990670E8DA1536CE /* Debug */, + F7DCB9A1E20AA4D1F5E050640DA39A0F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo-acknowledgements.markdown index 1ccd4deb..4e8cf691 100644 --- a/Example/Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo-acknowledgements.markdown +++ b/Example/Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo-acknowledgements.markdown @@ -38,7 +38,7 @@ Fabric: Copyright 2016 Twitter, Inc. All Rights Reserved. Use of this software i The MIT License (MIT) -Copyright (c) 2012-2016 qiniu.com +Copyright (c) 2011-2019 qiniu.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Example/Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo-acknowledgements.plist index bea34f2b..f2cd5e9b 100644 --- a/Example/Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo-acknowledgements.plist +++ b/Example/Pods/Target Support Files/Pods-PLShortVideoKitDemo/Pods-PLShortVideoKitDemo-acknowledgements.plist @@ -67,7 +67,7 @@ SOFTWARE. FooterText The MIT License (MIT) -Copyright (c) 2012-2016 qiniu.com +Copyright (c) 2011-2019 qiniu.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/PLShortVideoKit-Advanced.podspec b/PLShortVideoKit-Advanced.podspec index 34006675..23a6442c 100644 --- a/PLShortVideoKit-Advanced.podspec +++ b/PLShortVideoKit-Advanced.podspec @@ -9,12 +9,12 @@ Pod::Spec.new do |s| s.name = "PLShortVideoKit" - s.version = "2.2.0" + s.version = "3.0.0" s.summary = "PILI iOS short video record SDK" s.homepage = "https://github.com/pili-engineering/PLShortVideoKit" s.license = "Apache License 2.0" s.author = { "pili" => "pili@qiniu.com" } - s.source = { :http => "https://sdk-release.qnsdk.com/PLShortVideoKit-advanced-v2.2.0.zip"} + s.source = { :http => "https://sdk-release.qnsdk.com/PLShortVideoKit-advanced-v3.0.0.zip"} s.platform = :ios s.requires_arc = true diff --git a/PLShortVideoKit-Basic.podspec b/PLShortVideoKit-Basic.podspec index 121c42ea..ef2dbd78 100644 --- a/PLShortVideoKit-Basic.podspec +++ b/PLShortVideoKit-Basic.podspec @@ -9,12 +9,12 @@ Pod::Spec.new do |s| s.name = "PLShortVideoKit" - s.version = "2.2.0" + s.version = "3.0.0" s.summary = "PILI iOS short video record SDK" s.homepage = "https://github.com/pili-engineering/PLShortVideoKit" s.license = "Apache License 2.0" s.author = { "pili" => "pili@qiniu.com" } - s.source = { :http => "https://sdk-release.qnsdk.com/PLShortVideoKit-basic-v2.2.0.zip"} + s.source = { :http => "https://sdk-release.qnsdk.com/PLShortVideoKit-basic-v3.0.0.zip"} s.platform = :ios s.requires_arc = true diff --git a/PLShortVideoKit-Smart.podspec b/PLShortVideoKit-Smart.podspec new file mode 100644 index 00000000..0de19111 --- /dev/null +++ b/PLShortVideoKit-Smart.podspec @@ -0,0 +1,35 @@ +# +# Be sure to run `pod spec lint PLShortVideoKit.podspec' to ensure this is a +# valid spec and to remove all comments including this before submitting the spec. +# +# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html +# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ +# + +Pod::Spec.new do |s| + + s.name = "PLShortVideoKit" + s.version = "3.0.0" + s.summary = "PILI iOS short video record SDK" + s.homepage = "https://github.com/pili-engineering/PLShortVideoKit" + s.license = "Apache License 2.0" + s.author = { "pili" => "pili@qiniu.com" } + s.source = { :http => "https://sdk-release.qnsdk.com/PLShortVideoKit-smart-v3.0.0.zip"} + s.platform = :ios + s.requires_arc = true + + s.ios.deployment_target = "8.0" + + s.dependency 'Qiniu', '7.2.5' + + + s.subspec "ex-libMuseProcessor" do |ss1| + ss1.vendored_framework = "Pod/Library/Smart/PLShortVideoKit.framework" + end + + + s.subspec "libMuseProcessor" do |ss2| + ss2.vendored_libraries = 'Pod/Library/Smart/*.a' + end + +end diff --git a/PLShortVideoKit.podspec b/PLShortVideoKit.podspec index 78eeef00..f5ccec2f 100644 --- a/PLShortVideoKit.podspec +++ b/PLShortVideoKit.podspec @@ -9,12 +9,12 @@ Pod::Spec.new do |s| s.name = "PLShortVideoKit" - s.version = "2.2.0" + s.version = "3.0.0" s.summary = "PILI iOS short video record SDK" s.homepage = "https://github.com/pili-engineering/PLShortVideoKit" s.license = "Apache License 2.0" s.author = { "pili" => "pili@qiniu.com" } - s.source = { :http => "https://sdk-release.qnsdk.com/PLShortVideoKit-profession-v2.2.0.zip"} + s.source = { :http => "https://sdk-release.qnsdk.com/PLShortVideoKit-profession-v3.0.0.zip"} s.platform = :ios s.requires_arc = true diff --git a/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSEditPlayer.h b/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSEditPlayer.h index 23122d01..9dbb78ee 100644 --- a/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSEditPlayer.h +++ b/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSEditPlayer.h @@ -326,4 +326,7 @@ */ - (void)resetVideoLayerOrientation; + +- (void)reverserEffectVideoEnable:(BOOL)enable; + @end diff --git a/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSImageToMovieComposer.h b/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSImageToMovieComposer.h index aa0b4d9c..4d20f777 100644 --- a/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSImageToMovieComposer.h +++ b/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSImageToMovieComposer.h @@ -79,6 +79,8 @@ __deprecated_msg("Class PLSImageToMovieComposer is deprecated in v1.16.0, use PL @property transitionDuration @abstract 转场动画持续的时长,默认为1.0,即1秒 + @warning transitionDuration 最大值不能超过 imageDuration,大于 imageDuration 内部将默认取 imageDuration 的值 + @since v1.8.0 */ @property (assign, nonatomic) CGFloat transitionDuration; diff --git a/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSMovieComposer.h b/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSMovieComposer.h index a1b3104f..d021cdde 100644 --- a/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSMovieComposer.h +++ b/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLSMovieComposer.h @@ -124,7 +124,7 @@ __deprecated_msg("Class PLSMovieComposer is deprecated in v1.16.0, use PLSImageV /*! @method stopComposing - @brief 停止视频拼接s + @brief 停止视频拼接 @since v1.4.0 */ diff --git a/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLShortVideoEditor.h b/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLShortVideoEditor.h index a5af9c5e..72612887 100644 --- a/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLShortVideoEditor.h +++ b/Pod/Library/Profession/PLShortVideoKit.framework/Headers/PLShortVideoEditor.h @@ -63,6 +63,7 @@ @param editor PLShortVideoEditor 实例 @param asset 当前视频 @param timeRange 当前视频的有效视频区域,对应 PLShortVideoEditor 的属性 @property (assign, nonatomic) CMTimeRange timeRange + @since v1.9.0 */ @@ -434,6 +435,11 @@ */ - (void)resetVideoLayerOrientation; + +- (void)addReverserEffectVideoWithAudio:(BOOL)enable; + +- (void)removeReverserEffectVideoWithAudio; + @end diff --git a/Pod/Library/Profession/PLShortVideoKit.framework/Info.plist b/Pod/Library/Profession/PLShortVideoKit.framework/Info.plist index e5c0ef7a..39287ff3 100644 Binary files a/Pod/Library/Profession/PLShortVideoKit.framework/Info.plist and b/Pod/Library/Profession/PLShortVideoKit.framework/Info.plist differ diff --git a/Pod/Library/Profession/PLShortVideoKit.framework/PLShortVideoKit b/Pod/Library/Profession/PLShortVideoKit.framework/PLShortVideoKit index 14ed5d0e..668086ce 100644 Binary files a/Pod/Library/Profession/PLShortVideoKit.framework/PLShortVideoKit and b/Pod/Library/Profession/PLShortVideoKit.framework/PLShortVideoKit differ diff --git a/README.md b/README.md index 88e2b8fd..f54ddfa6 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,84 @@ # 1 产品简介 七牛短视频 SDK,方便开发者快速实现短视频拍摄、剪辑、编辑、合成、分发功能。我们提供 80+ 功能供开发使用,申请 **0 元体验**可联系销售或[填写表单](https://jinshuju.net/f/IeOD89?ref=www.qiniu.com)获得产品试用权限。 -# 2 多版本功能分布 -短视频 SDK 主要区分基础版、进阶版、专业版 3 个版本,不同版本的功能区别见如下表格 - -| 功能 | 子功能 | 基础版 | 进阶版 | 专业版 | -| :----------------------------------------------------------- | :----------------------------------------------------------- | :---------------------: | :---------------------: | :----------------------: | -| **用户交互界面** | **提供了一套完整的UI交互源码,可复用或自定义** | ✓ | ✓ | ✓ | -| **视频拍摄录制** | **摄像头采集** | ✓ | ✓ | ✓ | -| | **麦克风采集** | ✓ | ✓ | ✓ | -| | **视频采集参数定义**
*支持最高 1080P 拍摄,支持自定义视频采集源、采集画面的分辨率、采集画面的长宽比等参数* | ✓ | ✓ | ✓ | -| | **音频采集参数定义**
*支持自定义音频采集源、音频格式、音频声道、音频采样率等参数* | ✓ | ✓ | ✓ | -| | **视频编码参数定义**
*支持自定义编码视频的码率、帧率、分辨率、H.264 编码方式等参数* | ✓ | ✓ | ✓ | -| | **音频编码参数定义**
*支持自定义编码音频的码率、采样率、声道数、AAC 编码方式等参数* | ✓ | ✓ | ✓ | -| | **拍摄时长设置**
*支持设置实际拍摄过程中的最大、最小拍摄时长* | ✓ | ✓ | ✓ | -| | **摄像头切换**
*支持切换前后摄像头进行拍摄* | ✓ | ✓ | ✓ | -| | **闪光灯设置**
*支持开关闪光灯用于拍摄时的补光* | ✓ | ✓ | ✓ | -| | **曝光调节**
*支持调整曝光度参数* | ✓ | ✓ | ✓ | -| | **画面对焦**
*支持手动对焦和自动对焦* | ✓ | ✓ | ✓ | -| | **焦距调节**
*支持手动调节画面焦距进行放大、缩小* | ✓ | ✓ | ✓ | -| | **画面镜像**
*支持设置是否镜像预览画面和编码画面* | ✓ | ✓ | ✓ | -| | **横屏拍摄**
*支持根据设备的方向自动确定竖屏、横屏拍摄* | ✓ | ✓ | ✓ | -| | **分段拍摄**
*支持拍摄过程中实现连续多次拍摄、断点续拍、回删* | ✓ | ✓ | ✓ | -| | **变速拍摄**
*支持设置拍摄时的快/慢速率,目前支持 5 种拍摄速率* | ✗ | ✓ | ✓ | -| | **音频录制**
*支持纯音频录制* | ✓ | ✓ | ✓ | -| | **音频录制(图片特效)**
*支持音频录制的过程中,增加图片旋转效果,输出为 mp4 文件* | ✗ | ✓ | ✓ | -| | **背景音乐**
*支持拍摄前选择本地文件作为背景音乐* | ✗ | ✓ | ✓ | -| | **实时截图**
*支持拍摄时实时截图拍照保存到本地* | ✓ | ✓ | ✓ | -| | **静音功能**
*支持静音拍摄* | ✓ | ✓ | ✓ | -| | **分屏拍摄(合拍)**
*可以根据素材视频(或图片)进行合拍,生成双画面视频* | ✗ | ✗ | ✓ | -| | **屏幕录制(全屏) / View 录制(局部)**
*支持对整个屏幕或部分区域进行录制,实现整体或局部的录制效果* | ✗ | ✓
全屏 | ✓
全屏+局部 | -| | **外部导入**
*支持外部音视频裸数据导入,生成 mp4 文件* | ✗ | ✗ | ✓ | -| | **前后台切换**
*根据监听到 Application 的前后台状态自动停止和开始录制视频,默认从后台进入前台自动开始录制* | ✓ | ✓ | ✓ | -| | **实时水印**
*支持拍摄时添加静态水印,支持设置水印位置、大小、透明度,设置作用时间范围* | ✗ | ✓ | ✓ | -| | **实时美颜**
*支持拍摄时启用美颜功能,支持设置美颜、美白、红润 3 种效果并调节强度* | ✓ | ✓ | ✓ | -| | **实时滤镜**
*支持拍摄时启用滤镜功能,支持自由调节多种滤镜效果(33 种)* | ✓
提供 10 种滤镜效果 | ✓
提供 10 种滤镜效果 | ✓
提供 33 种滤镜效果 | -| | **实时预览**
*支持实时本地预览* | ✓ | ✓ | ✓ | -| | **草稿箱**
*支持将当前录制的片段与设置项存入草稿箱* | ✓ | ✓ | ✓ | -| **视频剪辑合成** | **视频导入**
*支持本地视频快速导入后编辑* | ✓ | ✓ | ✓ | -| | **编辑预览**
*支持编辑时实时预览本地效果* | ✓ | ✓ | ✓ | -| | **视频剪辑**
*支持按照给定的时间范围生成一个 mp4 文件* | ✓ | ✓ | ✓ | -| | **视频剪裁**
*支持按照视频画面大小(原比例、指定区域)精确裁剪视频生成一个 mp4 文件* | ✗ | ✗ | ✓ | -| | **视频转码**
*支持按照给定的目标旋转角度、码率、帧率等参数,生成一个 mp4 文件* | ✓ | ✓ | ✓ | -| | **视频拼接**
*基础功能:支持设置多个视频按照前后顺序导入拼接生成一个 mp4 文件*
*高级功能:支持设置多个视频的时间范围按照前后顺序导入拼接生成一个 mp4 文件(先分割后拼接)* | ✗ | ✓
基础功能 | ✓
基础功能 + 高级功能 | -| | **视频合成**
*支持设置多个视频合并为一个视频,支持设置每一个视频的位置、大小、开始播放时间等* | ✗ | ✗ | ✓ | -| | **GIF动画**
*支持基于多个图片或视频直接导出GIF动图* | ✗ | ✓ | ✓ | -| | **图片拼接**
*支持设置多个图片按照前后顺序导入拼接生成一个 mp4 文件* | ✗ | ✓ | ✓ | -| | **图片 & GIF 图 & 视频混拼**
*支持设置多个视频和图片按照前后顺序导入拼接生成一个 mp4 文件* | ✗ | ✗ | ✓ | -| **视频编辑处理** | **滤镜特效**
*支持给视频文件添加滤镜效果,默认支持33种滤镜效果* | ✗ | ✓
提供 10 种滤镜效果 | ✓
提供 33 种滤镜效果 | -| | **贴纸特效**
*支持给视频文件添加静态贴纸,并且能够自由设置贴纸大小、位置、旋转角度,支持设置特效显示的时间范围,可以自定义素材或使用供应商提供的收费素材* | ✗ | ✓ | ✓ | -| | **水印特效**
*支持给视频文件添加静态、动态水印,并且能够自由设置水印的大小、位置、透明度、旋转角度,支持设置特效显示的时间范围,可以自定义素材或使用供应商提供的收费素材* | ✗ | ✓ | ✓ | -| | **时间特效**
*支持对视频文件进行整体变速、分段变速,支持5种变速效果(极慢、慢、正常、快、极快)*
*支持1种倒放操作(即时光倒流特效)* | ✗ | ✓
变速 | ✓
变速+倒序 | -| | **字幕特效**
*支持给视频文件添加文字特效,支持设置文字内容,字体大小,字体颜色,透明度,旋转,位置等,支持设置特效显示的时间范围* | ✗ | ✓ | ✓ | -| | **MV特效**
*支持给视频文件添加 MV 效果,默认提供 4 种 MV 特效,MV 特效素材需要客户自行按要求制作* | ✗ | ✗ | ✓ | -| | **涂鸦特效**
*支持画笔尺寸和颜色调整,支持设置特效显示的时间范围* | ✗ | ✓ | ✓ | -| | **基础转场**
*支持在视频图片片段之间,增加淡入淡出效果* | ✗ | ✓ | ✓ | -| | **过场字幕**
*支持在视频之间增加转场字幕,支持定义转场字幕的背景色、持续时间、支持文字和图片特效,支持旋转、放大、位置移动、淡入淡出 4 种效果* | ✗ | ✗ | ✓ | -| | **混音特效**
*支持给视频文件添加多个背景音乐,支持调整视频原声、背景音乐音量,支持设置多个背景音乐有效时间区域* | ✗ | ✓
支持单音频混音 | ✓
支持多音频混音 | -| | **旋转特效**
*支持设置视频左右上下旋转,实时预览旋转效果* | ✗ | ✓ | ✓ | -| **视频播放** | **播放器SDK** | ✓ | ✓ | ✓ | -| **上传分发** | **视频上传** | ✓ | ✓ | ✓ | -| | **断点续传** | ✓ | ✓ | ✓ | -| | **上传加速** | ✓ | ✓ | ✓ | -| **接口扩展** | **扩展接口支持对接第三方美颜特效等增值能力** | ✓ | ✓ | ✓ | -| **增值能力**
(需要客户单独选购,在视频拍摄或视频编辑阶段增加) | **高级美颜**
*拍摄设置大眼、瘦脸、V脸、下巴调整、短脸、小鼻效果,并支持调节强度* | ✓ | ✓ | ✓ | -| | **人脸贴纸**
*支持人脸识别,进行人脸 2D、3D 贴纸操作* | ✓ | ✓ | ✓ | -| | **手势识别**
*可以对拍摄的人物的特定手势进行识别,配合其他特效*| ✓ | ✓ | ✓ | -| | **AR 特效**
*支持拍摄时设置AR特效* | ✓ | ✓ | ✓ | -| | **变声混响**
*拍摄时对录制的人音进行变声(如萝莉、大叔)和混响效果等操作(如KTV、会堂)* | ✓ | ✓ | ✓ | -| | **类抖音特效**
*滤镜效果,支持抖动、幻觉、灵魂出窍等数种抖音特效* | ✓ | ✓ | ✓ | -| | **背景抠图**
*将画面中的绿色元素(比如纯绿背景)抠除,替换成其他的元素,比如动态背景/PPT 等* | ✓ | ✓ | ✓ | +# 2 多版本功能分布 + +短视频SDK主要区分精简版、基础版、进阶版、专业版 4 个版本,不同版本的功能区别见如下表格 + +| 功能 | 子功能 | 精简版 | 基础版 | 进阶版 | 专业版 | +| :-------------------------- | :------------------------ | :------------------:| :---------------------: | :---------------------: | :----------------------: | +| **用户交互界面** | **提供了一套完整的UI交互源码,可复用或自定义** | ✓ | ✓ | ✓ | ✓ | +| **拍摄设置** | **摄像头采集** | ✓ | ✓ | ✓ | ✓ | +| | **麦克风采集** | ✓ | ✓ | ✓ | ✓ | +| | **视频采集参数定义**
*支持最高 1080P 拍摄,支持自定义视频采集源、采集画面的分辨率、采集画面的长宽比等参数* | ✓ | ✓ | ✓ | ✓ | +| | **音频采集参数定义**
*支持自定义音频采集源、音频格式、音频声道、音频采样率等参数* | ✓ | ✓ | ✓ | ✓ | +| | **视频编码参数定义**
*支持自定义编码视频的码率、帧率、分辨率、H.264 编码方式等参数* | ✓ | ✓ | ✓ | ✓ | +| | **音频编码参数定义**
*支持自定义编码音频的码率、采样率、声道数、AAC 编码方式等参数* | ✓ | ✓ | ✓ | ✓ | +| | **拍摄时长设置**
*支持设置实际拍摄过程中的最大、最小拍摄时长* | ✓ | ✓ | ✓ | ✓ | +| | **前后台切换**
*根据监听到 Application 的前后台状态自动停止和开始录制视频,默认从后台进入前台自动开始录制* | ✓ | ✓ | ✓ | ✓ | +| | **摄像头切换**
*支持切换前后摄像头进行拍摄* | ✓ | ✓ | ✓ | ✓ | +| | **闪光灯设置**
*支持开关闪光灯用于拍摄时的补光* | ✓ | ✓ | ✓ | ✓ | +| | **画面镜像**
*支持设置是否镜像预览画面和编码画面* | ✓ | ✓ | ✓ | ✓ | +| | **画面对焦**
*支持手动对焦和自动对焦* | ✓ | ✓ | ✓ | ✓ | +| | **焦距调节**
*支持手动调节画面焦距进行放大、缩小* | ✓ | ✓ | ✓ | ✓ | +| | **曝光调节**
*支持调整曝光度参数* | ✓ | ✓ | ✓ | ✓ | +| **拍摄模式** | **横屏拍摄**
*支持根据设备的方向自动确定竖屏、横屏拍摄* | ✓ | ✓ | ✓ | ✓ | +| | **分段拍摄**
*支持拍摄过程中实现连续多次拍摄、断点续拍、回删* | ✓ | ✓ | ✓ | ✓ | +| | **静音拍摄**
*支持静音拍摄* | ✓ | ✓ | ✓ | ✓ | +| | **音频录制**
*支持纯音频录制* | ✓ | ✓ | ✓ | ✓ | +| | **屏幕录制**
*支持对整个屏幕区域进行录制,实现整体的录制效果* | ✓ | ✓ | ✓ | ✓ | +| | **变速拍摄**
*支持设置拍摄时的快/慢速率,目前支持 5 种拍摄速率(默认正常速率,只支持 2 的倍数,或 1/2 的倍数)* | ✗ | ✓ | ✓ | ✓ | +| | **分屏拍摄(合拍)**
*可以根据素材视频(或图片)进行合拍,生成双画面视频* | ✗ | ✗ | ✓ | ✓ | +| **实时处理** | **实时截图**
*支持拍摄时实时截图拍照保存到本地* | ✓ | ✓ | ✓ | ✓ | +| | **实时预览**
*支持实时本地预览* | ✓ | ✓ | ✓ | ✓ | +| | **实时美颜**
*支持拍摄时启用美颜功能,支持设置美颜、美白、红润 3 种效果并调节强度* | ✓ | ✓ | ✓ | ✓ | +| | **实时滤镜**
支持*拍摄时启用滤镜功能,支持自由调节多种滤镜效果(33种)* | ✗ | ✓
提供 10 种滤镜效果 | ✓
提供 33 种滤镜效果 | ✓
提供 33 种滤镜效果 | +| | **实时水印**
*支持拍摄时添加静态水印,支持设置水印位置、大小、透明度,设置作用时间范围* | ✗ | ✓ | ✓ | ✓ | +| | **背景音乐**
*支持拍摄前选择本地文件作为背景音乐* | ✗ | ✓ | ✓ | ✓ | +| **基础编辑** | **视频导入**
*支持本地视频快速导入后编辑* | ✓ | ✓ | ✓ | ✓ | +| | **编辑预览**
*支持编辑时实时预览本地效果* | ✓ | ✓ | ✓ | ✓ | +| | **时长剪裁**
*支持时长裁剪,按照给定的时间范围生成一个 mp4 文件* | ✓ | ✓ | ✓ | ✓ | +| | **本地转码**
*支持按照给定的码率、帧率等参数,生成一个 mp4 文件* | ✓ | ✓ | ✓ | ✓ | +| | **视频旋转**
*支持按照给定的目标旋转角度,生成一个 mp4 文件* | ✗ | ✓ | ✓ | ✓ | +| | **画面剪裁**
*支持画面裁剪,按照视频画面大小(原比例、指定区域)精确裁剪视频生成一个mp4文件* | ✗ | ✗ | ✓ | ✓ | +| **特效编辑** | **视频旋转特效**
*支持设置视频左右上下旋转,实时预览旋转效果* | ✗ | ✓ | ✓ | ✓ | +| | **单音频混音**
*支持给视频文件添加单音频,实现混音效果* | ✗ | ✓ | ✓ | ✓ | +| | **滤镜特效**
*支持给视频文件添加滤镜效果,默认支持 33 种滤镜效果* | ✗ | ✓
提供 10 种滤镜效果 | ✓
提供 33 种滤镜效果 | ✓
提供 33 种滤镜效果 | +| | **涂鸦特效**
*支持画笔尺寸和颜色调整,支持设置特效显示的时间范围* | ✗ | ✓ | ✓ | ✓ | +| | **字幕特效**
*支持给视频文件添加文字特效,支持设置文字内容,字体大小,字体颜色,透明度,旋转,位置等,支持设置特效显示的时间范围* | ✗ | ✓ | ✓ | ✓ | +| | **水印特效**
*支持给视频文件添加静态、动态水印,并且能够自由设置水印的大小、位置、透明度、旋转角度,支持设置特效显示的时间范围,可以自定义素材或使用供应商提供的收费素材* | ✗ | ✓ | ✓ | ✓ | +| | **贴纸特效**
*支持给视频文件添加静态贴纸,并且能够自由设置贴纸大小、位置、旋转角度,支持设置特效显示的时间范围,可以自定义素材或使用供应商提供的收费素材* | ✗ | ✓ | ✓ | ✓ | +| | **时间特效**
*支持对视频文件进行整体变速、分段变速,支持5种变速效果(极慢、慢、正常、快、极快)* | ✗ | ✓ | ✓ | ✓ | +| | **时光倒流**
*支持 1 种倒放操作(即时光倒流特效)* | ✗ | ✗ | ✓ | ✓ | +| | **音乐唱片**
*支持音频录制的过程中,增加图片旋转效果,输出为 mp4 文件* | ✗ | ✗ | ✓ | ✓ | +| | **多音频混音**
*支持给视频文件添加多个背景音乐,支持调整视频原声、背景音乐音量,支持设置多个背景音乐有效时间区域,支持自己录音或者选用本地音乐* | ✗ | ✗ | ✗ | ✓ | +| | **MV 特效**
*支持给视频文件添加 MV 效果,默认提供 4 种 MV 特效,MV 特效素材需要客户自行按要求制作* | ✗ | ✗ | ✗ | ✓ | +| **多素材编排** | **视频拼接**
*支持设置多个视频按照前后顺序导入拼接生成一个 mp4 文件* | ✗ | ✗ | ✓ | ✓ | +| | **GIF 动画**
*支持基于多个图片或视频直接导出 GIF 动图* | ✗ | ✗ | ✓ | ✓ | +| | **图片拼接**
*支持设置多个图片按照前后顺序导入拼接生成一个 mp4 文件* | ✗ | ✗ | ✓ | ✓ | +| | **基础转场**
*支持在视频图片片段之间,增加淡入淡出效果* | ✗ | ✗ | ✓ | ✓ | +| | **过场字幕**
*支持在视频之间增加转场字幕,支持定义转场字幕的背景色、持续时间、支持文字和图片特效,支持旋转、放大、位置移动、淡入淡出 4 种效果* | ✗ | ✗ | ✓ | ✓ | +| | **视频合成**
*支持设置多个视频合并为一个视频,支持设置每一个视频的位置、大小、开始播放时间等* | ✗ | ✗ | ✗ | ✓ | +| | **图片 & GIF 图 & 视频混拼**
*支持设置多个视频和图片按照前后顺序导入拼接生成一个 mp4 文件* | ✗ | ✗ | ✗ | ✓ | +| **其他功能** | **草稿箱**
*支持将当前录制的片段与设置项存入草稿箱* | ✓ | ✓ | ✓ | ✓ | +| | **接口扩展**
*扩展接口支持对接第三方美颜特效等增值能力* | ✓ | ✓ | ✓ | ✓ | +| | **外部裸数据导入**
*支持外部音视频裸数据导入,生成 mp4 文件* | ✗ | ✗ | ✗ | ✓ | +| | **View 录制**
*支持 View 录制* | ✗ | ✗ | ✗ | ✓ | +| **视频播放** | **播放器 SDK** | ✓ | ✓ | ✓ | ✓ | +| **上传分发** | **视频上传** | ✓ | ✓ | ✓ | ✓ | +| | **断点续传** | ✓ | ✓ | ✓ | ✓ | +| | **上传加速** | ✓ | ✓ | ✓ | ✓ | + +增值能力方面,需要单独选购,在视频拍摄或视频编辑阶段增加,4个版本都支持相关开放接口。 + +| **功能** | +| ---------------------------------------------------------------------------------- | +| **高级美颜**
*拍摄设置大眼、瘦脸、V脸、下巴调整、短脸、小鼻效果,并支持调节强度* | +| **人脸贴纸**
*支持人脸识别,进行人脸 2D、3D 贴纸操作* | +| **手势识别**
*可以对拍摄的人物的特定手势进行识别,配合其他特效* | +| **AR 特效**
*支持拍摄时设置 AR 特效* | +| **变声混响**
*拍摄时对录制的人音进行变声(如萝莉、大叔)和混响效果等操作(如 KTV、会堂)* | +| **类抖音特效**
*滤镜效果,支持抖动、幻觉、灵魂出窍等数种抖音特效* | +| **背景抠图**
*将画面中的绿色元素(比如纯绿背景)抠除,替换成其他的元素,比如动态背景/ PPT 等* | # 3 设备以及系统要求 @@ -165,9 +175,37 @@ end ```bash $ pod install +``` + +## 4.5 精简版安装 +**如果你购买的是七牛基础版本的短视频 SDK,请使用下面的安装方式:** + +### 4.5.1 Podfile 添加精简版 + +```ruby +target 'TargetName' do +pod 'PLShortVideoKit', :podspec => 'https://raw.githubusercontent.com/pili-engineering/PLShortVideoKit/master/PLShortVideoKit-Smart.podspec' +end ``` -## 4.5 Warning +### 4.5.2 Warnings + +**在使用了七牛的推流或连麦 SDK 的工程中,集成该短视频 SDK 会出现美颜库导致的符号冲突问题 duplicate symbol _OBJC_CLASS_ MuseProcessor,解决方法如下** + +```ruby +target 'TargetName' do +pod 'PLShortVideoKit/ex-libMuseProcessor', :podspec => 'https://raw.githubusercontent.com/pili-engineering/PLShortVideoKit/master/PLShortVideoKit-Smart.podspec' +end +``` +### 4.5.3 运行 pod +然后,运行如下的命令: + +```bash +$ pod install +``` + + +## 4.6 Warning - Podfile 中添加 PLShortVideoKit 时如果不指定 podspec,默认安装的是 **专业版** 的短视频 SDK - 如果你安装的七牛短视频 SDK 版本和你购买的七牛短视频 SDK 版本不一致,比如购买的基础版,但是使用的是进阶版或者专业版的短视频 SDK,会引起你的 App 产生 crash 。**请一定安装和你购买匹配的短视频 SDK 版本** diff --git a/ReleaseNotes/release-notes-3.0.0.md b/ReleaseNotes/release-notes-3.0.0.md new file mode 100644 index 00000000..a10a34df --- /dev/null +++ b/ReleaseNotes/release-notes-3.0.0.md @@ -0,0 +1,18 @@ +# PLShortVideoKit Release Notes for 3.0.0 + +### 简介 +PLShortVideoKit 是七牛推出的一款适用于 iOS 平台的短视频 SDK,提供了包括美颜、滤镜、水印、断点录制、分段回删、视频编辑、混音特效、MV 特效、本地/云端存储在内的多种功能,支持高度定制以及二次开发。 + +### 版本 +- 发布 PLShortVideoKit.framework + +### 缺陷 +- 修复合拍分多段录制后,视频声音断断续续的问题 +- 修复部分图片和视频混排添加转场动画合成偶现失败的问题 +- 修复PLSImageToMovieComposer设置转场时间没有效果的问题 + + +### 注意事项 +- 七牛短视频 SDK 自 v3.0.0 版本起, 划分为精简版、基础版、进阶版、专业版 。不同版本 SDK 可以使用的功能点数量有差别,请按照购买的 License 版本使用对应的短视频 SDK 版本。 +- 若需要使用 PLShortVideoKit.framework 中的内置滤镜,则必须将 PLShortVideoKit.bundle 导入项目中。若需要增删、替换滤镜资源可操作 PLShortVideoKit.bundle 中的 colorFilter 文件夹。 +- 抖音特效,需要联系七牛商务获取 appkey 和资源文件。具体使用可参看 PLShortVideoKitDemo。