├── README.md ├── VideoCameraDemo ├── music_image.jpg ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── Icon-60.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-Small@2x.png │ │ ├── Icon-Small@3x.png │ │ ├── Dong+ logo _画板 1.png │ │ ├── Icon-Spotlight-40.png │ │ ├── Icon-Spotlight-40@2x.png │ │ ├── Icon-Spotlight-40@3x.png │ │ └── Contents.json │ ├── LaunchLogo.imageset │ │ ├── LaunchLogo副本.png │ │ └── Contents.json │ ├── circle_add_friend_icon.imageset │ │ ├── 粉丝.png │ │ └── Contents.json │ └── circle_apply_friend_icon.imageset │ │ ├── 关注 (1).png │ │ └── Contents.json ├── ViewController.h ├── AppDelegate.h ├── main.m ├── AppDelegate.m ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard ├── Info.plist └── ViewController.m ├── SDVideoCamera ├── Resources │ ├── sd_camera_upload@3x.png │ ├── sd_corp_add_icon@3x.png │ ├── sd_corp_drag_icon@3x.png │ ├── sd_camera_turn_over@3x.png │ ├── sd_commom_exit_icon@3x.png │ ├── sd_corp_cancle_icon@3x.png │ ├── sd_corp_delete_icon@3x.png │ ├── sd_preview_color_bg@3x.png │ ├── sd_album_delete_icon@3x.png │ ├── sd_camera_count_down@3x.png │ ├── sd_camera_original_off@3x.png │ ├── sd_camera_original_on@3x.png │ ├── sd_commom_return_icon@3x.png │ ├── sd_preview_color_alpha@3x.png │ ├── sd_preview_color_text@3x.png │ ├── sd_preview_image_icon@3x.png │ ├── sd_preview_text_icon@3x.png │ ├── sd_camera_flash_light_on@3x.png │ ├── sd_camera_menu_delete_icon.png │ ├── sd_camera_menu_finish_icon.png │ ├── sd_camera_autho_open_icon@3x.png │ ├── sd_camera_flash_light_off@3x.png │ ├── sd_preview_alignment_center@3x.png │ ├── sd_preview_alignment_left@3x.png │ ├── sd_preview_alignment_right@3x.png │ ├── sd_preview_music_more_icon@3x.png │ ├── sd_preview_text_delete_icon@2x.png │ ├── sd_preview_music_finish_icon@3x.png │ ├── sd_preview_music_normal_icon@3x.png │ ├── sd_preview_music_volume_icon@3x.png │ ├── sd_preview_music_default_image@3x.png │ ├── sd_video_loading │ │ ├── sd_video_loading0@2x.png │ │ ├── sd_video_loading1@2x.png │ │ ├── sd_video_loading2@2x.png │ │ ├── sd_video_loading3@2x.png │ │ ├── sd_video_loading4@2x.png │ │ ├── sd_video_loading5@2x.png │ │ ├── sd_video_loading6@2x.png │ │ ├── sd_video_loading7@2x.png │ │ ├── sd_video_loading8@2x.png │ │ ├── sd_video_loading9@2x.png │ │ ├── sd_video_loading10@2x.png │ │ ├── sd_video_loading11@2x.png │ │ ├── sd_video_loading12@2x.png │ │ ├── sd_video_loading13@2x.png │ │ ├── sd_video_loading14@2x.png │ │ ├── sd_video_loading15@2x.png │ │ ├── sd_video_loading16@2x.png │ │ ├── sd_video_loading17@2x.png │ │ ├── sd_video_loading18@2x.png │ │ ├── sd_video_loading19@2x.png │ │ ├── sd_video_loading20@2x.png │ │ ├── sd_video_loading21@2x.png │ │ ├── sd_video_loading22@2x.png │ │ ├── sd_video_loading23@2x.png │ │ ├── sd_video_loading24@2x.png │ │ ├── sd_video_loading25@2x.png │ │ ├── sd_video_loading26@2x.png │ │ ├── sd_video_loading27@2x.png │ │ ├── sd_video_loading28@2x.png │ │ ├── sd_video_loading29@2x.png │ │ ├── sd_video_loading30@2x.png │ │ ├── sd_video_loading31@2x.png │ │ ├── sd_video_loading32@2x.png │ │ ├── sd_video_loading33@2x.png │ │ ├── sd_video_loading34@2x.png │ │ ├── sd_video_loading35@2x.png │ │ ├── sd_video_loading36@2x.png │ │ ├── sd_video_loading37@2x.png │ │ ├── sd_video_loading38@2x.png │ │ ├── sd_video_loading39@2x.png │ │ ├── sd_video_loading40@2x.png │ │ ├── sd_video_loading41@2x.png │ │ ├── sd_video_loading42@2x.png │ │ ├── sd_video_loading43@2x.png │ │ ├── sd_video_loading44@2x.png │ │ ├── sd_video_loading45@2x.png │ │ ├── sd_video_loading46@2x.png │ │ ├── sd_video_loading47@2x.png │ │ ├── sd_video_loading48@2x.png │ │ ├── sd_video_loading49@2x.png │ │ ├── sd_video_loading50@2x.png │ │ ├── sd_video_loading51@2x.png │ │ ├── sd_video_loading52@2x.png │ │ ├── sd_video_loading53@2x.png │ │ ├── sd_video_loading54@2x.png │ │ ├── sd_video_loading55@2x.png │ │ ├── sd_video_loading56@2x.png │ │ ├── sd_video_loading57@2x.png │ │ ├── sd_video_loading58@2x.png │ │ └── sd_video_loading59@2x.png │ └── sd_preview_ expression │ │ └── expression.bundle │ │ ├── 冷.png │ │ ├── 凶.png │ │ ├── 哼.png │ │ ├── 啊.png │ │ ├── 晕.png │ │ ├── 衰.png │ │ ├── 酷.png │ │ ├── 三条线.png │ │ ├── 不舒服.png │ │ ├── 什么.png │ │ ├── 企鹅.png │ │ ├── 便便.png │ │ ├── 冷酷.png │ │ ├── 又死了.png │ │ ├── 发呆.png │ │ ├── 受伤.png │ │ ├── 吐舌头.png │ │ ├── 吓死.png │ │ ├── 呕吐.png │ │ ├── 呲牙.png │ │ ├── 呼气.png │ │ ├── 喜欢.png │ │ ├── 坏笑.png │ │ ├── 大惊.png │ │ ├── 大笑.png │ │ ├── 大闹.png │ │ ├── 天使.png │ │ ├── 奋斗.png │ │ ├── 好吃.png │ │ ├── 尴尬.png │ │ ├── 幽灵.png │ │ ├── 开心.png │ │ ├── 心碎.png │ │ ├── 忍者.png │ │ ├── 怪物.png │ │ ├── 恩_.png │ │ ├── 恶魔.png │ │ ├── 惊恐.png │ │ ├── 惊悚.png │ │ ├── 惊讶.png │ │ ├── 感冒.png │ │ ├── 愤怒.png │ │ ├── 懵逼.png │ │ ├── 打哈欠.png │ │ ├── 斜眼.png │ │ ├── 无聊.png │ │ ├── 星星眼.png │ │ ├── 死了.png │ │ ├── 汗颜.png │ │ ├── 流口水.png │ │ ├── 流汗.png │ │ ├── 流泪.png │ │ ├── 流鼻血.png │ │ ├── 炸弹.png │ │ ├── 点赞.png │ │ ├── 爱你.png │ │ ├── 爱心.png │ │ ├── 犯困.png │ │ ├── 猪头.png │ │ ├── 献吻.png │ │ ├── 生气.png │ │ ├── 疑问.png │ │ ├── 白眼.png │ │ ├── 睡着.png │ │ ├── 睡醒.png │ │ ├── 瞌睡.png │ │ ├── 笑掉大牙.png │ │ ├── 笑脸.png │ │ ├── 讨厌.png │ │ ├── 调皮.png │ │ ├── 贪吃.png │ │ ├── 闭嘴.png │ │ ├── 难过.png │ │ ├── 面无表情.png │ │ ├── 飞吻.png │ │ ├── 饿死.png │ │ ├── 骂人.png │ │ ├── 骷髅.png │ │ └── 鼻涕.png ├── Preview │ ├── SDVideoPreviewEffectModel.m │ ├── SDVideoPreviewTagCell.h │ ├── SDVideoPreviewTextColorCell.h │ ├── SDVideoPreviewMusicCell.h │ ├── SDVideoPreviewMusicSlider.h │ ├── SDVideoPreviewViewController.h │ ├── SDVideoMusicModel.m │ ├── SDVideoPreviewTextView.h │ ├── SDVideoPreviewTagsView.h │ ├── SDVideoPreviewEffectModel.h │ ├── SDVideoMusicModel.h │ ├── SDVideoPreviewMusicView.h │ ├── SDVideoPreviewTagCell.m │ ├── SDVideoPreviewTextColorCell.m │ ├── SDVideoPreviewMusicSlider.m │ ├── SDVideoPreviewMusicCell.m │ └── SDVideoPreviewTagsView.m ├── Crop │ ├── SDVideoCropItemListAddCell.h │ ├── SDVideoCropFrameCell.h │ ├── SDVideoCropItemListCell.h │ ├── SDVideoCropItemListView.h │ ├── SDVideoCropViewController.h │ ├── SDVideoCropFrameModel.m │ ├── SDVideoCropBottomView.h │ ├── SDVideoCropFrameModel.h │ ├── SDVideoCropFrameView.h │ ├── SDVideoCropHeader.h │ ├── SDVideoCropItemDeleteView.h │ ├── SDVideoCropFrameCell.m │ ├── SDVideoCropItemListAddCell.m │ ├── SDVideoCropItemListCell.m │ ├── SDVideoCropItemDeleteView.m │ └── SDVideoCropBottomView.m ├── Helpers │ ├── SDVideoLoadingView.h │ ├── SDAudioPlayerManager.h │ ├── SDVideoDataModel.h │ ├── SDVideoDataModel.m │ ├── SDVideoCaptureManager.h │ ├── SDVideoDataManager.h │ ├── SDAudioPlayerManager.m │ ├── SDVideoCropDataManager.h │ ├── SDVideoUtils.h │ ├── SDVideoLoadingView.m │ ├── SDVideoCropDataManager.m │ └── SDVideoDataManager.m ├── Categories │ ├── NSString+Size.h │ ├── UIColor+HexStringColor.h │ ├── UIImage+Color.h │ ├── UIButton+EdgeInsets.h │ ├── NSString+Size.m │ ├── UIView+Extension.h │ ├── UIColor+HexStringColor.m │ ├── UIImage+Color.m │ ├── UIView+Extension.m │ └── UIButton+EdgeInsets.m ├── Album │ ├── SDVideoAlbumCell.h │ ├── SDVideoAlbumSelectCell.h │ ├── SDVideoAlbumViewController.h │ ├── SDVideoAlbumSelectCell.m │ └── SDVideoAlbumCell.m ├── SDVideoController.h ├── Camera │ ├── SDVideoCameraController.h │ ├── SDVideoCameraPlayButton.h │ ├── SDVideoCameraAuthoView.h │ ├── SDVideoMenuDataModel.h │ ├── SDVideoMenuDataModel.m │ ├── SDVideoCameraMenuView.h │ ├── SDVideoCameraHeader.h │ ├── SDVideoCameraPlayButton.m │ ├── SDVideoCameraAuthoView.m │ └── SDVideoCameraController.m ├── SDVideoController.m ├── SDVideoConfig.h └── SDVideoConfig.m └── VideoCameraDemo.xcodeproj ├── project.xcworkspace ├── contents.xcworkspacedata ├── xcuserdata │ └── wangweidong.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata └── wangweidong.xcuserdatad ├── xcschemes └── xcschememanagement.plist └── xcdebugger └── Breakpoints_v2.xcbkptlist /README.md: -------------------------------------------------------------------------------- 1 | # SDVideoCamera 2 | 仿抖音录制 (视频录制 视频裁剪 视频合成) 3 | 4 | [简书博客地址](https://www.jianshu.com/p/309116a486cb) 5 | -------------------------------------------------------------------------------- /VideoCameraDemo/music_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/music_image.jpg -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_upload@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_upload@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_corp_add_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_corp_add_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_corp_drag_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_corp_drag_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_turn_over@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_turn_over@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_commom_exit_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_commom_exit_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_corp_cancle_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_corp_cancle_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_corp_delete_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_corp_delete_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_color_bg@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_color_bg@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_album_delete_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_album_delete_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_count_down@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_count_down@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_original_off@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_original_off@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_original_on@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_original_on@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_commom_return_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_commom_return_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_color_alpha@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_color_alpha@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_color_text@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_color_text@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_image_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_image_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_text_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_text_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_flash_light_on@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_flash_light_on@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_menu_delete_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_menu_delete_icon.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_menu_finish_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_menu_finish_icon.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_autho_open_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_autho_open_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_camera_flash_light_off@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_camera_flash_light_off@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_alignment_center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_alignment_center@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_alignment_left@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_alignment_left@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_alignment_right@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_alignment_right@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_music_more_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_music_more_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_text_delete_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_text_delete_icon@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_music_finish_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_music_finish_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_music_normal_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_music_normal_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_music_volume_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_music_volume_icon@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_music_default_image@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_music_default_image@3x.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-60.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading0@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading1@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading2@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading3@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading4@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading5@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading6@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading6@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading7@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading8@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading8@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading9@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading9@2x.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading10@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading10@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading11@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading11@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading12@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading12@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading13@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading13@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading14@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading14@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading15@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading15@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading16@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading17@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading17@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading18@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading18@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading19@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading19@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading20@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading21@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading21@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading22@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading22@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading23@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading23@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading24@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading24@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading25@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading25@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading26@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading26@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading27@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading27@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading28@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading28@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading29@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading30@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading30@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading31@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading31@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading32@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading33@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading33@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading34@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading34@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading35@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading35@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading36@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading36@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading37@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading37@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading38@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading38@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading39@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading39@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading40@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading41@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading41@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading42@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading42@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading43@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading43@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading44@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading44@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading45@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading45@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading46@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading46@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading47@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading47@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading48@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading48@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading49@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading49@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading50@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading51@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading51@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading52@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading52@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading53@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading53@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading54@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading54@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading55@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading55@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading56@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading56@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading57@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading58@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading58@2x.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_video_loading/sd_video_loading59@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_video_loading/sd_video_loading59@2x.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/LaunchLogo.imageset/LaunchLogo副本.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/LaunchLogo.imageset/LaunchLogo副本.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/冷.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/冷.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/凶.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/凶.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/哼.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/哼.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/啊.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/啊.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/晕.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/晕.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/衰.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/衰.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/酷.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/酷.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/circle_add_friend_icon.imageset/粉丝.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/circle_add_friend_icon.imageset/粉丝.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/三条线.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/三条线.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/不舒服.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/不舒服.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/什么.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/什么.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/企鹅.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/企鹅.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/便便.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/便便.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/冷酷.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/冷酷.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/又死了.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/又死了.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/发呆.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/发呆.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/受伤.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/受伤.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/吐舌头.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/吐舌头.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/吓死.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/吓死.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/呕吐.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/呕吐.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/呲牙.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/呲牙.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/呼气.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/呼气.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/喜欢.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/喜欢.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/坏笑.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/坏笑.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/大惊.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/大惊.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/大笑.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/大笑.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/大闹.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/大闹.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/天使.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/天使.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/奋斗.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/奋斗.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/好吃.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/好吃.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/尴尬.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/尴尬.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/幽灵.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/幽灵.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/开心.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/开心.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/心碎.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/心碎.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/忍者.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/忍者.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/怪物.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/怪物.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/恩_.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/恩_.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/恶魔.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/恶魔.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/惊恐.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/惊恐.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/惊悚.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/惊悚.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/惊讶.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/惊讶.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/感冒.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/感冒.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/愤怒.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/愤怒.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/懵逼.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/懵逼.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/打哈欠.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/打哈欠.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/斜眼.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/斜眼.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/无聊.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/无聊.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/星星眼.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/星星眼.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/死了.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/死了.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/汗颜.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/汗颜.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/流口水.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/流口水.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/流汗.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/流汗.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/流泪.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/流泪.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/流鼻血.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/流鼻血.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/炸弹.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/炸弹.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/点赞.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/点赞.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/爱你.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/爱你.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/爱心.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/爱心.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/犯困.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/犯困.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/猪头.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/猪头.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/献吻.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/献吻.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/生气.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/生气.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/疑问.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/疑问.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/白眼.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/白眼.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/睡着.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/睡着.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/睡醒.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/睡醒.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/瞌睡.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/瞌睡.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/笑掉大牙.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/笑掉大牙.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/笑脸.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/笑脸.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/讨厌.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/讨厌.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/调皮.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/调皮.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/贪吃.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/贪吃.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/闭嘴.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/闭嘴.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/难过.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/难过.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/面无表情.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/面无表情.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/飞吻.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/飞吻.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/饿死.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/饿死.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/骂人.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/骂人.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/骷髅.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/骷髅.png -------------------------------------------------------------------------------- /SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/鼻涕.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/SDVideoCamera/Resources/sd_preview_ expression/expression.bundle/鼻涕.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Dong+ logo _画板 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Dong+ logo _画板 1.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@3x.png -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/circle_apply_friend_icon.imageset/关注 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo/Assets.xcassets/circle_apply_friend_icon.imageset/关注 (1).png -------------------------------------------------------------------------------- /VideoCameraDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /VideoCameraDemo.xcodeproj/project.xcworkspace/xcuserdata/wangweidong.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDVideoCamera/HEAD/VideoCameraDemo.xcodeproj/project.xcworkspace/xcuserdata/wangweidong.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /VideoCameraDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/26. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewEffectModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewEffectModel.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/8. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoPreviewEffectModel.h" 10 | 11 | @implementation SDVideoPreviewEffectModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropItemListAddCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropItemListAddCell.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/27. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SDVideoCropItemListAddCell : UICollectionViewCell 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /VideoCameraDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /VideoCameraDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/26. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow * window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewTagCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewTagCell.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/5. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SDVideoPreviewTagCell : UICollectionViewCell 12 | 13 | // SDVideoPreviewTagCell 是贴纸标签的Cell 14 | 15 | @property(nonatomic,copy)NSString *imageName; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoLoadingView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoLoadingView.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/28. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SDVideoLoadingView : UIView 12 | 13 | // SDVideoLoadingView是Loading界面的视图 14 | 15 | + (void)showLoadingAction; 16 | 17 | + (void)dismissLoadingAction; 18 | 19 | @end 20 | 21 | -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/LaunchLogo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "LaunchLogo副本.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/circle_add_friend_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "粉丝.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropFrameCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropFrameCell.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/21. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoCropFrameModel.h" 11 | 12 | @interface SDVideoCropFrameCell : UICollectionViewCell 13 | 14 | // SDVideoCropFrameCell 是帧图片显示的 15 | 16 | @property(nonatomic,strong)SDVideoCropFrameModel *frameModel; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/circle_apply_friend_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "关注 (1).png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/NSString+Size.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Size.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/30. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NSString (Size) 13 | 14 | - (CGFloat)heightWithTextFont:(UIFont *)textFont andWidth:(CGFloat)width; 15 | 16 | - (CGFloat)widthWithTextFont:(UIFont *)textFont andHeight:(CGFloat)height; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropItemListCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropItemListCell.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/27. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SDVideoCropItemListCell : UICollectionViewCell 13 | 14 | @property(nonatomic,strong)AVAsset *videoAsset; 15 | @property(nonatomic,strong)UIImage *videoImage; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /VideoCameraDemo.xcodeproj/xcuserdata/wangweidong.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | VideoCameraDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/UIColor+HexStringColor.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+HexStringColor.h 3 | // ChildMusicTeacher 4 | // 5 | // Created by bnqc on 2018/12/7. 6 | // Copyright © 2018年 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (HexStringColor) 12 | 13 | // HexStringColor 是16进制颜色 14 | 15 | + (UIColor *)hexStringToColor:(NSString *)stringToConvert; 16 | 17 | + (UIColor *)hexStringToColor:(NSString *)stringToConvert alpha:(CGFloat)alpha; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/UIImage+Color.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Color.h 3 | // UIImage+Categories 4 | // 5 | // Created by lisong on 16/9/4. 6 | // Copyright © 2016年 lisong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (Color) 12 | 13 | /** 根据颜色生成纯色图片 */ 14 | + (UIImage *)imageWithColor:(UIColor *)color; 15 | 16 | /** 取图片某一像素的颜色 */ 17 | - (UIColor *)colorAtPixel:(CGPoint)point; 18 | 19 | /** 获得灰度图 */ 20 | - (UIImage *)convertToGrayImage; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropItemListView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropItemListView.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/27. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoCropDataManager.h" 11 | 12 | @interface SDVideoCropItemListView : UIView 13 | 14 | // SDVideoCropItemView 是视频媒体列表视图 15 | 16 | - (instancetype)initWithFrame:(CGRect)frame dataManager:(SDVideoCropDataManager *)dataManager; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewTextColorCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewTextColorCell.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/2. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SDVideoPreviewTextColorCell : UICollectionViewCell 12 | 13 | // SDVideoPreviewTextColorCell 是字体颜色的Cell 14 | 15 | @property(nonatomic,copy)NSString *hexColorString; 16 | @property(nonatomic,assign)BOOL isSelect; 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewMusicCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewMusicCell.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/30. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoMusicModel.h" 11 | 12 | @interface SDVideoPreviewMusicCell : UICollectionViewCell 13 | 14 | // SDVideoPreviewMusicCell 是配乐的Cell 15 | 16 | @property(nonatomic,strong)SDVideoMusicModel *dataModel; 17 | @property(nonatomic,assign)BOOL isSelect; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SDVideoCamera/Album/SDVideoAlbumCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoAlbumCell.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/19. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SDVideoAlbumCell : UICollectionViewCell 13 | 14 | // SDVideoAlbumCell是视频列表展示的Cell 15 | 16 | @property(nonatomic,strong)UIImage *bgImage; 17 | @property(nonatomic,strong)PHAsset *asset; 18 | @property(nonatomic,assign)int selectNumber; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewMusicSlider.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewMusicSlider.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/1. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SDVideoPreviewMusicSlider : UISlider 12 | 13 | @property(nonatomic,assign)BOOL isUserInterface; 14 | @property(nonatomic,strong)UIColor *valueTextColor; 15 | @property(nonatomic,strong)UIFont *valueFont; 16 | @property(nonatomic,copy)NSString *valueText; 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDAudioPlayerManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDAudioPlayerManager.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/18. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | 12 | @interface SDAudioPlayerManager : NSObject 13 | 14 | // SDAudioPlayerManager 是配音伴奏播放管理类 15 | 16 | - (instancetype)initWithConfig:(SDVideoConfig *)config; 17 | 18 | - (void)play; 19 | 20 | - (void)pause; 21 | 22 | - (void)seekToTime:(CMTime)time; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropViewController.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/19. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | #import 12 | 13 | @interface SDVideoCropViewController : UIViewController 14 | 15 | // SDVideoCropViewController 是视频裁剪的主体功能类 16 | 17 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config videoAssetArray:(NSArray *)videoAssetArray; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SDVideoCamera/SDVideoController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoController.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/18. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | #import "SDVideoCameraController.h" 12 | 13 | @interface SDVideoController : UINavigationController 14 | 15 | // SDVideoController 是仿写抖音录制一个库 16 | 17 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config; 18 | 19 | @property(nonatomic,strong)SDVideoCameraController *cameraController; 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /VideoCameraDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/26. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropFrameModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropFrameModel.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/22. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCropFrameModel.h" 10 | 11 | @implementation SDVideoCropFrameModel 12 | 13 | - (void)setStartTime:(CMTime)startTime { 14 | 15 | _startTime = startTime; 16 | 17 | // 解决某些视频不是从kCMTimeZero开始有帧图像的情况 18 | if (CMTimeCompare(startTime, kCMTimeZero) == 0) { 19 | _startTime = CMTimeMakeWithSeconds(1, 50); 20 | } 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoCameraController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCameraController.h 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | #import "SDVideoCameraMenuView.h" 12 | 13 | @interface SDVideoCameraController : UIViewController 14 | 15 | // SDVideoCameraController 是录制的控制器 16 | 17 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config; 18 | 19 | // 控制层视图,方便开发者自己定制 20 | @property(nonatomic,strong)SDVideoCameraMenuView *menuView; 21 | 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropBottomView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropBottomView.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/20. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoCropHeader.h" 11 | #import "SDVideoCropDataManager.h" 12 | 13 | @interface SDVideoCropBottomView : UIView 14 | 15 | // SDVideoCropBottomView 是合成预览底部视图 16 | 17 | - (instancetype)initWithFrame:(CGRect)frame dataManager:(SDVideoCropDataManager *)dataManager; 18 | 19 | @property(nonatomic,weak)id delegate; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoDataModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoDataModel.h 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SDVideoDataModel : NSObject 12 | 13 | // SDVideoDataModel 是分段视频的数据模型 14 | 15 | @property(nonatomic,strong)NSURL *pathURL; 16 | @property(nonatomic,assign)float duration;//时长进度 17 | @property(nonatomic,assign)float progress;//进度 18 | @property(nonatomic,assign)float durationWeight;//时长权重 19 | 20 | - (void)deleteLocalVideoFileAction; 21 | 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropFrameModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropFrameModel.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/22. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SDVideoCropFrameModel : NSObject 13 | 14 | @property(nonatomic,assign)NSInteger dataIndex; 15 | @property(nonatomic,strong)AVAsset *superAsset; 16 | @property(nonatomic,strong)UIImage *frameImage; 17 | @property(nonatomic,assign)CMTime startTime; // 在全局中起始时间 18 | @property(nonatomic,assign)CMTime duration; 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoCameraPlayButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCameraPlayButton.h 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | 12 | typedef enum : NSUInteger { 13 | PlayButtonStateNomal, 14 | PlayButtonStateTouch, 15 | PlayButtonStateMove, 16 | } PlayButtonState; 17 | 18 | @interface SDVideoCameraPlayButton : UIView 19 | 20 | - (instancetype)initWithFrame:(CGRect)frame config:(SDVideoConfig *)config; 21 | 22 | @property(nonatomic,assign)PlayButtonState buttonState; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropFrameView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropFrameView.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/22. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoCropHeader.h" 11 | #import "SDVideoCropDataManager.h" 12 | 13 | @interface SDVideoCropFrameView : UIView 14 | 15 | // SDVideoCropFrameView 是视频截取显示帧图的视图 16 | 17 | - (instancetype)initWithFrame:(CGRect)frame dataManager:(SDVideoCropDataManager *)dataManager; 18 | 19 | - (void)reloadPlayTimeRangeAction; 20 | 21 | @property(nonatomic,weak)id delegate; 22 | 23 | @end 24 | 25 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropHeader.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/24. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #ifndef SDVideoCropHeader_h 10 | #define SDVideoCropHeader_h 11 | 12 | @protocol SDVideoCropVideoDragDelegate 13 | 14 | @optional 15 | 16 | // 用户开始拖拽视频左右或进度按钮 17 | - (void)userStartChangeVideoTimeRangeAction; 18 | 19 | // 用户正在拖拽视频左右或进度按钮,数据已经同步到SDVideoCropDataManager中 20 | - (void)userChangeVideoTimeRangeAction; 21 | 22 | // 用户结束拖拽视频左右按钮或者进度按钮 23 | - (void)userEndChangeVideoTimeRangeAction; 24 | 25 | @end 26 | 27 | #endif /* SDVideoCropHeader_h */ 28 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/UIButton+EdgeInsets.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+imageTitleLayout.h 3 | // 4 | // 5 | // Created by 韩保玉 on 15/6/28. 6 | // Copyright (c) 2015年 韩保玉. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, ButtonEdgeInsetsStyle) { 12 | ButtonEdgeInsetsStyleImageLeft, 13 | ButtonEdgeInsetsStyleImageRight, 14 | ButtonEdgeInsetsStyleImageTop, 15 | ButtonEdgeInsetsStyleImageBottom 16 | }; 17 | 18 | @interface UIButton (EdgeInsets) 19 | 20 | - (void)layoutButtonWithEdgeInsetsStyle:(ButtonEdgeInsetsStyle)style imageTitlespace:(CGFloat)space; 21 | 22 | - (void)centerImageAndTitle:(CGFloat)space; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoCameraAuthoView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCameraAuthoView.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/29. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoCameraAuthoView.h" 11 | 12 | @protocol SDVideoCameraAuthoDelegate 13 | 14 | @optional 15 | 16 | /// 用户打开了所有的权限 17 | - (void)userOpenAllDerviceAuthoAction; 18 | 19 | @end 20 | 21 | @interface SDVideoCameraAuthoView : UIView 22 | 23 | // SDVideoCameraAuthoView 是相机权限展示视图 24 | 25 | @property(nonatomic,weak)id delegate; 26 | 27 | /// 检测权限状态,更改UI 28 | - (void)testAuthoStateAction; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewViewController.h 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/15. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | 12 | @interface SDVideoPreviewViewController : UIViewController 13 | 14 | // SDVideoPreviewViewController是视频预览界面的控制器,没有合成功能,只是顺序播放 15 | 16 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config 17 | playItem:(AVPlayerItem *)playItem 18 | videoAssetArray:(NSArray *)videoAssetArray 19 | playTimeRange:(CMTimeRange)playTimeRange; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoDataModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoDataModel.m 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import "SDVideoDataModel.h" 10 | 11 | @implementation SDVideoDataModel 12 | 13 | - (void)deleteLocalVideoFileAction { 14 | 15 | if (_pathURL != nil) { 16 | dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 17 | dispatch_async(global, ^{ 18 | NSFileManager *fileManager = [NSFileManager defaultManager]; 19 | [fileManager removeItemAtURL:self.pathURL error:nil]; 20 | self.pathURL = nil; 21 | }); 22 | } 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoMusicModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoMusicModel.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/30. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoMusicModel.h" 10 | 11 | @implementation SDVideoMusicModel 12 | 13 | - (instancetype)init { 14 | 15 | if (self = [super init]) { 16 | self.state = SDVideoMusicStateUnKnow; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)setMusicWebURL:(NSString *)musicWebURL { 22 | 23 | _musicWebURL = musicWebURL; 24 | self.state = SDVideoMusicStateWeb; 25 | } 26 | 27 | - (void)setMusicPathURL:(NSString *)musicPathURL { 28 | 29 | _musicPathURL = musicPathURL; 30 | self.state = SDVideoMusicStateLocal; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /SDVideoCamera/Album/SDVideoAlbumSelectCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoAlbumSelectCell.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/19. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @protocol SDVideoAlbumSelectCellDelegate 13 | 14 | @optional 15 | - (void)userDeleteVideoWithDataIndex:(NSNumber *)dataIndex; 16 | 17 | @end 18 | 19 | @interface SDVideoAlbumSelectCell : UICollectionViewCell 20 | 21 | // SDVideoAlbumSelectCell 是视频选择完成的Cell 22 | 23 | @property(nonatomic,copy)NSNumber *dataIndex; 24 | @property(nonatomic,strong)UIImage *bgImage; 25 | @property(nonatomic,strong)PHAsset *asset; 26 | 27 | @property(nonatomic,weak)id delegate; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /VideoCameraDemo.xcodeproj/xcuserdata/wangweidong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /SDVideoCamera/Album/SDVideoAlbumViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoAlbumViewController.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/19. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | 12 | @protocol SDVideoAlbumViewControllerDelegate 13 | 14 | @optional 15 | 16 | - (void)userFinishSelectWithVideoAssetArray:(NSArray *)videoAssetArray; 17 | 18 | @end 19 | 20 | 21 | @interface SDVideoAlbumViewController : UIViewController 22 | 23 | // SDVideoAlbumViewController 是相册选择的控制器 24 | 25 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config; 26 | 27 | @property(nonatomic,weak)id delegate; 28 | 29 | @property(nonatomic,assign)BOOL isFinishReturn; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewTextView.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/1. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | #import "SDVideoPreviewEffectModel.h" 12 | 13 | @protocol SDVideoPreviewTextDelegate 14 | 15 | @optional 16 | 17 | - (void)userFinishInputTextWithDataModel:(SDVideoPreviewEffectModel *)dataModel; 18 | 19 | @end 20 | 21 | @interface SDVideoPreviewTextView : UIView 22 | 23 | // SDVideoPreviewTextView 是文本输入的视图 24 | 25 | - (instancetype)initWithFrame:(CGRect)frame config:(SDVideoConfig *)config; 26 | 27 | - (void)showViewAction; 28 | 29 | - (void)dismissViewAction; 30 | 31 | @property(nonatomic,weak)id delegate; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewTagsView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewTagsView.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/5. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | #import "SDVideoPreviewEffectModel.h" 12 | 13 | @protocol SDVideoPreviewTagsDelegate 14 | 15 | @optional 16 | 17 | - (void)userFinishSelectTagWithDataModel:(SDVideoPreviewEffectModel *)dataModel; 18 | 19 | @end 20 | 21 | @interface SDVideoPreviewTagsView : UIView 22 | 23 | // SDVideoPreviewTagsView 是预览界面的贴纸视图. 24 | 25 | - (instancetype)initWithFrame:(CGRect)frame config:(SDVideoConfig *)config; 26 | 27 | - (void)showViewAction; 28 | 29 | - (void)dismissViewAction; 30 | 31 | @property(nonatomic,weak)id delegate; 32 | 33 | @end 34 | 35 | -------------------------------------------------------------------------------- /VideoCameraDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/26. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | 21 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 22 | self.window.backgroundColor = [UIColor whiteColor]; 23 | ViewController *viewController = [[ViewController alloc] init]; 24 | self.window.rootViewController = viewController; 25 | [self.window makeKeyAndVisible]; 26 | 27 | 28 | 29 | return YES; 30 | } 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropItemDeleteView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropItemDeleteView.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/27. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoCropDataManager.h" 11 | 12 | @protocol SDVideoCropItemDeleteViewDelegate 13 | 14 | @optional 15 | 16 | - (void)userDeletVideoAssetWithIndexRow:(NSInteger)indexRow; 17 | 18 | @end 19 | 20 | 21 | @interface SDVideoCropItemDeleteView : UIView 22 | 23 | // SDVideoCropItemDeleteView 是删除单个资源的视图 24 | 25 | - (instancetype)initWithFrame:(CGRect)frame dataManager:(SDVideoCropDataManager *)dataManager; 26 | 27 | @property(nonatomic,strong)UIImage *selectImage; 28 | @property(nonatomic,assign)NSInteger indexRow; 29 | @property(nonatomic,weak)id delegate; 30 | 31 | @end 32 | 33 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoMenuDataModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoMenuDataModel.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/15. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef enum : NSUInteger { 13 | VideoMenuTypesTurnOver,// 翻转按钮 14 | VideoMenuTypesFlashlight,// 闪光灯 15 | VideoMenuTypesCountDown,// 倒计时 16 | } VideoMenuType; 17 | 18 | typedef void(^ButtonActionBlock)(UIButton *sender); 19 | 20 | @interface SDVideoMenuDataModel : NSObject 21 | 22 | // SDVideoMenuDataModel 是侧边按钮数据Model 23 | 24 | @property(nonatomic,assign)VideoMenuType menuType; 25 | @property(nonatomic,copy)NSString *normalImageName; 26 | @property(nonatomic,copy)NSString *selectImageName; 27 | @property(nonatomic,copy)NSString *normalTitle; 28 | @property(nonatomic,copy)NSString *selectTitle; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewEffectModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewEffectModel.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/8. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum : NSUInteger { 12 | EffectDataTypeNone, 13 | EffectDataTypeText, 14 | EffectDataTypeImage, 15 | } EffectDataType; 16 | 17 | @interface SDVideoPreviewEffectModel : NSObject 18 | 19 | // SDVideoPreviewEffectModel 是特效的Model,包括文字和图片 20 | 21 | @property(nonatomic,assign)EffectDataType type; 22 | 23 | @property(nonatomic,copy)NSString *text; 24 | 25 | @property(nonatomic,strong)UIFont *textFont; 26 | 27 | @property(nonatomic,assign)CGFloat textFontSize; 28 | 29 | @property(nonatomic,strong)UIColor *textColor; 30 | 31 | @property(nonatomic,strong)UIColor *backgroundColor; 32 | 33 | @property(nonatomic,strong)UIImage *image; 34 | 35 | @property(nonatomic,assign)CGSize contentSize; 36 | 37 | @end 38 | 39 | -------------------------------------------------------------------------------- /SDVideoCamera/SDVideoController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoController.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/18. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoController.h" 10 | 11 | @implementation SDVideoController 12 | 13 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config { 14 | 15 | if (config.returnViewController == nil) { 16 | NSString *exceptionContent = [NSString stringWithFormat:@"需要设置根控制器,以便于dismiss使用"]; 17 | @throw [NSException exceptionWithName:@"returnViewController has not Setting" reason:exceptionContent userInfo:nil]; 18 | } 19 | 20 | SDVideoCameraController *cameraController = [[SDVideoCameraController alloc] initWithCameraConfig:config]; 21 | if (self = [super initWithRootViewController:cameraController]) { 22 | self.cameraController = cameraController; 23 | self.modalPresentationStyle = UIModalPresentationFullScreen; 24 | } 25 | return self; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoMusicModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoMusicModel.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/30. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum : NSUInteger { 12 | SDVideoMusicStateUnKnow, 13 | SDVideoMusicStateWeb, // 数据网络化 14 | SDVideoMusicStateDownLoad, // 数据正在下载 15 | SDVideoMusicStateLocal, //数据已本地化 16 | } SDVideoMusicState; 17 | 18 | @interface SDVideoMusicModel : NSObject 19 | 20 | // SDVideoMusicModel 是配乐的Model 21 | 22 | @property(nonatomic,assign)SDVideoMusicState state; 23 | @property(nonatomic,copy)NSString *musicTitle; 24 | @property(nonatomic,copy)NSString *musicImageName; // 本地封面图的地址 25 | @property(nonatomic,copy)NSString *musicImageURL; // 网络封面图片的地址 26 | @property(nonatomic,copy)NSString *musicPathURL; // 本地资源的地址 27 | @property(nonatomic,copy)NSString *musicWebURL; // 网络资源的地址,设置后会转化为musicPathURL 28 | @property(nonatomic,copy)NSData *musicImageData; // 从网络缓存的图片数据 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewMusicView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewMusicView.h 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/30. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoConfig.h" 11 | 12 | @class SDVideoMusicModel; 13 | 14 | @protocol SDVideoMusicDelegate 15 | 16 | @optional 17 | 18 | - (void)userSelectbackgroundMusicWithDataModel:(SDVideoMusicModel *)dataModel musicVolume:(CGFloat)musicVolume; 19 | 20 | - (void)userChangeOriginalVolume:(CGFloat)originalVolume musicVolume:(CGFloat)musicVolume; 21 | 22 | @end 23 | 24 | 25 | @interface SDVideoPreviewMusicView : UIView 26 | 27 | // SDVideoPreviewMusicView 是配乐选择的视图 28 | 29 | - (instancetype)initWithFrame:(CGRect)frame config:(SDVideoConfig *)config superViewController:(UIViewController *)superViewController; 30 | 31 | - (void)showViewAction; 32 | 33 | - (void)dismissViewAction; 34 | 35 | @property(nonatomic,weak)id delegate; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoCaptureManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCaptureManager.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/15. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "SDVideoConfig.h" 12 | 13 | @interface SDVideoCaptureManager : NSObject 14 | 15 | // SDVideoCaptureManager 是摄像头硬件管理类 16 | 17 | - (instancetype)initWithVideoView:(UIView *)videoView config:(SDVideoConfig *)config; 18 | 19 | /// 检测麦克风是否已经打开 20 | + (AVAuthorizationStatus)isOpenMicrophoneAuthStatus; 21 | 22 | /// 检测摄像头是否已经打开 23 | + (AVAuthorizationStatus)isOpenCameraAuthStatus; 24 | 25 | /// 开始录制视频 26 | - (void)startVideoRecordingAction; 27 | 28 | /// 暂停(或停止)录制视频 29 | - (void)pauseOrStopVideoRecordingAction; 30 | 31 | /// 翻转摄像头 32 | - (void)exchangeCameraInputAction; 33 | 34 | /// 打开闪光灯 35 | - (void)openCameraFlashLight; 36 | 37 | /// 设置相机焦距 38 | - (void)setVideoZoomFactorWithScale:(CGFloat)scale orientation:(TouchMoveOrientation)orientation; 39 | 40 | /// 重新设定相机的当前焦距边界值 41 | - (void)reloadCurrentVideoZoomFactorAction; 42 | 43 | @end 44 | 45 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoDataManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoDataManager.h 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoCameraHeader.h" 11 | #import "SDVideoDataModel.h" 12 | #import "SDVideoConfig.h" 13 | 14 | @interface SDVideoDataManager : NSObject 15 | 16 | // SDVideoDataManager 是视频数据管理单例类 17 | 18 | + (SDVideoDataManager *)defaultManager; 19 | 20 | @property(nonatomic,strong)SDVideoConfig *config; // 用户的配置项 21 | @property(nonatomic,assign)VideoCameraState cameraState;//相机的状态 22 | @property(nonatomic,assign,readonly)float videoSecondTime;//最大录制时长,根据用户配置项获得 23 | @property(nonatomic,assign)float totalVideoTime; //录制的总计时长 24 | @property(nonatomic,assign)float progress; //进度 25 | @property(nonatomic,assign)NSInteger videoNumber; //视频的个数,没法直接监听数组元素的变化 26 | @property(nonatomic,strong,readonly)NSMutableArray *videoDataArray; 27 | 28 | /// 添加一条新的分段视频 29 | - (void)addVideoModel:(SDVideoDataModel *)videoModel; 30 | 31 | /// 删除最后的分段视频 32 | - (void)deleteLastVideoModel; 33 | 34 | /// 删除所有的分段视频 35 | - (void)deleteAllVideoModel; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewTagCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewTagCell.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/5. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoPreviewTagCell.h" 10 | #import "UIView+Extension.h" 11 | 12 | @interface SDVideoPreviewTagCell () 13 | 14 | @property(nonatomic,strong)UIImageView *imageView; 15 | 16 | @end 17 | 18 | @implementation SDVideoPreviewTagCell 19 | 20 | - (instancetype)initWithFrame:(CGRect)frame { 21 | 22 | if (self = [super initWithFrame:frame]) { 23 | [self addSubview:self.imageView]; 24 | } 25 | return self; 26 | } 27 | 28 | - (UIImageView *)imageView { 29 | 30 | if (_imageView == nil) { 31 | _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.width * 0.8, self.height * 0.8)]; 32 | _imageView.center = CGPointMake(self.width/2.0, self.height/2.0); 33 | _imageView.contentMode = UIViewContentModeCenter; 34 | } 35 | return _imageView; 36 | } 37 | 38 | - (void)setImageName:(NSString *)imageName { 39 | 40 | _imageName = imageName; 41 | self.imageView.image = [UIImage imageNamed:imageName]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropFrameCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropFrameCell.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/21. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCropFrameCell.h" 10 | 11 | @interface SDVideoCropFrameCell () 12 | 13 | @property(nonatomic,strong)UIImageView *bgImageView; 14 | 15 | @end 16 | 17 | @implementation SDVideoCropFrameCell 18 | 19 | - (instancetype)initWithFrame:(CGRect)frame { 20 | 21 | if (self = [super initWithFrame:frame]) { 22 | self.backgroundColor = [UIColor blackColor]; 23 | [self addSubview:self.bgImageView]; 24 | } 25 | return self; 26 | } 27 | 28 | - (UIImageView *)bgImageView { 29 | 30 | if (_bgImageView == nil) { 31 | _bgImageView = [[UIImageView alloc] initWithFrame:self.bounds]; 32 | _bgImageView.contentMode = UIViewContentModeScaleAspectFill; 33 | _bgImageView.clipsToBounds = YES; 34 | } 35 | return _bgImageView; 36 | } 37 | 38 | - (void)setFrameModel:(SDVideoCropFrameModel *)frameModel { 39 | 40 | _frameModel = frameModel; 41 | _bgImageView.frame = self.bounds; 42 | self.bgImageView.image = frameModel.frameImage; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoMenuDataModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoMenuDataModel.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/15. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoMenuDataModel.h" 10 | 11 | @implementation SDVideoMenuDataModel 12 | 13 | - (void)setMenuType:(VideoMenuType)menuType { 14 | 15 | _menuType = menuType; 16 | 17 | NSArray *normalImageNameArray = @[@"sd_camera_turn_over", 18 | @"sd_camera_flash_light_off", 19 | @"sd_camera_count_down", 20 | @"sd_camera_original_off"]; 21 | NSArray *selectImageNameArray = @[@"sd_camera_turn_over", 22 | @"sd_camera_flash_light_on", 23 | @"sd_camera_count_down", 24 | @"sd_camera_original_on"]; 25 | NSArray *normalTitleArray = @[@"翻转",@"闪光灯",@"倒计时",@"关闭原声"]; 26 | NSArray *selectTitleArray = @[@"翻转",@"闪光灯",@"倒计时",@"打开原声"]; 27 | 28 | self.normalImageName = normalImageNameArray[menuType]; 29 | self.selectImageName = selectImageNameArray[menuType]; 30 | self.normalTitle = normalTitleArray[menuType]; 31 | self.selectTitle = selectTitleArray[menuType]; 32 | } 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/NSString+Size.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Size.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/30. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "NSString+Size.h" 10 | 11 | @implementation NSString (Size) 12 | 13 | - (CGFloat)heightWithTextFont:(UIFont *)textFont andWidth:(CGFloat)width { 14 | 15 | return [self textSizeWithTextFont:textFont width:width height:0].width; 16 | } 17 | 18 | - (CGFloat)widthWithTextFont:(UIFont *)textFont andHeight:(CGFloat)height { 19 | 20 | return [self textSizeWithTextFont:textFont width:0 height:height].height; 21 | } 22 | 23 | - (CGSize)textSizeWithTextFont:(UIFont *)textFont width:(float)width height:(float)height { 24 | 25 | int nowWidth = 0; 26 | int nowHeight = 0; 27 | if (width != 0) { 28 | nowWidth =width; 29 | }else{ 30 | nowWidth =CGFLOAT_MAX; 31 | } 32 | if (height != 0) { 33 | nowHeight =height; 34 | }else{ 35 | nowHeight =CGFLOAT_MAX; 36 | } 37 | if (textFont == nil) { 38 | textFont = [UIFont systemFontOfSize:14]; 39 | } 40 | CGSize newSizeToFit = [self boundingRectWithSize:CGSizeMake(nowWidth,nowHeight) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : textFont} context:nil].size; 41 | return newSizeToFit; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoCameraMenuView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCameraMenuView.h 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDVideoCameraHeader.h" 11 | #import "SDVideoConfig.h" 12 | 13 | @protocol SDVideoCameraMenuDelegate 14 | 15 | @optional 16 | 17 | // 用户把视频合并完成,需要跳转下一个界面了 18 | - (void)userFinishMergeVideoAction; 19 | 20 | // 用户改变摄像头的变焦程度 21 | - (void)userChangeVideoZoomFactorWithScale:(CGFloat)scale orientation:(TouchMoveOrientation)orientation; 22 | 23 | // 用户停止改变摄像头的变焦程度(结束拖拽时) 24 | - (void)userEndChangeVideoZoomFactor; 25 | 26 | // 回删某个分段视频 27 | - (void)deleteLaseVideoDataAction; 28 | 29 | // 用户点击菜单按钮 30 | - (void)userClickOutMenuButtonWithButtonType:(VideoMenuType)menuType; 31 | 32 | // 用户点击展示相册事件 33 | - (void)userClickAlbumAction; 34 | 35 | // 用户打开了所有设备权限回调 36 | - (void)userOpenAllDerviceAuthoAction; 37 | 38 | @end 39 | 40 | @interface SDVideoCameraMenuView : UIView 41 | 42 | // SDVideoCameraMenuView 是视频录制界面控制层视图 43 | 44 | - (instancetype)initWithFrame:(CGRect)frame cameraConfig:(SDVideoConfig *)config; 45 | 46 | @property(nonatomic,weak)id delegate; 47 | 48 | @property(nonatomic,weak)UIViewController *superViewController; 49 | 50 | @property(nonatomic,strong)UIButton *closeButton; 51 | 52 | - (BOOL)isOpenAllDeviceAuthoStateAction; 53 | 54 | @end 55 | 56 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropItemListAddCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropItemListAddCell.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/27. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCropItemListAddCell.h" 10 | #import "UIView+Extension.h" 11 | 12 | @interface SDVideoCropItemListAddCell () 13 | 14 | @property(nonatomic,strong)UIImageView *frameImageView; 15 | 16 | @end 17 | 18 | @implementation SDVideoCropItemListAddCell 19 | 20 | - (instancetype)initWithFrame:(CGRect)frame { 21 | 22 | if (self = [super initWithFrame:frame]) { 23 | [self addSubview:self.frameImageView]; 24 | } 25 | return self; 26 | } 27 | 28 | -(UIImageView *)frameImageView { 29 | 30 | if (_frameImageView == nil) { 31 | CGFloat frameImageHeight = self.height > 60 ? 60.0f : self.height * 0.8; 32 | _frameImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frameImageHeight, frameImageHeight)]; 33 | _frameImageView.image = [UIImage imageNamed:@"sd_corp_add_icon"]; 34 | _frameImageView.center = CGPointMake(self.width/2.0, self.height/2.0); 35 | _frameImageView.contentMode = UIViewContentModeScaleAspectFill; 36 | _frameImageView.layer.cornerRadius = 3.0f; 37 | _frameImageView.layer.masksToBounds = YES; 38 | _frameImageView.clipsToBounds = YES; 39 | } 40 | return _frameImageView; 41 | } 42 | 43 | 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoCameraHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCameraHeader.h 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #ifndef SDVideoCameraHeader_h 10 | #define SDVideoCameraHeader_h 11 | 12 | #import "UIView+Extension.h" 13 | #import "UIColor+HexStringColor.h" 14 | 15 | typedef enum : NSUInteger { 16 | VideoCameraStateIdle,//空闲状态 17 | VideoCameraStateInProgress,//录制状态 18 | VideoCameraStatePause,//暂停状态 19 | VideoCameraStateStop,//停止状态 20 | } VideoCameraState; 21 | 22 | typedef enum : NSUInteger { 23 | VideoFilePathTypeCachesPath,// 获取Library/Caches目录 24 | VideoFilePathTypeTmpPath,// 获取tmp目录 25 | VideoFilePathTypeDocumentsPath,// 获取Documents目录 26 | VideoFilePathTypeLibraryPath,// 获取Library目录 27 | VideoFilePathTypePreferencesPath,// 获取Library/Preferences目录 28 | } VideoFilePathType; 29 | 30 | typedef enum : NSUInteger { 31 | TouchMoveOrientationUp, 32 | TouchMoveOrientationDown, 33 | } TouchMoveOrientation; 34 | 35 | 36 | #define KNoSafeHeight [UIScreen mainScreen].bounds.size.height 37 | #define StatusHeight ((KNoSafeHeight == 812 || KNoSafeHeight == 896) ? 44.0f : 20.0f) 38 | #define KmainHeight ((KNoSafeHeight == 812 || KNoSafeHeight == 896) ? (KNoSafeHeight - 34) : KNoSafeHeight ) 39 | #define KmainWidth [UIScreen mainScreen].bounds.size.width 40 | #define NavigationBarHeight (44.0f) 41 | 42 | #endif /* SDVideoCameraHeader_h */ 43 | -------------------------------------------------------------------------------- /VideoCameraDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDAudioPlayerManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDAudioPlayerManager.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/18. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDAudioPlayerManager.h" 10 | #import 11 | 12 | @interface SDAudioPlayerManager () 13 | 14 | @property(nonatomic,strong)SDVideoConfig *config; 15 | @property(nonatomic,strong)AVPlayer *audioPlayer; 16 | 17 | @end 18 | 19 | @implementation SDAudioPlayerManager 20 | 21 | - (instancetype)initWithConfig:(SDVideoConfig *)config { 22 | 23 | if (self = [super init]) { 24 | self.config = config; 25 | if (config.audioURL != nil) { 26 | if (@available(iOS 10.0, *)) { 27 | self.audioPlayer.automaticallyWaitsToMinimizeStalling = NO; 28 | } 29 | [self.audioPlayer seekToTime:CMTimeMake(1.0, 1.0) completionHandler:^(BOOL finished) {}]; 30 | } 31 | } 32 | return self; 33 | } 34 | 35 | - (AVPlayer *)audioPlayer { 36 | 37 | if (_audioPlayer == nil) { 38 | NSURL *audioURL = self.config.audioURLType == AudioURLTypeWeb ? [NSURL URLWithString:self.config.audioURL] : [NSURL fileURLWithPath:self.config.audioURL]; 39 | AVPlayerItem *audioItem = [[AVPlayerItem alloc] initWithURL:audioURL]; 40 | _audioPlayer = [[AVPlayer alloc] initWithPlayerItem:audioItem]; 41 | } 42 | return _audioPlayer; 43 | } 44 | 45 | - (void)play { 46 | 47 | [_audioPlayer play]; 48 | } 49 | 50 | - (void)pause { 51 | 52 | [_audioPlayer pause]; 53 | } 54 | 55 | - (void)seekToTime:(CMTime)time { 56 | 57 | [_audioPlayer seekToTime:time]; 58 | } 59 | 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /VideoCameraDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UILaunchStoryboardName 6 | LaunchScreen 7 | NSCameraUsageDescription 8 | 该项目想访问你的摄像头 9 | NSMicrophoneUsageDescription 10 | 该项目想访问你的麦克风 11 | NSPhotoLibraryUsageDescription 12 | 该项目想访问你的相册 13 | CFBundleDevelopmentRegion 14 | $(DEVELOPMENT_LANGUAGE) 15 | CFBundleExecutable 16 | $(EXECUTABLE_NAME) 17 | CFBundleIdentifier 18 | $(PRODUCT_BUNDLE_IDENTIFIER) 19 | CFBundleInfoDictionaryVersion 20 | 6.0 21 | CFBundleName 22 | SD相机 23 | CFBundlePackageType 24 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 25 | CFBundleShortVersionString 26 | 1.0 27 | CFBundleVersion 28 | 1 29 | LSRequiresIPhoneOS 30 | 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/UIView+Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.h 3 | // SmartLock 4 | // 5 | // Created by 江欣华 on 2016/10/25. 6 | // Copyright © 2016年 工程锁. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Extension) 12 | 13 | /** 起点x坐标 */ 14 | @property (nonatomic,assign)CGFloat x; 15 | /** 起点y坐标 */ 16 | @property (nonatomic,assign)CGFloat y; 17 | /** 中心点x坐标 */ 18 | @property (nonatomic,assign)CGFloat centerX; 19 | /** 中心点y坐标 */ 20 | @property (nonatomic,assign)CGFloat centerY; 21 | /** 宽度 */ 22 | @property (nonatomic,assign)CGFloat width; 23 | /** 高度 */ 24 | @property (nonatomic,assign)CGFloat height; 25 | /** 顶部 */ 26 | @property (nonatomic,assign)CGFloat top; 27 | /** 底部 */ 28 | @property (nonatomic,assign)CGFloat bottom; 29 | /** 左边 */ 30 | @property (nonatomic,assign)CGFloat left; 31 | /** 右边 */ 32 | @property (nonatomic,assign)CGFloat right; 33 | /** size */ 34 | @property (nonatomic,assign)CGSize size; 35 | /** origin */ 36 | @property (nonatomic,assign)CGPoint origin; 37 | 38 | /** 设置圆角 */ 39 | - (void)rounded:(CGFloat)cornerRadius; 40 | 41 | /** 设置圆角和边框 */ 42 | - (void)rounded:(CGFloat)cornerRadius width:(CGFloat)borderWidth color:(UIColor *)borderColor; 43 | 44 | /** 设置边框 */ 45 | - (void)border:(CGFloat)borderWidth color:(UIColor *)borderColor; 46 | 47 | /** 给哪几个角设置圆角 */ 48 | - (void)round:(CGFloat)cornerRadius RectCorners:(UIRectCorner)rectCorner; 49 | 50 | /** 设置阴影 */ 51 | - (void)shadow:(UIColor *)shadowColor opacity:(CGFloat)opacity radius:(CGFloat)radius offset:(CGSize)offset; 52 | 53 | - (UIViewController *)viewController; 54 | 55 | + (CGFloat)getLabelHeightByWidth:(CGFloat)width Title:(NSString *)title font:(UIFont *)font; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewTextColorCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewTextColorCell.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/2. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoPreviewTextColorCell.h" 10 | #import "UIColor+HexStringColor.h" 11 | #import "UIView+Extension.h" 12 | 13 | @interface SDVideoPreviewTextColorCell () 14 | 15 | @property(nonatomic,strong)UIView *colorView; 16 | 17 | @end 18 | 19 | @implementation SDVideoPreviewTextColorCell 20 | 21 | - (instancetype)initWithFrame:(CGRect)frame { 22 | 23 | if (self = [super initWithFrame:frame]) { 24 | [self addSubview:self.colorView]; 25 | } 26 | return self; 27 | } 28 | 29 | - (UIView *)colorView { 30 | 31 | if (_colorView == nil) { 32 | _colorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.width/2.0, self.width/2.0)]; 33 | _colorView.center = CGPointMake(self.width/2.0, self.width/2.0); 34 | _colorView.layer.borderColor = [UIColor whiteColor].CGColor; 35 | _colorView.layer.cornerRadius = _colorView.width/2.0; 36 | _colorView.layer.masksToBounds = YES; 37 | _colorView.layer.borderWidth = 2.0f; 38 | } 39 | return _colorView; 40 | } 41 | 42 | - (void)setHexColorString:(NSString *)hexColorString { 43 | 44 | _hexColorString = hexColorString; 45 | _colorView.backgroundColor = [UIColor hexStringToColor:hexColorString]; 46 | } 47 | 48 | - (void)setIsSelect:(BOOL)isSelect { 49 | 50 | _isSelect = isSelect; 51 | if (isSelect) { 52 | _colorView.size = CGSizeMake(self.width * 0.6, self.width * 0.6); 53 | _colorView.layer.cornerRadius = _colorView.width/2.0; 54 | } else { 55 | _colorView.size = CGSizeMake(self.width/2.0, self.width/2.0); 56 | _colorView.layer.cornerRadius = _colorView.width/2.0; 57 | } 58 | _colorView.center = CGPointMake(self.width/2.0, self.width/2.0); 59 | } 60 | 61 | @end 62 | 63 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/UIColor+HexStringColor.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+HexStringColor.m 3 | // ChildMusicTeacher 4 | // 5 | // Created by bnqc on 2018/12/7. 6 | // Copyright © 2018年 Dong. All rights reserved. 7 | // 8 | 9 | #import "UIColor+HexStringColor.h" 10 | 11 | @implementation UIColor (HexStringColor) 12 | 13 | + (UIColor *)hexAlphaStringToColor:(NSString *)stringToConvert alpha:(CGFloat)alpha { 14 | NSString *cString = [[stringToConvert 15 | stringByTrimmingCharactersInSet: 16 | [NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 17 | // String should be 6 or 8 characters 18 | if ([cString length] < 6) 19 | return [UIColor blackColor]; 20 | // strip 0X if it appears 21 | if ([cString hasPrefix:@"0X"]) 22 | cString = [cString substringFromIndex:2]; 23 | if ([cString hasPrefix:@"#"]) 24 | cString = [cString substringFromIndex:1]; 25 | if ([cString length] != 6) 26 | return [UIColor blackColor]; 27 | // Separate into r, g, b substrings 28 | NSRange range; 29 | range.location = 0; 30 | range.length = 2; 31 | NSString *rString = [cString substringWithRange:range]; 32 | range.location = 2; 33 | NSString *gString = [cString substringWithRange:range]; 34 | range.location = 4; 35 | NSString *bString = [cString substringWithRange:range]; 36 | // Scan values 37 | unsigned int r, g, b; 38 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 39 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 40 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 41 | return [UIColor colorWithRed:((float)r / 255.0f) 42 | green:((float)g / 255.0f) 43 | blue:((float)b / 255.0f) 44 | alpha:alpha]; 45 | } 46 | 47 | + (UIColor *)hexStringToColor:(NSString *)stringToConvert { 48 | return [UIColor hexAlphaStringToColor:stringToConvert alpha:1.0f]; 49 | } 50 | 51 | + (UIColor *)hexStringToColor:(NSString *)stringToConvert alpha:(CGFloat)alpha { 52 | return [UIColor hexAlphaStringToColor:stringToConvert alpha:alpha]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropItemListCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropItemListCell.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/27. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCropItemListCell.h" 10 | #import "UIView+Extension.h" 11 | 12 | @interface SDVideoCropItemListCell () 13 | 14 | @property(nonatomic,strong)UIImageView *frameImageView; 15 | @property(nonatomic,strong)UILabel *timeLabel; 16 | 17 | @end 18 | 19 | @implementation SDVideoCropItemListCell 20 | 21 | - (instancetype)initWithFrame:(CGRect)frame { 22 | 23 | if (self = [super initWithFrame:frame]) { 24 | [self addSubview:self.frameImageView]; 25 | } 26 | return self; 27 | } 28 | 29 | -(UIImageView *)frameImageView { 30 | 31 | if (_frameImageView == nil) { 32 | CGFloat frameImageHeight = self.height > 60 ? 60.0f : self.height * 0.8; 33 | _frameImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frameImageHeight, frameImageHeight)]; 34 | _frameImageView.center = CGPointMake(self.width/2.0, self.height/2.0); 35 | _frameImageView.contentMode = UIViewContentModeScaleAspectFill; 36 | _frameImageView.layer.cornerRadius = 3.0f; 37 | _frameImageView.layer.masksToBounds = YES; 38 | _frameImageView.clipsToBounds = YES; 39 | [_frameImageView addSubview:self.timeLabel]; 40 | } 41 | return _frameImageView; 42 | } 43 | 44 | - (UILabel *)timeLabel { 45 | 46 | if (_timeLabel == nil) { 47 | _timeLabel = [[UILabel alloc] initWithFrame:self.frameImageView.bounds]; 48 | _timeLabel.font = [UIFont boldSystemFontOfSize:12]; 49 | _timeLabel.textAlignment = NSTextAlignmentCenter; 50 | _timeLabel.textColor = [UIColor whiteColor]; 51 | } 52 | return _timeLabel; 53 | } 54 | 55 | - (void)setVideoAsset:(AVAsset *)videoAsset { 56 | 57 | _videoAsset = videoAsset; 58 | self.timeLabel.text = [NSString stringWithFormat:@"%.1fs",CMTimeGetSeconds(videoAsset.duration)]; 59 | } 60 | 61 | - (void)setVideoImage:(UIImage *)videoImage { 62 | 63 | _videoImage = videoImage; 64 | self.frameImageView.image = videoImage; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /VideoCameraDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/26. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "SDVideoController.h" 11 | 12 | @interface ViewController () 13 | 14 | @property(nonatomic,strong)UIButton *button; 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | 22 | [super viewDidLoad]; 23 | self.button = [[UIButton alloc] initWithFrame:CGRectMake(10, 200, self.view.width - 20, 40)]; 24 | self.button.backgroundColor = [UIColor orangeColor]; 25 | self.button.layer.cornerRadius = 4.0f; 26 | self.button.layer.masksToBounds = YES; 27 | [self.button setTitle:@"弹出SDVideoCamera" forState:UIControlStateNormal]; 28 | [self.button addTarget:self action:@selector(presentSDVideoCameraAction) forControlEvents:UIControlEventTouchUpInside]; 29 | [self.view addSubview:self.button]; 30 | } 31 | 32 | - (void)presentSDVideoCameraAction { 33 | 34 | SDVideoConfig *config = [[SDVideoConfig alloc] init]; 35 | config.returnViewController = self; 36 | config.returnBlock = ^(NSString *mergeVideoPathString) { 37 | NSLog(@"合成路径 %@",mergeVideoPathString); 38 | }; 39 | 40 | SDVideoMusicModel *musicModel = [[SDVideoMusicModel alloc] init]; 41 | musicModel.musicTitle = @"你是人间四月天"; 42 | musicModel.musicImageName = @"music_image.jpg"; 43 | musicModel.musicWebURL = @"https://zhike-oss.oss-cn-beijing.aliyuncs.com/tmp/test_music.mp3"; 44 | 45 | SDVideoMusicModel *otherMusicModel = [[SDVideoMusicModel alloc] init]; 46 | otherMusicModel.musicTitle = @"郊外静音"; 47 | otherMusicModel.musicImageName = @"music_image.jpg"; 48 | otherMusicModel.musicWebURL = @"https://zhike-oss.oss-cn-beijing.aliyuncs.com/tmp/test_music2.mp3"; 49 | 50 | config.recommendMusicList = @[musicModel,otherMusicModel]; 51 | 52 | config.previewTagImageNameArray = @[@"circle_add_friend_icon",@"circle_apply_friend_icon"]; 53 | 54 | SDVideoController *videoController = [[SDVideoController alloc] initWithCameraConfig:config]; 55 | [self presentViewController:videoController animated:YES completion:nil]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoCropDataManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropDataManager.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/24. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "SDVideoConfig.h" 12 | 13 | 14 | // 用户添加视频媒体的通知 15 | #define VideoArrayItemAddNotificationName @"VideoArrayItemAddNotificationName" 16 | 17 | // 用户删除视频的下标位置的通知 18 | #define VideoArrayItemDeleteIndexNotificationName @"VideoArrayItemDeleteIndexNotificationName" 19 | 20 | // 用户交换视频的下标位置的通知 21 | #define VideoArrayItemExchangeIndexNotificationName @"VideoArrayItemExchangeIndexNotificationName" 22 | 23 | // 播放媒体改变的通知 24 | #define VideoPlayItemChangeNotificationName @"VideoPlayItemChangeNotificationName" 25 | 26 | @interface SDVideoCropDataManager : NSObject 27 | 28 | // SDVideoCropDataManager 是视频截取模块数据管理的类 29 | // 由于视频解决模块视图层级可能很多,所以在数据传递上有着一定的问题,或者传递混乱,这时候就需要这个数据管理类来共同管理公用数据 30 | // 其他模块通过get方式或者KVO的形式来监听数据的变化 31 | 32 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config; 33 | 34 | /// 用户配置项 35 | @property(nonatomic,strong)SDVideoConfig *config; 36 | 37 | /// 所在控制器 38 | @property(nonatomic,weak)UIViewController *superViewController; 39 | 40 | /// 视频数组 41 | @property(nonatomic,strong,readonly)NSMutableArray *videoArray; 42 | 43 | /// 播放的媒体Item 44 | @property(nonatomic,copy)AVPlayerItem *playItem; 45 | 46 | /// 媒体的总播放区间 47 | @property(nonatomic,assign)CMTimeRange playTotalTimeRange; 48 | 49 | /// 播放的区间 50 | @property(nonatomic,assign)CMTimeRange playTimeRange; 51 | 52 | /// 最小的时长,默认为1s 53 | @property(nonatomic,assign)CMTime minDuration; 54 | 55 | /// 每过多少秒监听移除播放时间.默认为0.1s 56 | @property(nonatomic,assign,readonly)CMTime observerTimeSpace; 57 | 58 | /// 当前播放时间 59 | @property(nonatomic,assign)CMTime currentPlayTime; 60 | 61 | /// 添加视频资源 62 | - (void)videoArrayAddVideoAsset:(AVAsset *)videoAsset; 63 | 64 | /// 添加一组视频资源 65 | - (void)videoArrayAddVideoAssetArray:(NSArray *)videoAssetArray; 66 | 67 | /// 删除某个视频资源 68 | - (void)videoArrayDeleteVideoWithDataIndex:(NSInteger)dataIndex; 69 | 70 | /// 对某两个视频资源对换位置 71 | - (void)videoArrayChangeIndexWithFirstIndex:(NSInteger)firstIndex secondIndex:(NSInteger)secondIndex; 72 | 73 | @end 74 | 75 | -------------------------------------------------------------------------------- /VideoCameraDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-Spotlight-40.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "Icon-60.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "Icon-Small@2x.png", 17 | "idiom" : "iphone", 18 | "scale" : "2x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "Icon-Small@3x.png", 23 | "idiom" : "iphone", 24 | "scale" : "3x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "Icon-Spotlight-40@2x.png", 29 | "idiom" : "iphone", 30 | "scale" : "2x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "filename" : "Icon-Spotlight-40@3x.png", 35 | "idiom" : "iphone", 36 | "scale" : "3x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "Icon-60@2x.png", 41 | "idiom" : "iphone", 42 | "scale" : "2x", 43 | "size" : "60x60" 44 | }, 45 | { 46 | "filename" : "Icon-60@3x.png", 47 | "idiom" : "iphone", 48 | "scale" : "3x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "idiom" : "ipad", 53 | "scale" : "1x", 54 | "size" : "20x20" 55 | }, 56 | { 57 | "idiom" : "ipad", 58 | "scale" : "2x", 59 | "size" : "20x20" 60 | }, 61 | { 62 | "idiom" : "ipad", 63 | "scale" : "1x", 64 | "size" : "29x29" 65 | }, 66 | { 67 | "idiom" : "ipad", 68 | "scale" : "2x", 69 | "size" : "29x29" 70 | }, 71 | { 72 | "idiom" : "ipad", 73 | "scale" : "1x", 74 | "size" : "40x40" 75 | }, 76 | { 77 | "idiom" : "ipad", 78 | "scale" : "2x", 79 | "size" : "40x40" 80 | }, 81 | { 82 | "idiom" : "ipad", 83 | "scale" : "1x", 84 | "size" : "76x76" 85 | }, 86 | { 87 | "idiom" : "ipad", 88 | "scale" : "2x", 89 | "size" : "76x76" 90 | }, 91 | { 92 | "idiom" : "ipad", 93 | "scale" : "2x", 94 | "size" : "83.5x83.5" 95 | }, 96 | { 97 | "filename" : "Dong+ logo _画板 1.png", 98 | "idiom" : "ios-marketing", 99 | "scale" : "1x", 100 | "size" : "1024x1024" 101 | } 102 | ], 103 | "info" : { 104 | "author" : "xcode", 105 | "version" : 1 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoUtils.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/14. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "SDVideoCameraHeader.h" 12 | #import "SDVideoDataModel.h" 13 | 14 | // 视频尺寸 15 | #define SDVideoSize (CGSizeMake(1080, 1920)) 16 | 17 | @interface SDVideoUtils : NSObject 18 | 19 | // SDVideoUtils 是视频工具类 20 | 21 | 22 | /// 合成录制视频,返回播放单体.(主要用于播放,合成时间短) 23 | /// @param assetArray 媒体数组 24 | /// @param timeRange 选择时间区间,如果想选择全部,请使用 kCMTimeRangeZero 25 | /// @param bgAudioAsset 伴奏音乐 26 | /// @param originalVolume 视频音量(0 ~ 1) 27 | /// @param bgAudioVolume 背景音频音量(0 ~ 1) 28 | + (AVPlayerItem *)mergeMediaPlayerItemActionWithAssetArray:(NSArray *)assetArray 29 | timeRange:(CMTimeRange)timeRange 30 | bgAudioAsset:(AVAsset *)bgAudioAsset 31 | originalVolume:(float)originalVolume 32 | bgAudioVolume:(float)bgAudioVolume; 33 | 34 | 35 | /// 合成录制视频,返回合成路径 36 | /// @param assetArray 合成资源数组 37 | /// @param bgAudioAsset 背景音乐合成资源 38 | /// @param timeRange 选择时间区间,如果想选择全部,请使用 kCMTimeRangeZero 39 | /// @param originalVolume 视频音量(0 ~ 1) 40 | /// @param bgAudioVolume 背景音频音量(0 ~ 1) 41 | /// @param layerArray 贴纸图层数组 42 | /// @param mergeFilePath 合成媒体文件路径,默认在NSCachesDirectory路径下 43 | /// @param mergeFileName 合成媒体文件名称,默认为"SD_" + "时间戳_" + 0~999随机数 + ".mov" 44 | + (NSString *)mergeMediaActionWithAssetArray:(NSArray *)assetArray 45 | bgAudioAsset:(AVAsset *)bgAudioAsset 46 | timeRange:(CMTimeRange)timeRange 47 | originalVolume:(float)originalVolume 48 | bgAudioVolume:(float)bgAudioVolume 49 | layerArray:(NSArray *)layerArray 50 | mergeFilePath:(NSString *)mergeFilePath 51 | mergeFileName:(NSString *)mergeFileName; 52 | 53 | /// 给视频添加贴图信息 54 | /// @param composition 视频合成器 55 | /// @param size 视频尺寸 56 | /// @param layerArray 图层数组 57 | + (void)applyVideoEffectsWithComposition:(AVMutableVideoComposition *)composition 58 | size:(CGSize)size 59 | layerArray:(NSArray *)layerArray; 60 | 61 | /// 根据类型快速获取沙盒路径 62 | /// @param pathType 路径类型 63 | + (NSString *)getSandboxFilePathWithPathType:(VideoFilePathType)pathType; 64 | 65 | @end 66 | 67 | -------------------------------------------------------------------------------- /SDVideoCamera/Album/SDVideoAlbumSelectCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoAlbumSelectCell.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/19. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoAlbumSelectCell.h" 10 | #import "UIColor+HexStringColor.h" 11 | #import "UIView+Extension.h" 12 | 13 | @interface SDVideoAlbumSelectCell () 14 | 15 | @property(nonatomic,strong)UIImageView *bgImageView; 16 | @property(nonatomic,strong)UIButton *deleteButton; 17 | @property(nonatomic,strong)UILabel *timeLabel; 18 | 19 | @end 20 | 21 | @implementation SDVideoAlbumSelectCell 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame { 24 | 25 | if (self = [super initWithFrame:frame]) { 26 | [self addSubview:self.bgImageView]; 27 | [self addSubview:self.deleteButton]; 28 | [self addSubview:self.timeLabel]; 29 | } 30 | return self; 31 | } 32 | 33 | - (UIImageView *)bgImageView { 34 | 35 | if (_bgImageView == nil) { 36 | _bgImageView = [[UIImageView alloc] initWithFrame:self.bounds]; 37 | _bgImageView.contentMode = UIViewContentModeScaleAspectFill; 38 | _bgImageView.clipsToBounds = YES; 39 | } 40 | return _bgImageView; 41 | } 42 | 43 | - (UIButton *)deleteButton { 44 | 45 | if (_deleteButton == nil) { 46 | _deleteButton = [[UIButton alloc] initWithFrame:CGRectMake(self.width - 20, 0, 20, 20)]; 47 | _deleteButton.backgroundColor = [UIColor hexStringToColor:@"000000" alpha:0.3]; 48 | _deleteButton.adjustsImageWhenHighlighted = NO; 49 | [_deleteButton setImage:[UIImage imageNamed:@"sd_album_delete_icon"] forState:UIControlStateNormal]; 50 | [_deleteButton addTarget:self action:@selector(deleteButtonAction) forControlEvents:UIControlEventTouchUpInside]; 51 | } 52 | return _deleteButton; 53 | } 54 | 55 | - (UILabel *)timeLabel { 56 | 57 | if (_timeLabel == nil) { 58 | _timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.height - 20, self.width, 20)]; 59 | _timeLabel.textColor = [UIColor hexStringToColor:@"ffffff"]; 60 | _timeLabel.textAlignment = NSTextAlignmentCenter; 61 | _timeLabel.font = [UIFont systemFontOfSize:12]; 62 | } 63 | return _timeLabel; 64 | } 65 | 66 | - (void)setBgImage:(UIImage *)bgImage { 67 | 68 | _bgImage = bgImage; 69 | self.bgImageView.image = bgImage; 70 | } 71 | 72 | - (void)setAsset:(PHAsset *)asset { 73 | 74 | _asset = asset; 75 | _timeLabel.text = [NSString stringWithFormat:@"%02d:%02d",((int)asset.duration)/60,((int)asset.duration)%60]; 76 | } 77 | 78 | - (void)deleteButtonAction { 79 | 80 | if (self.delegate != nil && [self.delegate respondsToSelector:@selector(userDeleteVideoWithDataIndex:)]) { 81 | [self.delegate userDeleteVideoWithDataIndex:self.dataIndex]; 82 | } 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /SDVideoCamera/Album/SDVideoAlbumCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoAlbumCell.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/19. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoAlbumCell.h" 10 | #import "UIColor+HexStringColor.h" 11 | #import "UIView+Extension.h" 12 | 13 | @interface SDVideoAlbumCell () 14 | 15 | @property(nonatomic,strong)UIImageView *bgImageView; 16 | @property(nonatomic,strong)UILabel *numberLabel; 17 | @property(nonatomic,strong)UILabel *timeLabel; 18 | 19 | @end 20 | 21 | @implementation SDVideoAlbumCell 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame { 24 | 25 | if (self = [super initWithFrame:frame]) { 26 | [self addSubview:self.bgImageView]; 27 | [self addSubview:self.numberLabel]; 28 | [self addSubview:self.timeLabel]; 29 | } 30 | return self; 31 | } 32 | 33 | - (UIImageView *)bgImageView { 34 | 35 | if (_bgImageView == nil) { 36 | _bgImageView = [[UIImageView alloc] initWithFrame:self.bounds]; 37 | _bgImageView.contentMode = UIViewContentModeScaleAspectFill; 38 | _bgImageView.clipsToBounds = YES; 39 | } 40 | return _bgImageView; 41 | } 42 | 43 | - (UILabel *)timeLabel { 44 | 45 | if (_timeLabel == nil) { 46 | _timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, self.height - 20, self.width - 5 * 2, 20)]; 47 | _timeLabel.textColor = [UIColor hexStringToColor:@"ffffff"]; 48 | _timeLabel.textAlignment = NSTextAlignmentRight; 49 | _timeLabel.font = [UIFont systemFontOfSize:12]; 50 | } 51 | return _timeLabel; 52 | } 53 | 54 | - (UILabel *)numberLabel { 55 | 56 | if (_numberLabel == nil) { 57 | _numberLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.width - 10 - 20, 10, 20, 20)]; 58 | _numberLabel.textColor = [UIColor hexStringToColor:@"000000"]; 59 | _numberLabel.textAlignment = NSTextAlignmentCenter; 60 | _numberLabel.font = [UIFont systemFontOfSize:12]; 61 | _numberLabel.layer.cornerRadius = 10.0; 62 | _numberLabel.layer.masksToBounds = YES; 63 | _numberLabel.layer.borderColor = [UIColor hexStringToColor:@"f5f5f5"].CGColor; 64 | } 65 | return _numberLabel; 66 | } 67 | 68 | - (void)setBgImage:(UIImage *)bgImage { 69 | 70 | _bgImage = bgImage; 71 | self.bgImageView.image = bgImage; 72 | } 73 | 74 | - (void)setAsset:(PHAsset *)asset { 75 | 76 | _asset = asset; 77 | _timeLabel.text = [NSString stringWithFormat:@"%02d:%02d",((int)asset.duration)/60,((int)asset.duration)%60]; 78 | } 79 | 80 | - (void)setSelectNumber:(int)selectNumber { 81 | 82 | _selectNumber = selectNumber; 83 | 84 | if (selectNumber == - 1) { 85 | self.numberLabel.text = nil; 86 | self.numberLabel.backgroundColor = [UIColor hexStringToColor:@"ffffff" alpha:0]; 87 | self.numberLabel.layer.borderWidth = 1.0f; 88 | } else { 89 | self.numberLabel.text = [NSString stringWithFormat:@"%d",selectNumber]; 90 | self.numberLabel.backgroundColor = [UIColor hexStringToColor:@"ffffff"]; 91 | self.numberLabel.layer.borderWidth = 0.0f; 92 | } 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoLoadingView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoLoadingView.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/28. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoLoadingView.h" 10 | #import "UIColor+HexStringColor.h" 11 | #import "UIView+Extension.h" 12 | 13 | @interface SDVideoLoadingView () 14 | 15 | @property(nonatomic,strong)UIView *mainView; 16 | @property(nonatomic,strong)UIImageView *loadingImageView; 17 | @property(nonatomic,strong)UILabel *loadingLabel; 18 | 19 | @end 20 | 21 | @implementation SDVideoLoadingView 22 | 23 | static SDVideoLoadingView *loadingView; 24 | 25 | + (SDVideoLoadingView *)defaultManager { 26 | 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | if (loadingView == nil) { 30 | loadingView = [[SDVideoLoadingView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 31 | loadingView.userInteractionEnabled = YES; 32 | [loadingView addSubview:loadingView.mainView]; 33 | } 34 | }); 35 | return loadingView; 36 | } 37 | 38 | - (UIView *)mainView { 39 | 40 | if (_mainView == nil) { 41 | _mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 42 | _mainView.backgroundColor = [UIColor hexStringToColor:@"000000" alpha:0.2]; 43 | _mainView.layer.cornerRadius = 3.0f; 44 | _mainView.layer.masksToBounds = YES; 45 | _mainView.center = self.center; 46 | [_mainView addSubview:self.loadingImageView]; 47 | [_mainView addSubview:self.loadingLabel]; 48 | } 49 | return _mainView; 50 | } 51 | 52 | - (UIImageView *)loadingImageView { 53 | 54 | if (_loadingImageView == nil) { 55 | NSMutableArray *framesArray = [[NSMutableArray alloc] init]; 56 | for (int i = 0; i < 60; i++) { 57 | UIImage *imageName = [UIImage imageNamed:[NSString stringWithFormat:@"sd_video_loading%d@2x",i]]; 58 | [framesArray addObject:imageName]; 59 | } 60 | _loadingImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 30, self.mainView.width, 32)]; 61 | _loadingImageView.contentMode = UIViewContentModeScaleAspectFit; 62 | _loadingImageView.animationImages = framesArray; 63 | _loadingImageView.animationDuration = 1.0; 64 | [_loadingImageView startAnimating]; 65 | } 66 | return _loadingImageView; 67 | } 68 | 69 | - (UILabel *)loadingLabel { 70 | 71 | if (_loadingLabel == nil) { 72 | _loadingLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.loadingImageView.bottom , self.mainView.width, 40)]; 73 | _loadingLabel.textAlignment = NSTextAlignmentCenter; 74 | _loadingLabel.font = [UIFont systemFontOfSize:12]; 75 | _loadingLabel.textColor = [UIColor whiteColor]; 76 | _loadingLabel.text = @"奋力加载中..."; 77 | } 78 | return _loadingLabel; 79 | } 80 | 81 | + (void)showLoadingAction { 82 | 83 | [[UIApplication sharedApplication].delegate.window addSubview:[SDVideoLoadingView defaultManager]]; 84 | } 85 | 86 | + (void)dismissLoadingAction { 87 | 88 | [[SDVideoLoadingView defaultManager] removeFromSuperview]; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewMusicSlider.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewMusicSlider.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/1. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoPreviewMusicSlider.h" 10 | #import "UIColor+HexStringColor.h" 11 | 12 | @interface SDVideoPreviewMusicSlider () 13 | 14 | @property(nonatomic,assign)CGRect thumbRect; 15 | @property(nonatomic,strong)UILabel *valueLabel; 16 | 17 | @end 18 | 19 | @implementation SDVideoPreviewMusicSlider 20 | 21 | - (instancetype)initWithFrame:(CGRect)frame { 22 | 23 | if (self = [super initWithFrame:frame]) { 24 | self.isUserInterface = YES; 25 | } 26 | return self; 27 | } 28 | 29 | - (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value { 30 | 31 | CGRect thumbRect = [super thumbRectForBounds:bounds trackRect:rect value:value]; 32 | self.thumbRect = thumbRect; 33 | self.valueText = [NSString stringWithFormat:@"%.0f", self.value]; 34 | return thumbRect; 35 | } 36 | 37 | #pragma mark - Setter functions 38 | 39 | - (void)setValueText:(NSString *)valueText { 40 | 41 | _valueText = valueText; 42 | self.valueLabel.text = valueText; 43 | [self.valueLabel sizeToFit]; 44 | self.valueLabel.center = CGPointMake(self.thumbRect.origin.x + self.thumbRect.size.width/2.0, self.thumbRect.origin.y - self.valueLabel.bounds.size.height/2.0); 45 | 46 | if (!self.valueLabel.superview) { 47 | [self addSubview:self.valueLabel]; 48 | } 49 | } 50 | 51 | #pragma mark - Getter functions 52 | 53 | - (UILabel *)valueLabel { 54 | 55 | if (_valueLabel == nil) { 56 | _valueLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 57 | _valueLabel.textColor = _valueTextColor ?: [UIColor whiteColor]; 58 | _valueLabel.font = _valueFont ?: [UIFont systemFontOfSize:14.0]; 59 | _valueLabel.textAlignment = NSTextAlignmentCenter; 60 | } 61 | return _valueLabel; 62 | } 63 | 64 | - (void)setIsUserInterface:(BOOL)isUserInterface { 65 | 66 | _isUserInterface = isUserInterface; 67 | self.userInteractionEnabled = isUserInterface; 68 | if (isUserInterface) { 69 | self.minimumTrackTintColor = [UIColor hexStringToColor:@"fbc835"]; 70 | self.maximumTrackTintColor = [UIColor hexStringToColor:@"ffffff"]; 71 | self.thumbTintColor = [UIColor hexStringToColor:@"ffffff"]; 72 | [self setThumbImage:[UIImage imageNamed:@"sd_preview_music_volume_icon"] forState:UIControlStateNormal]; 73 | } else { 74 | self.minimumTrackTintColor = [UIColor hexStringToColor:@"7a6c1e"]; 75 | self.maximumTrackTintColor = [UIColor hexStringToColor:@"7b7b7b"]; 76 | self.thumbTintColor = [UIColor hexStringToColor:@"808080"]; 77 | [self setThumbImage:[UIImage imageNamed:@"sd_preview_music_volume_icon"] forState:UIControlStateNormal]; 78 | } 79 | } 80 | 81 | - (void)setValueFont:(UIFont *)valueFont { 82 | 83 | _valueFont = valueFont; 84 | self.valueLabel.font = valueFont; 85 | } 86 | 87 | - (void)setValueTextColor:(UIColor *)valueTextColor { 88 | 89 | _valueTextColor = valueTextColor; 90 | self.valueLabel.textColor = valueTextColor; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/UIImage+Color.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Color.m 3 | // UIImage+Categories 4 | // 5 | // Created by lisong on 16/9/4. 6 | // Copyright © 2016年 lisong. All rights reserved. 7 | // 8 | 9 | #import "UIImage+Color.h" 10 | 11 | @implementation UIImage (Color) 12 | 13 | /** 根据颜色生成纯色图片 */ 14 | + (UIImage *)imageWithColor:(UIColor *)color 15 | { 16 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 17 | UIGraphicsBeginImageContext(rect.size); 18 | CGContextRef context = UIGraphicsGetCurrentContext(); 19 | 20 | CGContextSetFillColorWithColor(context, [color CGColor]); 21 | CGContextFillRect(context, rect); 22 | 23 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 24 | UIGraphicsEndImageContext(); 25 | 26 | return image; 27 | } 28 | 29 | /** 取图片某一像素的颜色 */ 30 | - (UIColor *)colorAtPixel:(CGPoint)point 31 | { 32 | if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), point)) 33 | { 34 | return nil; 35 | } 36 | 37 | NSInteger pointX = trunc(point.x); 38 | NSInteger pointY = trunc(point.y); 39 | CGImageRef cgImage = self.CGImage; 40 | NSUInteger width = self.size.width; 41 | NSUInteger height = self.size.height; 42 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 43 | int bytesPerPixel = 4; 44 | int bytesPerRow = bytesPerPixel * 1; 45 | NSUInteger bitsPerComponent = 8; 46 | unsigned char pixelData[4] = { 0, 0, 0, 0 }; 47 | CGContextRef context = CGBitmapContextCreate(pixelData, 48 | 1, 49 | 1, 50 | bitsPerComponent, 51 | bytesPerRow, 52 | colorSpace, 53 | kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 54 | CGColorSpaceRelease(colorSpace); 55 | CGContextSetBlendMode(context, kCGBlendModeCopy); 56 | 57 | CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height); 58 | CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage); 59 | CGContextRelease(context); 60 | 61 | CGFloat red = (CGFloat)pixelData[0] / 255.0f; 62 | CGFloat green = (CGFloat)pixelData[1] / 255.0f; 63 | CGFloat blue = (CGFloat)pixelData[2] / 255.0f; 64 | CGFloat alpha = (CGFloat)pixelData[3] / 255.0f; 65 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 66 | } 67 | 68 | /** 获得灰度图 */ 69 | - (UIImage *)convertToGrayImage 70 | { 71 | int width = self.size.width; 72 | int height = self.size.height; 73 | 74 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 75 | CGContextRef context = CGBitmapContextCreate(nil,width,height,8,0,colorSpace,kCGImageAlphaNone); 76 | CGColorSpaceRelease(colorSpace); 77 | 78 | if (context == NULL) 79 | { 80 | return nil; 81 | } 82 | 83 | CGContextDrawImage(context,CGRectMake(0, 0, width, height), self.CGImage); 84 | CGImageRef contextRef = CGBitmapContextCreateImage(context); 85 | UIImage *grayImage = [UIImage imageWithCGImage:contextRef]; 86 | CGContextRelease(context); 87 | CGImageRelease(contextRef); 88 | 89 | return grayImage; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /SDVideoCamera/SDVideoConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoConfig.h 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/14. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "SDVideoMenuDataModel.h" 12 | #import "SDVideoCameraHeader.h" 13 | #import "SDVideoMusicModel.h" 14 | 15 | #define MenuViewVerticalDistance (15.0f) // 控件垂直方向上的间距 16 | #define MenuProgressTopDistance (10.0f) // 进度条的头部间距 17 | #define MenuProgressLeftDistance (10.0f) // 进度条的左边间距 18 | 19 | typedef enum : NSUInteger { 20 | AudioURLTypeNone, // 没有配音 21 | AudioURLTypeLocal, // 本地配音 22 | AudioURLTypeWeb, // 网络配音 23 | } AudioURLType; 24 | 25 | typedef enum : NSUInteger { 26 | MaxVideoDurationTypeDuration, 27 | MaxVideoDurationTypeAudio, 28 | } MaxVideoDurationType; 29 | 30 | typedef void(^CameraReturnBlock)(NSString *mergeVideoPathString); 31 | 32 | // 用户完成选择 33 | typedef void(^UserSelectMusicFinishBlock)(SDVideoMusicModel *selectModel); 34 | 35 | @interface SDVideoConfig : NSObject 36 | 37 | // SDVideoConfig 是相机的配置项 38 | 39 | // 返回时回调的Block 40 | @property(nonatomic,copy)CameraReturnBlock returnBlock; 41 | 42 | // 需要返回到哪个控制器 43 | @property(nonatomic,weak)UIViewController *returnViewController; 44 | 45 | // 录制最大时长策略,一共有两种模式,一 由配置中的最大时长决定 , 二 由配音时长决定 46 | @property(nonatomic,assign)MaxVideoDurationType durationType; 47 | 48 | // 最大录制时长,默认为15秒 49 | @property(nonatomic,assign)NSTimeInterval maxVideoDuration; 50 | 51 | // 配音类型 52 | @property(nonatomic,assign)AudioURLType audioURLType; 53 | 54 | // 配音URL 55 | @property(nonatomic,copy)NSString *audioURL; 56 | 57 | // 配音名称,默认为空 58 | @property(nonatomic,copy)NSString *audioName; 59 | 60 | // 分段视频存放路径,默认为VideoFilePathTypeTmpPath 61 | @property(nonatomic,assign)VideoFilePathType videoFilePathType; 62 | 63 | // 分段视频前缀,默认为"SD_Record_Video", 64 | @property(nonatomic,copy)NSString *videoFileNamePrefix; 65 | 66 | // 合成视频路径,默认为VideoFilePathTypeCachesPath 67 | @property(nonatomic,assign)VideoFilePathType mergeFilePathType; 68 | 69 | // 合成视频名称,默认为"SD_" + "时间戳_" + 0~999随机数 + ".mov" 70 | @property(nonatomic,copy)NSString *mergeFileName; 71 | 72 | /************************UI部分************************/ 73 | 74 | // 整体主色,默认为#fb1e4d 75 | @property(nonatomic,copy)NSString *tintColor; 76 | 77 | // 进度条颜色,默认为#fbc835 78 | @property(nonatomic,copy)NSString *progressColor; 79 | 80 | // 功能菜单列表数组 81 | @property(nonatomic,copy)NSArray *menuDataArray; 82 | 83 | // 默认摄像头,默认为后置摄像头(AVCaptureDevicePositionBack) 84 | @property(nonatomic,assign)AVCaptureDevicePosition devicePosition; 85 | 86 | // 闪光灯开关,默认为关闭 87 | @property(nonatomic,assign)BOOL isOpenFlashlight; 88 | 89 | // 最大焦距倍数,默认为6,注:不可以超过6 90 | @property(nonatomic,assign)CGFloat maxVideoZoomFactor; 91 | 92 | // 配置自我检测,可以检测配置是否存在错误 93 | - (void)configDataSelfCheckAction; 94 | 95 | 96 | /************************预览设置部分************************/ 97 | 98 | // 推荐配乐列表 99 | @property(nonatomic,copy)NSArray *recommendMusicList; 100 | 101 | // 更多配乐的控制器 102 | @property(nonatomic,weak)UIViewController *moreMusicViewController; 103 | 104 | // 更多配乐选择完成需要 **调用(非实现)** 的block,用于把数据进行回传. 105 | @property(nonatomic,strong)UserSelectMusicFinishBlock finishBlock; 106 | 107 | // 字体颜色数组 108 | @property(nonatomic,copy)NSArray *previewColorArray; 109 | 110 | // 预览界面贴纸名称数组 111 | @property(nonatomic,copy)NSArray *previewTagImageNameArray; 112 | 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /SDVideoCamera/SDVideoConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoConfig.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/14. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoConfig.h" 10 | #import 11 | 12 | @implementation SDVideoConfig 13 | 14 | - (instancetype)init { 15 | 16 | if (self = [super init]) { 17 | self.durationType = MaxVideoDurationTypeDuration; 18 | self.maxVideoDuration = 15; 19 | self.audioURLType = AudioURLTypeNone; 20 | self.videoFilePathType = VideoFilePathTypeTmpPath; 21 | self.videoFileNamePrefix = @"SD_Record_Video"; 22 | self.mergeFilePathType = VideoFilePathTypeCachesPath; 23 | self.mergeFileName = nil; 24 | self.tintColor = @"fb1e4d"; 25 | self.progressColor = @"fbc835"; 26 | self.isOpenFlashlight = NO; 27 | self.devicePosition = AVCaptureDevicePositionBack; 28 | self.maxVideoZoomFactor = 6; 29 | [self loadMenuButtonDataAction]; 30 | [self loadPreviewTextColorArray]; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)loadMenuButtonDataAction { 36 | 37 | NSMutableArray *menuButtonArray = [NSMutableArray arrayWithCapacity:4]; 38 | 39 | SDVideoMenuDataModel *turnOverDataModel = [[SDVideoMenuDataModel alloc] init]; 40 | turnOverDataModel.menuType = VideoMenuTypesTurnOver; 41 | [menuButtonArray addObject:turnOverDataModel]; 42 | 43 | SDVideoMenuDataModel *flashlightDataModel = [[SDVideoMenuDataModel alloc] init]; 44 | flashlightDataModel.menuType = VideoMenuTypesFlashlight; 45 | [menuButtonArray addObject:flashlightDataModel]; 46 | 47 | SDVideoMenuDataModel *countDownDataModel = [[SDVideoMenuDataModel alloc] init]; 48 | countDownDataModel.menuType = VideoMenuTypesCountDown; 49 | [menuButtonArray addObject:countDownDataModel]; 50 | 51 | self.menuDataArray = menuButtonArray; 52 | } 53 | 54 | - (void)loadPreviewTextColorArray { 55 | 56 | self.previewColorArray = @[@"ffffff", 57 | @"010101", 58 | @"ff484e", 59 | @"bd01cc", 60 | @"4e49cc", 61 | @"1b8cef", 62 | @"31d366", 63 | @"ffc62e", 64 | @"ff8840", 65 | @"66c19d", 66 | @"ffa29e", 67 | @"a17d4d", 68 | @"005f84", 69 | @"1f4a33", 70 | @"858c93", 71 | @"2d2d2d"]; 72 | } 73 | 74 | #pragma mark - 接口方法 75 | 76 | - (void)configDataSelfCheckAction { 77 | 78 | // 设置了配音,但是没有设置配音类型 79 | if (self.audioURL != nil && self.audioURLType == AudioURLTypeNone) { 80 | NSLog(@"SDVideoConfig设置了配音,但是没有设置配音类型👇👇👇"); 81 | NSString *exceptionContent = [NSString stringWithFormat:@"audioURL 不为nil时,self.audioURLType不能为AudioURLTypeNone"]; 82 | @throw [NSException exceptionWithName:@"audioURLType has not Setting" reason:exceptionContent userInfo:nil]; 83 | } 84 | 85 | // 设置了配音,但是没有设置配音名称 86 | if (self.audioURL != nil && self.audioName == nil) { 87 | NSLog(@"SDVideoConfig设置了配音,但是没有设置配音名称👇👇👇"); 88 | NSString *exceptionContent = [NSString stringWithFormat:@"audioURL 不为nil时,self.audioName不能为nil"]; 89 | @throw [NSException exceptionWithName:@"audioName has not Setting" reason:exceptionContent userInfo:nil]; 90 | } 91 | } 92 | 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoCropDataManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropDataManager.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/24. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCropDataManager.h" 10 | 11 | #import "SDVideoUtils.h" 12 | 13 | @implementation SDVideoCropDataManager 14 | 15 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config { 16 | 17 | if (self = [super init]) { 18 | _config = config; 19 | _minDuration = CMTimeMake(1.0, 1.0); 20 | _observerTimeSpace = CMTimeMake(1, 10); 21 | _videoArray = [NSMutableArray arrayWithCapacity:16]; 22 | } 23 | return self; 24 | } 25 | 26 | #pragma mark - 接口方法 27 | 28 | - (void)videoArrayAddVideoAsset:(AVAsset *)videoAsset { 29 | 30 | [[self mutableArrayValueForKey:@"videoArray"] addObject:videoAsset]; 31 | [self reloadPlayItemAction]; 32 | [[NSNotificationCenter defaultCenter] postNotificationName:VideoArrayItemAddNotificationName object:nil]; 33 | [[NSNotificationCenter defaultCenter] postNotificationName:VideoPlayItemChangeNotificationName object:nil]; 34 | } 35 | 36 | - (void)videoArrayAddVideoAssetArray:(NSArray *)videoAssetArray { 37 | 38 | [[self mutableArrayValueForKey:@"videoArray"] addObjectsFromArray:videoAssetArray]; 39 | [self reloadPlayItemAction]; 40 | [[NSNotificationCenter defaultCenter] postNotificationName:VideoArrayItemAddNotificationName object:nil]; 41 | [[NSNotificationCenter defaultCenter] postNotificationName:VideoPlayItemChangeNotificationName object:nil]; 42 | } 43 | 44 | - (void)videoArrayDeleteVideoWithDataIndex:(NSInteger)dataIndex { 45 | 46 | [[self mutableArrayValueForKey:@"videoArray"] removeObjectAtIndex:dataIndex]; 47 | [self reloadPlayItemAction]; 48 | [[NSNotificationCenter defaultCenter] postNotificationName:VideoArrayItemDeleteIndexNotificationName object:@[@(dataIndex)]]; 49 | [[NSNotificationCenter defaultCenter] postNotificationName:VideoPlayItemChangeNotificationName object:nil]; 50 | } 51 | 52 | - (void)videoArrayChangeIndexWithFirstIndex:(NSInteger)firstIndex secondIndex:(NSInteger)secondIndex { 53 | 54 | [[self mutableArrayValueForKey:@"videoArray"] exchangeObjectAtIndex:firstIndex withObjectAtIndex:secondIndex]; 55 | [self reloadPlayItemAction]; 56 | [[NSNotificationCenter defaultCenter] postNotificationName:VideoArrayItemExchangeIndexNotificationName object:@[@(firstIndex),@(secondIndex)]]; 57 | [[NSNotificationCenter defaultCenter] postNotificationName:VideoPlayItemChangeNotificationName object:nil]; 58 | } 59 | 60 | #pragma mark - 私有方法 61 | 62 | // 重新生成媒体Item 63 | - (void)reloadPlayItemAction { 64 | 65 | self.playItem = [SDVideoUtils mergeMediaPlayerItemActionWithAssetArray:_videoArray 66 | timeRange:kCMTimeRangeZero 67 | bgAudioAsset:nil 68 | originalVolume:1 69 | bgAudioVolume:0]; 70 | } 71 | 72 | - (void)setPlayItem:(AVPlayerItem *)playItem { 73 | 74 | _playItem = playItem; 75 | self.currentPlayTime = kCMTimeZero; 76 | self.playTimeRange = CMTimeRangeMake(kCMTimeZero, playItem.asset.duration); 77 | self.playTotalTimeRange = CMTimeRangeMake(kCMTimeZero, playItem.asset.duration); 78 | _playItem.forwardPlaybackEndTime = CMTimeAdd(kCMTimeZero, playItem.asset.duration); 79 | } 80 | 81 | - (void)setPlayTimeRange:(CMTimeRange)playTimeRange { 82 | 83 | if (CMTIME_COMPARE_INLINE(playTimeRange.start, <, kCMTimeZero)) { 84 | playTimeRange = CMTimeRangeMake(kCMTimeZero, playTimeRange.duration); 85 | } 86 | if (CMTIME_COMPARE_INLINE(playTimeRange.duration, >, self.playTotalTimeRange.duration)) { 87 | playTimeRange = CMTimeRangeMake(playTimeRange.start, self.playTotalTimeRange.duration); 88 | } 89 | _playTimeRange = playTimeRange; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewMusicCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewMusicCell.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/30. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoPreviewMusicCell.h" 10 | #import "UIColor+HexStringColor.h" 11 | #import "UIView+Extension.h" 12 | 13 | @interface SDVideoPreviewMusicCell () 14 | 15 | @property(nonatomic,strong)UIImageView *musicImageView; 16 | @property(nonatomic,strong)UILabel *musicNameLabel; 17 | @property(nonatomic,strong)UIActivityIndicatorView *indicatorView; // 系统自带加载 18 | 19 | @end 20 | 21 | @implementation SDVideoPreviewMusicCell 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame { 24 | 25 | if (self = [super initWithFrame:frame]) { 26 | [self addSubview:self.musicImageView]; 27 | [self addSubview:self.musicNameLabel]; 28 | } 29 | return self; 30 | } 31 | 32 | #pragma mark - 懒加载 33 | 34 | - (UIImageView *)musicImageView { 35 | 36 | if (_musicImageView == nil) { 37 | _musicImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, self.width, self.width)]; 38 | self.musicImageView.layer.borderColor = [UIColor hexStringToColor:@"fbc835"].CGColor; 39 | _musicImageView.contentMode = UIViewContentModeScaleAspectFill; 40 | _musicImageView.clipsToBounds = YES; 41 | } 42 | return _musicImageView; 43 | } 44 | 45 | - (UILabel *)musicNameLabel { 46 | 47 | if (_musicNameLabel == nil) { 48 | _musicNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.musicImageView.bottom, self.width, self.height - self.musicImageView.bottom)]; 49 | _musicNameLabel.textColor = [UIColor hexStringToColor:@"ffffff"]; 50 | _musicNameLabel.lineBreakMode = NSLineBreakByCharWrapping; 51 | _musicNameLabel.textAlignment = NSTextAlignmentCenter; 52 | _musicNameLabel.font = [UIFont systemFontOfSize:12]; 53 | } 54 | return _musicNameLabel; 55 | } 56 | 57 | - (UIActivityIndicatorView *)indicatorView { 58 | if (_indicatorView == nil) { 59 | _indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleGray)]; 60 | _indicatorView.frame= self.musicImageView.bounds; 61 | _indicatorView.color = [UIColor lightGrayColor]; 62 | _indicatorView.center = self.center; 63 | _indicatorView.backgroundColor = [UIColor clearColor]; 64 | } 65 | return _indicatorView; 66 | } 67 | 68 | - (void)setDataModel:(SDVideoMusicModel *)dataModel { 69 | 70 | _dataModel = dataModel; 71 | self.musicNameLabel.text = dataModel.musicTitle; 72 | if (dataModel.musicImageName != nil) { 73 | self.musicImageView.image = [UIImage imageNamed:dataModel.musicImageName]; 74 | } 75 | if (dataModel.musicImageURL != nil) { 76 | if (dataModel.musicImageData != nil) { 77 | self.musicImageView.image = [UIImage imageWithData:dataModel.musicImageData]; 78 | } else { 79 | self.musicImageView.image = [UIImage imageNamed:@"sd_preview_music_default_image"]; 80 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 81 | NSData* imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:dataModel.musicImageURL]]; 82 | self.dataModel.musicImageData = imageData; 83 | dispatch_async(dispatch_get_main_queue(), ^{ 84 | self.musicImageView.image = [UIImage imageWithData:imageData]; 85 | }); 86 | }); 87 | } 88 | } 89 | if (self.dataModel.state == SDVideoMusicStateDownLoad) { 90 | [self.musicImageView addSubview:self.indicatorView]; 91 | [self.indicatorView startAnimating]; 92 | } else { 93 | [_indicatorView stopAnimating]; 94 | [_indicatorView removeFromSuperview]; 95 | } 96 | } 97 | 98 | - (void)setIsSelect:(BOOL)isSelect { 99 | 100 | _isSelect = isSelect; 101 | 102 | if (isSelect) { 103 | self.musicImageView.layer.borderWidth = 2.0; 104 | } else { 105 | self.musicImageView.layer.borderWidth = 0; 106 | } 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /VideoCameraDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropItemDeleteView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropItemDeleteView.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/27. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCropItemDeleteView.h" 10 | #import "UIColor+HexStringColor.h" 11 | #import "UIView+Extension.h" 12 | 13 | @interface SDVideoCropItemDeleteView () 14 | 15 | @property(nonatomic,strong)UIView *lineView; 16 | @property(nonatomic,strong)UIButton *deleteButton; 17 | @property(nonatomic,strong)UIButton *cancleButton; 18 | @property(nonatomic,strong)UIImageView *imageView; 19 | 20 | @property(nonatomic,strong)SDVideoCropDataManager *dataManager; 21 | 22 | @end 23 | 24 | @implementation SDVideoCropItemDeleteView 25 | 26 | - (instancetype)initWithFrame:(CGRect)frame dataManager:(SDVideoCropDataManager *)dataManager { 27 | 28 | if (self = [super initWithFrame:frame]) { 29 | self.backgroundColor = [UIColor hexStringToColor:@"15181f"]; 30 | self.dataManager = dataManager; 31 | [self addSubview:self.deleteButton]; 32 | [self addSubview:self.imageView]; 33 | [self addSubview:self.cancleButton]; 34 | [self addSubview:self.lineView]; 35 | } 36 | return self; 37 | } 38 | 39 | - (UIView *)lineView { 40 | 41 | if (_lineView == nil) { 42 | _lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.width, 0.5f)]; 43 | _lineView.backgroundColor = [UIColor hexStringToColor:@"666666"]; 44 | } 45 | return _lineView;; 46 | } 47 | 48 | - (UIButton *)deleteButton { 49 | 50 | if (_deleteButton == nil) { 51 | _deleteButton = [[UIButton alloc] initWithFrame:CGRectMake(20, 0, 60, self.height)]; 52 | _deleteButton.adjustsImageWhenHighlighted = NO; 53 | [_deleteButton setImage:[UIImage imageNamed:@"sd_corp_delete_icon"] forState:UIControlStateNormal]; 54 | [_deleteButton addTarget:self action:@selector(deleteButtonAction) forControlEvents:UIControlEventTouchUpInside]; 55 | } 56 | return _deleteButton; 57 | } 58 | 59 | - (UIImageView *)imageView { 60 | 61 | if (_imageView == nil) { 62 | _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.height/2.0, self.height/2.0)]; 63 | _imageView.layer.borderColor = [UIColor hexStringToColor:@"fbc835"].CGColor; 64 | _imageView.center = CGPointMake(self.width/2.0, self.height/2.0); 65 | _imageView.contentMode = UIViewContentModeScaleAspectFill; 66 | _imageView.layer.cornerRadius = 2.0f; 67 | _imageView.layer.masksToBounds = YES; 68 | _imageView.layer.borderWidth = 1.0f; 69 | _imageView.clipsToBounds = YES; 70 | } 71 | return _imageView; 72 | } 73 | 74 | - (UIButton *)cancleButton { 75 | 76 | if (_cancleButton == nil) { 77 | _cancleButton = [[UIButton alloc] initWithFrame:CGRectMake(self.width - 20 - 60, 0, 60, self.height)]; 78 | _cancleButton.adjustsImageWhenHighlighted = NO; 79 | [_cancleButton setImage:[UIImage imageNamed:@"sd_corp_cancle_icon"] forState:UIControlStateNormal]; 80 | [_cancleButton addTarget:self action:@selector(cancleButtonAction) forControlEvents:UIControlEventTouchUpInside]; 81 | } 82 | return _cancleButton; 83 | } 84 | 85 | - (void)setIndexRow:(NSInteger)indexRow { 86 | 87 | _indexRow = indexRow; 88 | } 89 | 90 | - (void)setSelectImage:(UIImage *)selectImage { 91 | 92 | _selectImage = selectImage; 93 | _imageView.image = selectImage; 94 | } 95 | 96 | - (void)cancleButtonAction { 97 | 98 | [UIView animateWithDuration:0.2 animations:^{ 99 | self.top = self.height; 100 | } completion:^(BOOL finished) { 101 | [self removeFromSuperview]; 102 | }]; 103 | } 104 | 105 | - (void)deleteButtonAction { 106 | 107 | UIAlertController *alertViewController = [UIAlertController alertControllerWithTitle:@"是否删除此片段?" message:nil preferredStyle:UIAlertControllerStyleAlert]; 108 | UIAlertAction *deleteAction = [UIAlertAction actionWithTitle:@"删除" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 109 | [self cancleButtonAction]; 110 | if (self.delegate != nil && [self.delegate respondsToSelector:@selector(userDeletVideoAssetWithIndexRow:)]) { 111 | [self.delegate userDeletVideoAssetWithIndexRow:self.indexRow]; 112 | } 113 | }]; 114 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; 115 | [alertViewController addAction:deleteAction]; 116 | [alertViewController addAction:cancelAction]; 117 | [self.dataManager.superViewController presentViewController:alertViewController animated:YES completion:nil]; 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /SDVideoCamera/Helpers/SDVideoDataManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoDataManager.m 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import "SDVideoDataManager.h" 10 | #import 11 | #import "SDVideoUtils.h" 12 | 13 | @interface SDVideoDataManager () 14 | 15 | @property (nonatomic, weak) NSTimer *videoTimer; 16 | 17 | @end 18 | 19 | @implementation SDVideoDataManager 20 | 21 | static SDVideoDataManager *manager = nil; 22 | 23 | + (SDVideoDataManager *)defaultManager { 24 | 25 | static dispatch_once_t onceToken; 26 | dispatch_once(&onceToken, ^{ 27 | if (manager == nil) { 28 | manager = [[SDVideoDataManager alloc] init]; 29 | } 30 | }); 31 | return manager; 32 | } 33 | 34 | - (NSTimer *)videoTimer { 35 | 36 | if (_videoTimer == nil) { 37 | _videoTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(videoStartTimerAction) userInfo:nil repeats:YES]; 38 | } 39 | return _videoTimer; 40 | } 41 | 42 | - (void)videoStartTimerAction { 43 | 44 | self.totalVideoTime += 0.1; 45 | if (self.totalVideoTime > _videoSecondTime) { 46 | self.cameraState = VideoCameraStateStop; 47 | [_videoTimer invalidate]; 48 | _videoTimer = nil; 49 | } else { 50 | self.progress = (float)self.totalVideoTime / (float)_videoSecondTime; 51 | } 52 | } 53 | 54 | - (void)setCameraState:(VideoCameraState)cameraState { 55 | 56 | _cameraState = cameraState; 57 | switch (cameraState) { 58 | case VideoCameraStateIdle:{ 59 | self.progress = 0; 60 | self.totalVideoTime = 0; 61 | break; 62 | } 63 | case VideoCameraStateInProgress:{ 64 | [self.videoTimer setFireDate:[NSDate distantPast]]; 65 | break; 66 | } 67 | case VideoCameraStatePause:{ 68 | [self.videoTimer setFireDate:[NSDate distantFuture]]; 69 | break; 70 | } 71 | case VideoCameraStateStop: { 72 | self.progress = 1; 73 | break; 74 | } 75 | } 76 | } 77 | 78 | #pragma mark - 视频的相关操作 79 | 80 | - (void)addVideoModel:(SDVideoDataModel *)videoModel { 81 | 82 | [_videoDataArray addObject:videoModel]; 83 | self.videoNumber = self.videoDataArray.count; 84 | } 85 | 86 | - (void)deleteLastVideoModel { 87 | 88 | SDVideoDataModel *dataModel = _videoDataArray.lastObject; 89 | manager.totalVideoTime -= dataModel.duration; 90 | [dataModel deleteLocalVideoFileAction]; 91 | [_videoDataArray removeLastObject]; 92 | self.videoNumber = self.videoDataArray.count; 93 | 94 | if (self.videoNumber == 0) { 95 | self.cameraState = VideoCameraStateIdle; 96 | } else { 97 | self.cameraState = VideoCameraStatePause; 98 | } 99 | } 100 | 101 | - (void)deleteAllVideoModel { 102 | 103 | for (SDVideoDataModel *dataModel in _videoDataArray) { 104 | [dataModel deleteLocalVideoFileAction]; 105 | } 106 | [_videoDataArray removeAllObjects]; 107 | self.videoNumber = self.videoDataArray.count; 108 | self.cameraState = VideoCameraStateIdle; 109 | } 110 | 111 | #pragma mark - 设置方法 112 | 113 | - (void)setConfig:(SDVideoConfig *)config { 114 | 115 | _config = config; 116 | self.totalVideoTime = 0; 117 | _videoDataArray = [NSMutableArray arrayWithCapacity:16]; 118 | 119 | // 根据不同情况设置最大时长 120 | if (config.audioURL == nil) { 121 | // 当前没有配音伴奏URL 122 | _videoSecondTime = config.maxVideoDuration; 123 | } else { 124 | // 当前有配音伴奏 125 | if (config.durationType == MaxVideoDurationTypeAudio) { 126 | switch (config.audioURLType) { 127 | case AudioURLTypeNone: 128 | _videoSecondTime = config.maxVideoDuration; 129 | break; 130 | case AudioURLTypeLocal: 131 | _videoSecondTime = [SDVideoDataManager getMediaSecondWithMediaURL:[NSURL fileURLWithPath:config.audioURL]]; 132 | break; 133 | case AudioURLTypeWeb: 134 | _videoSecondTime = [SDVideoDataManager getMediaSecondWithMediaURL:[NSURL URLWithString:config.audioURL]]; 135 | break; 136 | } 137 | } else { 138 | _videoSecondTime = config.maxVideoDuration; 139 | } 140 | } 141 | } 142 | 143 | #pragma mark - 私有方法 144 | 145 | // 获取媒体时长 146 | + (NSInteger)getMediaSecondWithMediaURL:(NSURL *)mediaURL { 147 | 148 | AVURLAsset *mediaAsset = [AVURLAsset assetWithURL:mediaURL]; 149 | CMTime mediaTime = [mediaAsset duration]; 150 | return ceil(mediaTime.value/mediaTime.timescale); 151 | } 152 | 153 | @end 154 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/UIView+Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.m 3 | // SmartLock 4 | // 5 | // Created by 江欣华 on 2016/10/25. 6 | // Copyright © 2016年 工程锁. All rights reserved. 7 | // 8 | 9 | #import "UIView+Extension.h" 10 | 11 | @implementation UIView (Extension) 12 | 13 | #pragma mark - frame 14 | 15 | - (void)setX:(CGFloat)x { 16 | CGRect frame = self.frame; 17 | frame.origin.x = x; 18 | self.frame = frame; 19 | } 20 | 21 | - (void)setY:(CGFloat)y { 22 | CGRect frame = self.frame; 23 | frame.origin.y = y; 24 | self.frame = frame; 25 | } 26 | 27 | - (CGFloat)x { 28 | return self.frame.origin.x; 29 | } 30 | 31 | - (CGFloat)y { 32 | return self.frame.origin.y; 33 | } 34 | 35 | - (void)setCenterX:(CGFloat)centerX { 36 | 37 | CGPoint center = self.center; 38 | center.x = centerX; 39 | self.center = center; 40 | 41 | } 42 | 43 | - (CGFloat)centerX { 44 | return self.center.x; 45 | } 46 | 47 | - (void)setCenterY:(CGFloat)centerY{ 48 | CGPoint center = self.center; 49 | center.y = centerY; 50 | self.center = center; 51 | } 52 | 53 | - (CGFloat)centerY { 54 | return self.center.y; 55 | } 56 | 57 | - (void)setWidth:(CGFloat)width { 58 | CGRect frame = self.frame; 59 | frame.size.width = width; 60 | self.frame = frame; 61 | } 62 | 63 | - (void)setHeight:(CGFloat)height { 64 | CGRect frame = self.frame; 65 | frame.size.height = height; 66 | self.frame = frame; 67 | } 68 | 69 | - (CGFloat)height { 70 | return self.frame.size.height; 71 | } 72 | 73 | - (CGFloat)width { 74 | return self.frame.size.width; 75 | } 76 | 77 | - (void)setSize:(CGSize)size { 78 | CGRect frame = self.frame; 79 | frame.size = size; 80 | self.frame = frame; 81 | } 82 | 83 | - (CGSize)size { 84 | return self.frame.size; 85 | } 86 | 87 | - (void)setOrigin:(CGPoint)origin { 88 | CGRect frame = self.frame; 89 | frame.origin = origin; 90 | self.frame = frame; 91 | } 92 | 93 | - (CGPoint)origin { 94 | return self.frame.origin; 95 | } 96 | 97 | - (CGFloat)top { 98 | return self.frame.origin.y; 99 | } 100 | 101 | - (void)setTop:(CGFloat)top { 102 | CGRect frame = self.frame; 103 | frame.origin.y = top; 104 | self.frame = frame; 105 | } 106 | 107 | - (CGFloat)left { 108 | return self.frame.origin.x; 109 | } 110 | 111 | - (void)setLeft:(CGFloat)left { 112 | CGRect frame = self.frame; 113 | frame.origin.x = left; 114 | self.frame = frame; 115 | } 116 | 117 | - (CGFloat)bottom { 118 | return self.frame.size.height + self.frame.origin.y; 119 | } 120 | 121 | - (void)setBottom:(CGFloat)bottom { 122 | CGRect frame = self.frame; 123 | frame.origin.y = bottom - frame.size.height; 124 | self.frame = frame; 125 | } 126 | 127 | - (CGFloat)right { 128 | return self.frame.size.width + self.frame.origin.x; 129 | } 130 | 131 | - (void)setRight:(CGFloat)right { 132 | CGRect frame = self.frame; 133 | frame.origin.x = right - frame.size.width; 134 | self.frame = frame; 135 | } 136 | 137 | #pragma mark - layer 138 | 139 | - (void)rounded:(CGFloat)cornerRadius { 140 | [self rounded:cornerRadius width:0 color:nil]; 141 | } 142 | 143 | - (void)border:(CGFloat)borderWidth color:(UIColor *)borderColor { 144 | [self rounded:0 width:borderWidth color:borderColor]; 145 | } 146 | 147 | - (void)rounded:(CGFloat)cornerRadius width:(CGFloat)borderWidth color:(UIColor *)borderColor { 148 | self.layer.cornerRadius = cornerRadius; 149 | self.layer.borderWidth = borderWidth; 150 | self.layer.borderColor = [borderColor CGColor]; 151 | self.layer.masksToBounds = YES; 152 | } 153 | 154 | 155 | - (void)round:(CGFloat)cornerRadius RectCorners:(UIRectCorner)rectCorner { 156 | 157 | UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCorner cornerRadii:CGSizeMake(cornerRadius, cornerRadius)]; 158 | CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; 159 | maskLayer.frame = self.bounds; 160 | maskLayer.path = maskPath.CGPath; 161 | self.layer.mask = maskLayer; 162 | } 163 | 164 | - (void)shadow:(UIColor *)shadowColor opacity:(CGFloat)opacity radius:(CGFloat)radius offset:(CGSize)offset { 165 | //给Cell设置阴影效果 166 | self.layer.masksToBounds = NO; 167 | self.layer.shadowColor = shadowColor.CGColor; 168 | self.layer.shadowOpacity = opacity; 169 | self.layer.shadowRadius = radius; 170 | self.layer.shadowOffset = offset; 171 | } 172 | 173 | #pragma mark - base 174 | 175 | - (UIViewController *)viewController { 176 | 177 | id nextResponder = [self nextResponder]; 178 | while (nextResponder != nil) { 179 | if ([nextResponder isKindOfClass:[UIViewController class]]) { 180 | UIViewController *vc = (UIViewController *)nextResponder; 181 | return vc; 182 | } 183 | nextResponder = [nextResponder nextResponder]; 184 | } 185 | return nil; 186 | } 187 | 188 | + (CGFloat)getLabelHeightByWidth:(CGFloat)width Title:(NSString *)title font:(UIFont *)font { 189 | 190 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 0)]; 191 | label.text = title; 192 | label.font = font; 193 | label.numberOfLines = 0; 194 | [label sizeToFit]; 195 | CGFloat height = label.frame.size.height; 196 | return height; 197 | } 198 | 199 | @end 200 | -------------------------------------------------------------------------------- /SDVideoCamera/Preview/SDVideoPreviewTagsView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoPreviewTagsView.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/5/5. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoPreviewTagsView.h" 10 | #import "UIColor+HexStringColor.h" 11 | #import "SDVideoPreviewTagCell.h" 12 | #import "UIView+Extension.h" 13 | 14 | @interface SDVideoPreviewTagsView () 15 | 16 | @property(nonatomic,strong)SDVideoConfig *config; 17 | @property(nonatomic,strong)UIView *mainView; 18 | @property(nonatomic,strong)UILabel *titleLabel; 19 | @property(nonatomic,strong)UICollectionView *colletionView; 20 | 21 | @end 22 | 23 | @implementation SDVideoPreviewTagsView 24 | 25 | - (instancetype)initWithFrame:(CGRect)frame config:(SDVideoConfig *)config { 26 | 27 | if (self = [super initWithFrame:frame]) { 28 | self.config = config; 29 | [self addSubview:self.mainView]; 30 | } 31 | return self; 32 | } 33 | 34 | #pragma mark - 懒加载 35 | 36 | - (UIView *)mainView { 37 | 38 | if (_mainView == nil) { 39 | _mainView = [[UIView alloc] initWithFrame:CGRectMake(0, StatusHeight + NavigationBarHeight, self.width, self.height - (StatusHeight + NavigationBarHeight))]; 40 | _mainView.backgroundColor = [UIColor hexStringToColor:@"000000" alpha:0.8]; 41 | [_mainView addSubview:self.titleLabel]; 42 | [_mainView addSubview:self.colletionView]; 43 | } 44 | return _mainView; 45 | } 46 | 47 | - (UILabel *)titleLabel { 48 | 49 | if (_titleLabel == nil) { 50 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.mainView.width, 60)]; 51 | _titleLabel.textColor = [UIColor hexStringToColor:@"ffffff"]; 52 | _titleLabel.textAlignment = NSTextAlignmentCenter; 53 | _titleLabel.font = [UIFont systemFontOfSize:14]; 54 | _titleLabel.text = @"贴纸"; 55 | CALayer *lineLayer = [[CALayer alloc] init]; 56 | lineLayer.frame = CGRectMake(0, _titleLabel.height - 1, _titleLabel.width, 0.5); 57 | lineLayer.backgroundColor = [UIColor hexStringToColor:@"333333"].CGColor; 58 | [_titleLabel.layer addSublayer:lineLayer]; 59 | } 60 | return _titleLabel; 61 | } 62 | 63 | - (UICollectionView *)colletionView { 64 | 65 | if (_colletionView == nil) { 66 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; 67 | layout.itemSize = CGSizeMake(self.mainView.width/4.0, self.mainView.width/4.0); 68 | layout.minimumInteritemSpacing = 0; 69 | layout.minimumLineSpacing = 0; 70 | _colletionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, self.titleLabel.bottom, self.mainView.width, self.mainView.height - self.titleLabel.bottom) collectionViewLayout:layout]; 71 | _colletionView.backgroundColor = [UIColor clearColor]; 72 | _colletionView.showsVerticalScrollIndicator = NO; 73 | _colletionView.dataSource = self; 74 | _colletionView.delegate = self; 75 | [_colletionView registerClass:[SDVideoPreviewTagCell class] forCellWithReuseIdentifier:@"SDVideoPreviewTagCell"]; 76 | } 77 | return _colletionView; 78 | } 79 | 80 | #pragma mark - UICollectionViewDelegateFlowLayout,UICollectionViewDataSource 81 | 82 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 83 | 84 | return self.config.previewTagImageNameArray.count; 85 | } 86 | 87 | - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 88 | 89 | SDVideoPreviewTagCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"SDVideoPreviewTagCell" forIndexPath:indexPath]; 90 | cell.imageName = self.config.previewTagImageNameArray[indexPath.row]; 91 | return cell; 92 | } 93 | 94 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 95 | 96 | UIImage *contentImage = [UIImage imageNamed:self.config.previewTagImageNameArray[indexPath.row]]; 97 | SDVideoPreviewEffectModel *dataModel = [[SDVideoPreviewEffectModel alloc] init]; 98 | dataModel.contentSize = contentImage.size; 99 | dataModel.type = EffectDataTypeImage; 100 | dataModel.image = contentImage; 101 | if (_delegate != nil && [_delegate respondsToSelector:@selector(userFinishSelectTagWithDataModel:)]) { 102 | [_delegate userFinishSelectTagWithDataModel:dataModel]; 103 | } 104 | [self removeFromSuperview]; 105 | } 106 | 107 | #pragma mark - 显示与隐藏 108 | 109 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 110 | 111 | CGPoint touchPoint = [[touches anyObject] locationInView:self]; 112 | 113 | if (!CGRectContainsPoint(self.mainView.frame, touchPoint)) { 114 | [self dismissViewAction]; 115 | } 116 | } 117 | 118 | - (void)showViewAction { 119 | 120 | self.mainView.top = self.height; 121 | [UIView animateWithDuration:0.3 animations:^{ 122 | self.mainView.bottom = self.height; 123 | }]; 124 | } 125 | 126 | - (void)dismissViewAction { 127 | 128 | [UIView animateWithDuration:0.2 animations:^{ 129 | self.mainView.top = self.height; 130 | } completion:^(BOOL finished) { 131 | [self removeFromSuperview]; 132 | }]; 133 | } 134 | 135 | 136 | @end 137 | 138 | -------------------------------------------------------------------------------- /SDVideoCamera/Crop/SDVideoCropBottomView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCropBottomView.m 3 | // SDVideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/20. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCropBottomView.h" 10 | #import "SDVideoCropItemListView.h" 11 | #import "UIColor+HexStringColor.h" 12 | #import "SDVideoCropFrameView.h" 13 | #import "UIView+Extension.h" 14 | #import "SDVideoUtils.h" 15 | 16 | @interface SDVideoCropBottomView () 17 | 18 | @property(nonatomic,strong)UILabel *selectTimeLabel; 19 | @property(nonatomic,strong)UIButton *reloadSelectButton; 20 | @property(nonatomic,strong)SDVideoCropFrameView *cropFrameView; 21 | @property(nonatomic,strong)SDVideoCropItemListView *itemListView; 22 | @property(nonatomic,strong)UICollectionView *videoCollectionView; 23 | 24 | @property(nonatomic,strong)SDVideoCropDataManager *dataManager; 25 | 26 | @end 27 | 28 | @implementation SDVideoCropBottomView 29 | 30 | - (instancetype)initWithFrame:(CGRect)frame dataManager:(SDVideoCropDataManager *)dataManager { 31 | 32 | if (self = [super initWithFrame:frame]) { 33 | self.backgroundColor = [UIColor hexStringToColor:@"15181f"]; 34 | self.dataManager = dataManager; 35 | [self addDataObserverAction]; 36 | [self addSubview:self.selectTimeLabel]; 37 | [self addSubview:self.cropFrameView]; 38 | [self addSubview:self.itemListView]; 39 | } 40 | return self; 41 | } 42 | 43 | #pragma mark - 懒加载 44 | 45 | - (UILabel *)selectTimeLabel { 46 | 47 | if (_selectTimeLabel == nil) { 48 | _selectTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, self.width - 10 * 2, 30)]; 49 | _selectTimeLabel.text = [NSString stringWithFormat:@"已选取 %.1fs",CMTimeGetSeconds(self.dataManager.playTimeRange.duration)]; 50 | _selectTimeLabel.textColor = [UIColor hexStringToColor:@"ffffff"]; 51 | _selectTimeLabel.font = [UIFont boldSystemFontOfSize:12]; 52 | _selectTimeLabel.userInteractionEnabled = YES; 53 | } 54 | return _selectTimeLabel; 55 | } 56 | 57 | - (UIButton *)reloadSelectButton { 58 | 59 | if (_reloadSelectButton == nil) { 60 | _reloadSelectButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60, 26)]; 61 | _reloadSelectButton.backgroundColor = [UIColor hexStringToColor:self.dataManager.config.tintColor]; 62 | _reloadSelectButton.titleLabel.font = [UIFont boldSystemFontOfSize:12]; 63 | _reloadSelectButton.centerY = self.selectTimeLabel.height/2.0; 64 | _reloadSelectButton.right = self.selectTimeLabel.width; 65 | _reloadSelectButton.layer.cornerRadius = 13.0f; 66 | _reloadSelectButton.layer.masksToBounds = YES; 67 | [_reloadSelectButton setTitle:@"重置" forState:UIControlStateNormal]; 68 | [_reloadSelectButton addTarget:self action:@selector(reloadSelectButtonAction) forControlEvents:UIControlEventTouchUpInside]; 69 | } 70 | return _reloadSelectButton; 71 | } 72 | 73 | - (SDVideoCropFrameView *)cropFrameView { 74 | 75 | if (_cropFrameView == nil) { 76 | _cropFrameView = [[SDVideoCropFrameView alloc] initWithFrame:CGRectMake(0, _selectTimeLabel.bottom, self.width, 100) dataManager:self.dataManager]; 77 | _cropFrameView.delegate = self; 78 | } 79 | return _cropFrameView; 80 | } 81 | 82 | - (SDVideoCropItemListView *)itemListView { 83 | 84 | if (_itemListView == nil) { 85 | _itemListView = [[SDVideoCropItemListView alloc] initWithFrame:CGRectMake(0, self.cropFrameView.bottom, self.width, self.height - self.cropFrameView.bottom) dataManager:self.dataManager]; 86 | } 87 | return _itemListView; 88 | } 89 | 90 | #pragma mark - 点击方法 91 | 92 | - (void)reloadSelectButtonAction { 93 | 94 | self.dataManager.playTimeRange = self.dataManager.playTotalTimeRange; 95 | self.dataManager.currentPlayTime = kCMTimeZero; 96 | [self.cropFrameView reloadPlayTimeRangeAction]; 97 | } 98 | 99 | #pragma mark - 拖拽代理方法 100 | 101 | - (void)userStartChangeVideoTimeRangeAction { 102 | 103 | if (_delegate != nil && [_delegate respondsToSelector:@selector(userStartChangeVideoTimeRangeAction)]) { 104 | [_delegate userStartChangeVideoTimeRangeAction]; 105 | } 106 | } 107 | 108 | - (void)userChangeVideoTimeRangeAction { 109 | 110 | if (_delegate != nil && [_delegate respondsToSelector:@selector(userChangeVideoTimeRangeAction)]) { 111 | [_delegate userChangeVideoTimeRangeAction]; 112 | } 113 | } 114 | 115 | - (void)userEndChangeVideoTimeRangeAction { 116 | 117 | if (_delegate != nil && [_delegate respondsToSelector:@selector(userEndChangeVideoTimeRangeAction)]) { 118 | [_delegate userEndChangeVideoTimeRangeAction]; 119 | } 120 | } 121 | 122 | #pragma mark - 数据监听观察 123 | 124 | - (void)addDataObserverAction { 125 | 126 | [self.dataManager addObserver:self forKeyPath:@"playTimeRange" options:NSKeyValueObservingOptionNew context:nil]; 127 | } 128 | 129 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 130 | 131 | if ([keyPath isEqualToString:@"playTimeRange"]) { 132 | self.selectTimeLabel.text = [NSString stringWithFormat:@"已选取 %.1fs",CMTimeGetSeconds(self.dataManager.playTimeRange.duration)]; 133 | if (CMTimeCompare(self.dataManager.playTimeRange.duration,self.dataManager.playTotalTimeRange.duration) == 0) { 134 | [_reloadSelectButton removeFromSuperview]; 135 | } else { 136 | [self.selectTimeLabel addSubview:self.reloadSelectButton]; 137 | } 138 | } 139 | } 140 | 141 | #pragma mark - 系统方法 142 | 143 | - (void)dealloc { 144 | 145 | [self.dataManager removeObserver:self forKeyPath:@"playTimeRange"]; 146 | } 147 | 148 | @end 149 | -------------------------------------------------------------------------------- /SDVideoCamera/Categories/UIButton+EdgeInsets.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+imageTitleLayout.m 3 | // 4 | // 5 | // Created by 韩保玉 on 15/6/28. 6 | // Copyright (c) 2015年 韩保玉. All rights reserved. 7 | // 8 | 9 | #import "UIButton+EdgeInsets.h" 10 | 11 | @implementation UIButton (EdgeInsets) 12 | 13 | - (void)layoutButtonWithEdgeInsetsStyle:(ButtonEdgeInsetsStyle)style imageTitlespace:(CGFloat)space { 14 | CGFloat imageViewWidth = CGRectGetWidth(self.imageView.frame); 15 | CGFloat labelWidth = CGRectGetWidth(self.titleLabel.frame); 16 | 17 | if (labelWidth == 0) { 18 | CGSize titleSize = [self.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}]; 19 | labelWidth = titleSize.width; 20 | } 21 | 22 | CGFloat imageInsetsTop = 0.0f; 23 | CGFloat imageInsetsLeft = 0.0f; 24 | CGFloat imageInsetsBottom = 0.0f; 25 | CGFloat imageInsetsRight = 0.0f; 26 | 27 | CGFloat titleInsetsTop = 0.0f; 28 | CGFloat titleInsetsLeft = 0.0f; 29 | CGFloat titleInsetsBottom = 0.0f; 30 | CGFloat titleInsetsRight = 0.0f; 31 | 32 | switch (style) { 33 | case ButtonEdgeInsetsStyleImageRight: 34 | { 35 | space = space * 0.5; 36 | 37 | imageInsetsLeft = labelWidth + space; 38 | imageInsetsRight = -imageInsetsLeft; 39 | 40 | titleInsetsLeft = - (imageViewWidth + space); 41 | titleInsetsRight = -titleInsetsLeft; 42 | } 43 | break; 44 | 45 | case ButtonEdgeInsetsStyleImageLeft: 46 | { 47 | space = space * 0.5; 48 | 49 | imageInsetsLeft = -space; 50 | imageInsetsRight = -imageInsetsLeft; 51 | 52 | titleInsetsLeft = space; 53 | titleInsetsRight = -titleInsetsLeft; 54 | } 55 | break; 56 | case ButtonEdgeInsetsStyleImageBottom: 57 | { 58 | CGFloat imageHeight = CGRectGetHeight(self.imageView.frame); 59 | CGFloat labelHeight = CGRectGetHeight(self.titleLabel.frame); 60 | CGFloat buttonHeight = CGRectGetHeight(self.frame); 61 | CGFloat boundsCentery = (imageHeight + space + labelHeight) * 0.5; 62 | 63 | CGFloat centerX_button = CGRectGetMidX(self.bounds); // bounds 64 | CGFloat centerX_titleLabel = CGRectGetMidX(self.titleLabel.frame); 65 | CGFloat centerX_image = CGRectGetMidX(self.imageView.frame); 66 | 67 | CGFloat imageBottomY = CGRectGetMaxY(self.imageView.frame); 68 | CGFloat titleTopY = CGRectGetMinY(self.titleLabel.frame); 69 | 70 | imageInsetsTop = buttonHeight - (buttonHeight * 0.5 - boundsCentery) - imageBottomY; 71 | imageInsetsLeft = centerX_button - centerX_image; 72 | imageInsetsRight = - imageInsetsLeft; 73 | imageInsetsBottom = - imageInsetsTop; 74 | 75 | titleInsetsTop = (buttonHeight * 0.5 - boundsCentery) - titleTopY; 76 | titleInsetsLeft = -(centerX_titleLabel - centerX_button); 77 | titleInsetsRight = - titleInsetsLeft; 78 | titleInsetsBottom = - titleInsetsTop; 79 | 80 | } 81 | break; 82 | case ButtonEdgeInsetsStyleImageTop: 83 | { 84 | CGFloat imageHeight = CGRectGetHeight(self.imageView.frame); 85 | CGFloat labelHeight = CGRectGetHeight(self.titleLabel.frame); 86 | CGFloat buttonHeight = CGRectGetHeight(self.frame); 87 | CGFloat boundsCentery = (imageHeight + space + labelHeight) * 0.5; 88 | 89 | CGFloat centerX_button = CGRectGetMidX(self.bounds); // bounds 90 | CGFloat centerX_titleLabel = CGRectGetMidX(self.titleLabel.frame); 91 | CGFloat centerX_image = CGRectGetMidX(self.imageView.frame); 92 | 93 | CGFloat imageTopY = CGRectGetMinY(self.imageView.frame); 94 | CGFloat titleBottom = CGRectGetMaxY(self.titleLabel.frame); 95 | 96 | imageInsetsTop = (buttonHeight * 0.5 - boundsCentery) - imageTopY; 97 | imageInsetsLeft = centerX_button - centerX_image; 98 | imageInsetsRight = - imageInsetsLeft; 99 | imageInsetsBottom = - imageInsetsTop; 100 | 101 | titleInsetsTop = buttonHeight - (buttonHeight * 0.5 - boundsCentery) - titleBottom; 102 | titleInsetsLeft = -(centerX_titleLabel - centerX_button); 103 | titleInsetsRight = - titleInsetsLeft; 104 | titleInsetsBottom = - titleInsetsTop; 105 | } 106 | break; 107 | 108 | default: 109 | break; 110 | } 111 | self.imageEdgeInsets = UIEdgeInsetsMake(imageInsetsTop, imageInsetsLeft, imageInsetsBottom, imageInsetsRight); 112 | self.titleEdgeInsets = UIEdgeInsetsMake(titleInsetsTop, titleInsetsLeft, titleInsetsBottom, titleInsetsRight); 113 | } 114 | 115 | - (void)centerImageAndTitle:(CGFloat)space { 116 | CGSize imageSize = self.imageView.frame.size; 117 | CGSize titleSize = self.titleLabel.frame.size; 118 | // get the height they will take up as a unit 119 | // NSLog(@"%lf-%lf",imageSize.width,imageSize.height);// 63 63 120 | // NSLog(@"%lf-%lf",titleSize.width,titleSize.height); // 14.5 17 121 | // NSLog(@"%lf-%lf",self.frame.size.width,self.frame.size.height); // 93.75 100 122 | CGFloat totalHeight = (imageSize.height + titleSize.height + space); 123 | // raise the image and push it right to center it 124 | // self.imageEdgeInsets = UIEdgeInsetsMake(- (totalHeight - imageSize.height), titleSize.width/2.0, 0.0, - titleSize.width); 125 | self.imageEdgeInsets = UIEdgeInsetsMake(-(totalHeight - imageSize.height), (self.frame.size.width - imageSize.width)/2.0, 0.0, 0); 126 | // lower the text and push it left to center it 127 | self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (totalHeight - titleSize.height),0.0); 128 | } 129 | @end 130 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoCameraPlayButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCameraPlayButton.m 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCameraPlayButton.h" 10 | #import "SDVideoCameraHeader.h" 11 | 12 | @interface SDVideoCameraPlayButton () 13 | 14 | @property(nonatomic,strong)SDVideoConfig *config; 15 | @property(nonatomic,strong)CAShapeLayer *ringShapeLayer; 16 | @property(nonatomic,strong)CALayer *mainLayer; 17 | @property(nonatomic,strong)UIBezierPath *normalPath; 18 | @property(nonatomic,strong)UIBezierPath *selectMinPath; 19 | @property(nonatomic,strong)UIBezierPath *selectMaxPath; 20 | @property(nonatomic,assign)CGFloat mainLayerScale; 21 | 22 | @end 23 | 24 | @implementation SDVideoCameraPlayButton 25 | 26 | - (instancetype)initWithFrame:(CGRect)frame config:(SDVideoConfig *)config { 27 | 28 | if (self = [super initWithFrame:frame]) { 29 | self.layer.masksToBounds = NO; 30 | self.mainLayerScale = 1; 31 | self.config = config; 32 | [self.layer addSublayer:self.ringShapeLayer]; 33 | [self.layer addSublayer:self.mainLayer]; 34 | } 35 | return self; 36 | } 37 | 38 | #pragma mark - 懒加载 39 | 40 | - (CAShapeLayer *)ringShapeLayer { 41 | 42 | if (_ringShapeLayer == nil) { 43 | _ringShapeLayer = [[CAShapeLayer alloc] init]; 44 | _ringShapeLayer.strokeColor = [UIColor hexStringToColor:self.config.tintColor alpha:0.5].CGColor; 45 | _ringShapeLayer.fillColor = [UIColor clearColor].CGColor; 46 | _ringShapeLayer.path = self.normalPath.CGPath; 47 | _ringShapeLayer.lineWidth = 8; 48 | } 49 | return _ringShapeLayer; 50 | } 51 | 52 | - (CALayer *)mainLayer { 53 | 54 | if (_mainLayer == nil) { 55 | _mainLayer = [[CALayer alloc] init]; 56 | _mainLayer.backgroundColor = [UIColor hexStringToColor:self.config.tintColor].CGColor; 57 | _mainLayer.frame = CGRectMake(6, 6, self.frame.size.width - 12, self.frame.size.height - 12); 58 | _mainLayer.cornerRadius = _mainLayer.frame.size.height/2.0; 59 | _mainLayer.masksToBounds = YES; 60 | } 61 | return _mainLayer; 62 | } 63 | 64 | - (UIBezierPath *)normalPath { 65 | 66 | if (_normalPath == nil) { 67 | CGFloat radius = self.frame.size.width/2.0; 68 | _normalPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0) radius:radius startAngle:0 endAngle:2 * M_PI clockwise:false]; 69 | } 70 | return _normalPath; 71 | } 72 | 73 | - (UIBezierPath *)selectMinPath { 74 | 75 | if (_selectMinPath == nil) { 76 | CGFloat radius = self.frame.size.width/2.0 + 10; 77 | _selectMinPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0) radius:radius startAngle:0 endAngle:2 * M_PI clockwise:false]; 78 | } 79 | return _selectMinPath; 80 | } 81 | 82 | - (UIBezierPath *)selectMaxPath { 83 | 84 | if (_selectMaxPath == nil) { 85 | CGFloat radius = self.frame.size.width/2.0 + 8; 86 | _selectMaxPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0) radius:radius startAngle:0 endAngle:2 * M_PI clockwise:false]; 87 | } 88 | return _selectMaxPath; 89 | } 90 | 91 | - (void)setButtonState:(PlayButtonState)buttonState { 92 | 93 | // 状态是否已经发生了改变 94 | BOOL stateIsChange = buttonState == _buttonState ? NO : YES; 95 | _buttonState = buttonState; 96 | if (!stateIsChange) { 97 | return; 98 | } 99 | [self.mainLayer removeAllAnimations]; 100 | [self.ringShapeLayer removeAllAnimations]; 101 | switch (buttonState) { 102 | case PlayButtonStateNomal:{ 103 | _ringShapeLayer.lineWidth = 8; 104 | _ringShapeLayer.path = self.normalPath.CGPath; 105 | _mainLayer.frame = CGRectMake(6, 6, self.frame.size.width - 12, self.frame.size.height - 12); 106 | _mainLayer.cornerRadius = _mainLayer.frame.size.height/2.0; 107 | _mainLayer.masksToBounds = YES; 108 | _mainLayerScale = 1; 109 | break; 110 | } 111 | case PlayButtonStateTouch:{ 112 | self.mainLayer.cornerRadius = 15.0f; 113 | CABasicAnimation *sizeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 114 | sizeAnimation.fromValue = @(_mainLayerScale); 115 | sizeAnimation.toValue = @(0.6f); 116 | sizeAnimation.fillMode = kCAFillModeForwards; 117 | sizeAnimation.repeatCount = 1; 118 | sizeAnimation.duration = 0.3f; 119 | sizeAnimation.removedOnCompletion = NO; 120 | [self.mainLayer addAnimation:sizeAnimation forKey:@"sizeAnimation"]; 121 | [self addRingShapeLayerAnimationAction]; 122 | _mainLayerScale = 0.5; 123 | break; 124 | } 125 | case PlayButtonStateMove:{ 126 | CABasicAnimation *sizeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 127 | sizeAnimation.fromValue = @(_mainLayerScale); 128 | sizeAnimation.toValue = @(0); 129 | sizeAnimation.fillMode = kCAFillModeForwards; 130 | sizeAnimation.repeatCount = 1; 131 | sizeAnimation.duration = 0.3f; 132 | sizeAnimation.removedOnCompletion = NO; 133 | [self.mainLayer addAnimation:sizeAnimation forKey:@"sizeAnimation"]; 134 | [self addRingShapeLayerAnimationAction]; 135 | _mainLayerScale = 0; 136 | break; 137 | } 138 | } 139 | } 140 | 141 | - (void)addRingShapeLayerAnimationAction { 142 | 143 | CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; 144 | pathAnimation.fromValue = (id)self.selectMinPath.CGPath; 145 | pathAnimation.toValue = (id)self.selectMaxPath.CGPath; 146 | pathAnimation.duration = 0.5f; 147 | pathAnimation.fillMode = kCAFillModeForwards; 148 | pathAnimation.autoreverses = YES; 149 | pathAnimation.removedOnCompletion = NO; 150 | pathAnimation.repeatCount = MAXFLOAT; 151 | CABasicAnimation *lineWidthAnimation = [CABasicAnimation animationWithKeyPath:@"lineWidth"]; 152 | lineWidthAnimation.fromValue = @(8); 153 | lineWidthAnimation.toValue = @(12); 154 | lineWidthAnimation.duration = 0.5f; 155 | lineWidthAnimation.fillMode = kCAFillModeForwards; 156 | lineWidthAnimation.autoreverses = YES; 157 | lineWidthAnimation.removedOnCompletion = NO; 158 | lineWidthAnimation.repeatCount = MAXFLOAT; 159 | [self.ringShapeLayer addAnimation:pathAnimation forKey:@"pathAnimation"]; 160 | [self.ringShapeLayer addAnimation:lineWidthAnimation forKey:@"lineWidthAnimation"]; 161 | } 162 | 163 | 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoCameraAuthoView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCameraAuthoView.m 3 | // VideoCameraDemo 4 | // 5 | // Created by 王巍栋 on 2020/4/29. 6 | // Copyright © 2020 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCameraAuthoView.h" 10 | #import "UIColor+HexStringColor.h" 11 | #import "SDVideoCaptureManager.h" 12 | #import "UIView+Extension.h" 13 | 14 | @interface SDVideoCameraAuthoView () 15 | 16 | @property(nonatomic,strong)UILabel *titleLabel; 17 | @property(nonatomic,strong)UILabel *subTitleLabel; 18 | @property(nonatomic,strong)UIButton *cameraAuthoButton; 19 | @property(nonatomic,strong)UIButton *microAuthoButton; 20 | 21 | @end 22 | 23 | @implementation SDVideoCameraAuthoView 24 | 25 | - (instancetype)initWithFrame:(CGRect)frame { 26 | 27 | if (self = [super initWithFrame:frame]) { 28 | self.backgroundColor = [UIColor hexStringToColor:@"000000" alpha:0.8]; 29 | self.userInteractionEnabled = YES; 30 | [self addSubview:self.titleLabel]; 31 | [self addSubview:self.subTitleLabel]; 32 | [self addSubview:self.cameraAuthoButton]; 33 | [self addSubview:self.microAuthoButton]; 34 | [self testAuthoStateAction]; 35 | } 36 | return self; 37 | } 38 | 39 | - (UILabel *)titleLabel { 40 | 41 | if (_titleLabel == nil) { 42 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.subTitleLabel.top - 30 - 10, self.width, 30)]; 43 | _titleLabel.textColor = [UIColor hexStringToColor:@"ffffff"]; 44 | _titleLabel.font = [UIFont boldSystemFontOfSize:30]; 45 | _titleLabel.textAlignment = NSTextAlignmentCenter; 46 | _titleLabel.text = @"拍摄音乐短视频"; 47 | } 48 | return _titleLabel;; 49 | } 50 | 51 | - (UILabel *)subTitleLabel { 52 | 53 | if (_subTitleLabel == nil) { 54 | _subTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.height/2.0 - 20 - 30, self.width, 30)]; 55 | _subTitleLabel.textColor = [UIColor hexStringToColor:@"787878"]; 56 | _subTitleLabel.font = [UIFont systemFontOfSize:16]; 57 | _subTitleLabel.textAlignment = NSTextAlignmentCenter; 58 | _subTitleLabel.text = @"允许访问即可进入拍摄"; 59 | } 60 | return _subTitleLabel;; 61 | } 62 | 63 | - (UIButton *)cameraAuthoButton { 64 | 65 | if (_cameraAuthoButton == nil) { 66 | _cameraAuthoButton = [[UIButton alloc] initWithFrame:CGRectMake(10, self.height/2.0 + 20, self.width - 10 * 2, 30)]; 67 | _cameraAuthoButton.tintColor = [UIColor hexStringToColor:@"737373"]; 68 | [_cameraAuthoButton setTitle:@"启用相机访问权限" forState:UIControlStateNormal]; 69 | [_cameraAuthoButton setTitle:@" 启用相机访问权限" forState:UIControlStateSelected]; 70 | [_cameraAuthoButton setTitle:@"相机不可用" forState:UIControlStateDisabled]; 71 | [_cameraAuthoButton setTitleColor:[UIColor hexStringToColor:@"4cb0c1"] forState:UIControlStateNormal]; 72 | [_cameraAuthoButton setTitleColor:[UIColor hexStringToColor:@"737373"] forState:UIControlStateSelected]; 73 | [_cameraAuthoButton setTitleColor:[UIColor hexStringToColor:@"737373"] forState:UIControlStateDisabled]; 74 | [_cameraAuthoButton setImage:[[UIImage imageNamed:@"sd_camera_autho_open_icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateSelected]; 75 | [_cameraAuthoButton addTarget:self action:@selector(cameraAuthoButtonAction) forControlEvents:UIControlEventTouchUpInside]; 76 | } 77 | return _cameraAuthoButton; 78 | } 79 | 80 | - (UIButton *)microAuthoButton { 81 | 82 | if (_microAuthoButton == nil) { 83 | _microAuthoButton = [[UIButton alloc] initWithFrame:CGRectMake(10, self.cameraAuthoButton.bottom + 20, self.width - 10 * 2, 30)]; 84 | _microAuthoButton.tintColor = [UIColor hexStringToColor:@"737373"]; 85 | [_microAuthoButton setTitle:@"启用麦克风访问权限" forState:UIControlStateNormal]; 86 | [_microAuthoButton setTitle:@" 启用麦克风访问权限" forState:UIControlStateSelected]; 87 | [_microAuthoButton setTitle:@"麦克风不可用" forState:UIControlStateDisabled]; 88 | [_microAuthoButton setTitleColor:[UIColor hexStringToColor:@"4cb0c1"] forState:UIControlStateNormal]; 89 | [_microAuthoButton setTitleColor:[UIColor hexStringToColor:@"737373"] forState:UIControlStateSelected]; 90 | [_microAuthoButton setTitleColor:[UIColor hexStringToColor:@"737373"] forState:UIControlStateDisabled]; 91 | [_microAuthoButton setImage:[[UIImage imageNamed:@"sd_camera_autho_open_icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateSelected]; 92 | [_microAuthoButton addTarget:self action:@selector(microAuthoButtonAction) forControlEvents:UIControlEventTouchUpInside]; 93 | } 94 | return _microAuthoButton; 95 | } 96 | 97 | #pragma mark - 点击事件 98 | 99 | - (void)testAuthoStateAction { 100 | 101 | self.cameraAuthoButton.enabled = YES; 102 | self.cameraAuthoButton.selected = NO; 103 | switch ([SDVideoCaptureManager isOpenCameraAuthStatus]) { 104 | case AVAuthorizationStatusNotDetermined:case AVAuthorizationStatusDenied: 105 | self.cameraAuthoButton.selected = NO; 106 | break; 107 | case AVAuthorizationStatusRestricted: 108 | self.cameraAuthoButton.enabled = NO; 109 | self.cameraAuthoButton.selected = YES; 110 | break; 111 | case AVAuthorizationStatusAuthorized: 112 | self.cameraAuthoButton.selected = YES; 113 | break; 114 | } 115 | 116 | self.microAuthoButton.enabled = YES; 117 | self.microAuthoButton.selected = NO; 118 | switch ([SDVideoCaptureManager isOpenMicrophoneAuthStatus]) { 119 | case AVAuthorizationStatusNotDetermined:case AVAuthorizationStatusDenied: 120 | self.microAuthoButton.selected = NO; 121 | break; 122 | case AVAuthorizationStatusRestricted: 123 | self.microAuthoButton.enabled = NO; 124 | self.microAuthoButton.selected = YES; 125 | break; 126 | case AVAuthorizationStatusAuthorized: 127 | self.microAuthoButton.selected = YES; 128 | break; 129 | } 130 | 131 | if ([SDVideoCaptureManager isOpenCameraAuthStatus] == AVAuthorizationStatusAuthorized && 132 | [SDVideoCaptureManager isOpenMicrophoneAuthStatus] == AVAuthorizationStatusAuthorized) { 133 | [UIView animateWithDuration:0.2 animations:^{ 134 | self.top = self.height; 135 | } completion:^(BOOL finished) { 136 | [self removeFromSuperview]; 137 | }]; 138 | if (_delegate != nil && [_delegate respondsToSelector:@selector(userOpenAllDerviceAuthoAction)]) { 139 | [_delegate userOpenAllDerviceAuthoAction]; 140 | } 141 | } 142 | } 143 | 144 | - (void)cameraAuthoButtonAction { 145 | 146 | if (self.cameraAuthoButton.selected) { 147 | return; 148 | } 149 | 150 | switch ([SDVideoCaptureManager isOpenCameraAuthStatus]) { 151 | case AVAuthorizationStatusNotDetermined: { 152 | [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { 153 | dispatch_async(dispatch_get_main_queue(), ^{ 154 | [self testAuthoStateAction]; 155 | }); 156 | }]; 157 | break; 158 | } 159 | case AVAuthorizationStatusRestricted: { 160 | self.cameraAuthoButton.enabled = NO; 161 | self.cameraAuthoButton.selected = YES; 162 | break; 163 | } 164 | case AVAuthorizationStatusDenied: { 165 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; 166 | break; 167 | } 168 | case AVAuthorizationStatusAuthorized: { 169 | self.cameraAuthoButton.selected = YES; 170 | break; 171 | } 172 | } 173 | } 174 | 175 | - (void)microAuthoButtonAction { 176 | 177 | if (self.microAuthoButton.selected) { 178 | return; 179 | } 180 | 181 | switch ([SDVideoCaptureManager isOpenMicrophoneAuthStatus]) { 182 | case AVAuthorizationStatusNotDetermined: { 183 | [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) { 184 | dispatch_async(dispatch_get_main_queue(), ^{ 185 | [self testAuthoStateAction]; 186 | }); 187 | }]; 188 | break; 189 | } 190 | case AVAuthorizationStatusRestricted: { 191 | self.microAuthoButton.enabled = NO; 192 | self.microAuthoButton.selected = YES; 193 | break; 194 | } 195 | case AVAuthorizationStatusDenied: { 196 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; 197 | break; 198 | } 199 | case AVAuthorizationStatusAuthorized: { 200 | self.microAuthoButton.selected = YES; 201 | break; 202 | } 203 | } 204 | 205 | } 206 | 207 | @end 208 | -------------------------------------------------------------------------------- /SDVideoCamera/Camera/SDVideoCameraController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDVideoCameraController.m 3 | // FamilyClassroom 4 | // 5 | // Created by 王巍栋 on 2020/1/13. 6 | // Copyright © 2020 Dong. All rights reserved. 7 | // 8 | 9 | #import "SDVideoCameraController.h" 10 | #import "SDVideoPreviewViewController.h" 11 | #import "SDVideoAlbumViewController.h" 12 | #import "SDVideoCameraAuthoView.h" 13 | #import "SDVideoCaptureManager.h" 14 | #import "SDAudioPlayerManager.h" 15 | #import "SDVideoLoadingView.h" 16 | #import "SDVideoDataManager.h" 17 | #import "SDVideoUtils.h" 18 | 19 | @interface SDVideoCameraController () 20 | 21 | @property(nonatomic,strong)SDVideoConfig *config; 22 | @property(nonatomic,strong)UIView *videoView; 23 | @property(nonatomic,strong)SDVideoCaptureManager *captureManager; 24 | @property(nonatomic,strong)SDAudioPlayerManager *audioManager; 25 | 26 | @end 27 | 28 | @implementation SDVideoCameraController 29 | 30 | - (instancetype)initWithCameraConfig:(SDVideoConfig *)config { 31 | 32 | if (self = [super init]) { 33 | self.config = config; 34 | [config configDataSelfCheckAction]; 35 | [SDVideoDataManager defaultManager].config = config; 36 | [SDVideoDataManager defaultManager].cameraState = VideoCameraStateIdle; 37 | [[SDVideoDataManager defaultManager] addObserver:self forKeyPath:@"cameraState" options:NSKeyValueObservingOptionNew context:nil]; 38 | } 39 | return self; 40 | } 41 | 42 | - (void)viewDidLoad { 43 | [super viewDidLoad]; 44 | [self.view addSubview:self.videoView]; 45 | [self.view addSubview:self.menuView]; 46 | self.view.backgroundColor = [UIColor blackColor]; 47 | } 48 | 49 | - (void)viewWillAppear:(BOOL)animated { 50 | 51 | [super viewWillAppear:animated]; 52 | if ([self.menuView isOpenAllDeviceAuthoStateAction]) { 53 | [self captureManager]; 54 | } 55 | [self setNeedsStatusBarAppearanceUpdate]; 56 | [self.navigationController setNavigationBarHidden:YES]; 57 | } 58 | 59 | - (void)closeButtonAction { 60 | 61 | if ([SDVideoDataManager defaultManager].videoNumber != 0) { 62 | UIAlertController *alertViewController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; 63 | UIAlertAction *reloadAction = [UIAlertAction actionWithTitle:@"重新拍摄" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { 64 | [[SDVideoDataManager defaultManager] deleteAllVideoModel]; 65 | }]; 66 | UIAlertAction *exitAction = [UIAlertAction actionWithTitle:@"退出" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 67 | [self dismissViewControllerAnimated:YES completion:nil]; 68 | }]; 69 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; 70 | [alertViewController addAction:reloadAction]; 71 | [alertViewController addAction:exitAction]; 72 | [alertViewController addAction:cancelAction]; 73 | [self presentViewController:alertViewController animated:YES completion:nil]; 74 | } else { 75 | [self dismissViewControllerAnimated:YES completion:nil]; 76 | } 77 | } 78 | 79 | #pragma mark - 懒加载 80 | 81 | - (UIView *)videoView { 82 | 83 | if (_videoView == nil) { 84 | _videoView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 85 | _videoView.backgroundColor = [UIColor blackColor]; 86 | _videoView.layer.masksToBounds = YES; 87 | } 88 | return _videoView; 89 | } 90 | 91 | - (SDVideoCameraMenuView *)menuView { 92 | 93 | if (_menuView == nil) { 94 | _menuView = [[SDVideoCameraMenuView alloc] initWithFrame:[UIScreen mainScreen].bounds cameraConfig:self.config]; 95 | _menuView.superViewController = self; 96 | _menuView.delegate = self; 97 | [_menuView.closeButton addTarget:self action:@selector(closeButtonAction) forControlEvents:UIControlEventTouchUpInside]; 98 | } 99 | return _menuView; 100 | } 101 | 102 | - (SDVideoCaptureManager *)captureManager { 103 | 104 | if (_captureManager == nil) { 105 | _captureManager = [[SDVideoCaptureManager alloc] initWithVideoView:self.videoView config:self.config]; 106 | } 107 | return _captureManager; 108 | } 109 | 110 | - (SDAudioPlayerManager *)audioManager { 111 | 112 | if (_audioManager == nil) { 113 | _audioManager = [[SDAudioPlayerManager alloc] initWithConfig:self.config]; 114 | } 115 | return _audioManager; 116 | } 117 | 118 | #pragma mark - 控制层回调方法 119 | 120 | - (void)userFinishMergeVideoAction { 121 | 122 | [SDVideoLoadingView showLoadingAction]; 123 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 124 | 125 | NSMutableArray *videoAssetArray = [NSMutableArray arrayWithCapacity:16]; 126 | for (SDVideoDataModel *dataModel in [SDVideoDataManager defaultManager].videoDataArray) { 127 | AVAsset *asset = [AVAsset assetWithURL:dataModel.pathURL]; 128 | [videoAssetArray addObject:asset]; 129 | } 130 | 131 | AVPlayerItem *playItem = [SDVideoUtils mergeMediaPlayerItemActionWithAssetArray:videoAssetArray 132 | timeRange:kCMTimeRangeZero 133 | bgAudioAsset:nil 134 | originalVolume:1 135 | bgAudioVolume:0]; 136 | dispatch_async(dispatch_get_main_queue(), ^{ 137 | [SDVideoLoadingView dismissLoadingAction]; 138 | SDVideoPreviewViewController *previewViewController = [[SDVideoPreviewViewController alloc] initWithCameraConfig:self.config playItem:playItem videoAssetArray:videoAssetArray playTimeRange:kCMTimeRangeZero]; 139 | [self.navigationController pushViewController:previewViewController animated:YES]; 140 | }); 141 | 142 | }); 143 | } 144 | 145 | - (void)deleteLaseVideoDataAction { 146 | 147 | [self.audioManager seekToTime:CMTimeMake([SDVideoDataManager defaultManager].totalVideoTime, 1.0)]; 148 | } 149 | 150 | - (void)userClickOutMenuButtonWithButtonType:(VideoMenuType)menuType { 151 | 152 | switch (menuType) { 153 | case VideoMenuTypesTurnOver:{ 154 | [self.captureManager exchangeCameraInputAction]; 155 | break; 156 | } 157 | case VideoMenuTypesFlashlight:{ 158 | [self.captureManager openCameraFlashLight]; 159 | break; 160 | } 161 | default: 162 | break; 163 | } 164 | } 165 | 166 | - (void)userChangeVideoZoomFactorWithScale:(CGFloat)scale orientation:(TouchMoveOrientation)orientation { 167 | 168 | [self.captureManager setVideoZoomFactorWithScale:scale orientation:orientation]; 169 | } 170 | 171 | - (void)userEndChangeVideoZoomFactor { 172 | 173 | [self.captureManager reloadCurrentVideoZoomFactorAction]; 174 | } 175 | 176 | - (void)userClickAlbumAction { 177 | 178 | SDVideoAlbumViewController *albumViewController = [[SDVideoAlbumViewController alloc] initWithCameraConfig:self.config]; 179 | UINavigationController *albumNavigationController = [[UINavigationController alloc] initWithRootViewController:albumViewController]; 180 | albumNavigationController.modalPresentationStyle = UIModalPresentationFullScreen; 181 | [self.navigationController presentViewController:albumNavigationController animated:YES completion:nil]; 182 | } 183 | 184 | - (void)userOpenAllDerviceAuthoAction { 185 | 186 | [self captureManager]; 187 | } 188 | 189 | #pragma mark - 监听方法 190 | 191 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 192 | 193 | if ([keyPath isEqualToString:@"cameraState"]) { 194 | switch ([SDVideoDataManager defaultManager].cameraState) { 195 | case VideoCameraStateIdle:{ 196 | break; 197 | } 198 | case VideoCameraStateInProgress:{ 199 | [self.audioManager play]; 200 | [self.captureManager startVideoRecordingAction]; 201 | break; 202 | } 203 | case VideoCameraStatePause:{ 204 | [self.audioManager pause]; 205 | [self.captureManager pauseOrStopVideoRecordingAction];//停止录制 206 | break; 207 | } 208 | case VideoCameraStateStop: { 209 | [self.audioManager pause]; 210 | [self.captureManager pauseOrStopVideoRecordingAction];//停止录制 211 | break; 212 | } 213 | } 214 | } 215 | } 216 | 217 | #pragma mark - 系统方法 218 | 219 | - (BOOL)prefersStatusBarHidden { 220 | 221 | return YES; 222 | } 223 | 224 | - (void)dealloc { 225 | 226 | [[SDVideoDataManager defaultManager] removeObserver:self forKeyPath:@"cameraState"]; 227 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 228 | } 229 | 230 | 231 | @end 232 | --------------------------------------------------------------------------------