├── 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 |
--------------------------------------------------------------------------------