iOS开发一个制作Live Photo的工具
1.livePhoto简介
livePhoto是iOS 9.0 之后系统相机提供的拍摄动态照片的功能,但是仅在6S+,iOS 9.0+设备可用。拍摄完livePhoto之后,只需要在相册按压livePhoto相片即可动态的播放。livePhoto还可以设置为动态壁纸。如果只能用相机拍摄的livePhoto设置为动态壁纸,这不能满足我们的需求了。如果可以将视频转换为livePhoto那就完美了。如果要实现这个功能就要了解live Photo的本质了。
2.livePhoto的本质
其实livePhoto的本质是一张jpg图片+一段mov视频另外再加入一些信息一起写入到相册内即可生成livePhoto,核心的写入代码是我在github找到的,但是Swift版,我将它翻译为OC版。Swift版写入livePhotoDemo。
3.涉及到的技术
1)相册数据的读取与写入;
2)share Extension的使用;
3)视频提取某一帧图片;
4)不同进程间的通讯;
5)PHLivePhotoView展示livePhoto图片;
4.实现livePhoto制作工具
主界面UI如下图,噗。。请原谅我毫无美感的页面设计,勿喷。

顶部一个AVplayer实现本地视频的播放,AVplayer下面一个UISlider可以选择视频的哪一帧作为livePhoto的封面图。UISlider下面一个PHLivePhotoView按压可以预览livePhoto的效果图。
1)如何提取视频中的某一帧?
/**
获取视频的 某一帧
@param currentTime 某一时刻单位 s
@param path 视频路径
@return return 返回image
*/
- (UIImage *)getVideoImageWithTime:(Float64)currentTime videoPath:(NSURL *)path {
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:path options:nil];
// float fps = [[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] nominalFrameRate];
// NSLog(@"视频帧率%f",fps);
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
gen.appliesPreferredTrackTransform = YES;
gen.requestedTimeToleranceAfter = kCMTimeZero;// 精确提取某一帧,需要这样处理
gen.requestedTimeToleranceBefore = kCMTimeZero;// 精确提取某一帧,需要这样处理
CMTime time = CMTimeMakeWithSeconds(currentTime, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
UIImage *img = [[UIImage alloc] initWithCGImage:image];
CMTimeShow(actualTime);
CGImageRelease(image);
return img;
}
2)图片与视频分别经过特定的处理然后分别存储为JPG 与 MOV格式。
将视频转为livePhoto存入相册,iOS原生API并没有给出这样的方法。而能将视频转为livePhoto,是源于SwiftlivePhotoDemo作者对livePhoto细心观察。我这里只是借花献佛转化为OC版本。

使用上图中的两个文件可以将图片与视频分别经过特定的处理然后分别存储为JPG 与 MOV格式
3)将处理后的JPG 与 MOV一同存储生成livePhoto
首先引入#import <Photos/Photos.h>框架,调用performChanges方法存储,具体代码如下
+ (void)writeLivePhotoWithVideo:(NSURL *)videoPath image:(NSURL *)imagePath result:(void(^)(BOOL res))result {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest * request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto fileURL:imagePath options:nil];
[request addResourceWithType:PHAssetResourceTypePairedVideo fileURL:videoPath options:nil];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success) {
//保存成功
NSLog(@"保存成功");
}
if (result) {
result(success);
}
}];
}
自此一个简单的livePhoto制作工具完成。但是为了用户体验,我们还要进行素材选取途径拓宽。
4)拓宽素材选取的途径
a.从相册选取素材
从相册选取素材,这里使用了UIImagePickerController来处理,具体代码如下:
- (void)chooseVideoFromPhotoLibraryResult:(ResultBlock)result {
UIImagePickerController *imagePick = [[UIImagePickerController alloc] init];
imagePick.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
imagePick.mediaTypes = @[@"public.movie"];//只获取视频数据
imagePick.delegate = self;
self.result = result;
[[[UIApplication sharedApplication] delegate].window.rootViewController presentViewController:imagePick animated:YES completion:nil];
}
// UIImagePickerController 的选择结果的代理方法。
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
[picker dismissViewControllerAnimated:YES completion:nil];
if ([[info[@"UIImagePickerControllerMediaURL"] absoluteString] length]) {
if (self.result) {
self.result(info[@"UIImagePickerControllerMediaURL"], YES);
}
}
}
b.使用share Extension,让用户可以从其他App中获取素材
我们在项目工程下file-->New-->target-->share Extension-->Nest 创建一个share Extension如下图:


这篇文章详细解读了share Extension,如有需要可以先看一下
由于没有使用原生的share Extension UI所以这里,我们先把系统生成的.h+.m+MainInterface.storyboard这三个文件删除。然后创建一个viewController(继承UIviewController)+Xib。
在viewdidload里实现下面的代码,这些代码是为了获取用户选择的视频地址的操作。
__weak typeof (self) ws = self;
[self.extensionContext.inputItems enumerateObjectsUsingBlock:^(NSExtensionItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj.attachments enumerateObjectsUsingBlock:^(NSItemProvider * _Nonnull itemProvider, NSUInteger idx, BOOL * _Nonnull stop) {
if ([itemProvider hasItemConformingToTypeIdentifier:itemProvider.registeredTypeIdentifiers[0]]) {
[itemProvider loadItemForTypeIdentifier:itemProvider.registeredTypeIdentifiers[0] options:nil completionHandler:^(id<NSSecureCoding> _Nullable item, NSError * _Null_unspecified error) {
NSLog(@"%@",item);
if ([(NSObject *)item isKindOfClass:[NSURL class]]) {
NSString * lastAppending = [[[(NSURL*)item absoluteString] componentsSeparatedByString:@"/"] lastObject];
NSFileManager *fileManger = [NSFileManager defaultManager];
NSURL *groupFile = [fileManger containerURLForSecurityApplicationGroupIdentifier:@"group.com.livephoto"];
NSURL *fileUrl = [groupFile URLByAppendingPathComponent:lastAppending];
//移除旧的数据
[fileManger removeItemAtURL:fileUrl error:nil];
NSError *error = nil;
[fileManger copyItemAtURL:(NSURL *)item toURL:fileUrl error:&error];
if (!error) {
ws.lastAppending = lastAppending;
dispatch_async(dispatch_get_main_queue(), ^{
[ws initVideoWithPath:fileUrl];
});
NSLog(@"存入成功!!!");
}
}
}];
*stop = YES;
}
}];
*stop = YES;
}];
这里要注意,由于Extension 与 宿主app分别属于不同的进程,由于iOS是沙盒存储机制。所以不同的进程是不能直接相互访问数据的。但是同一个公司的App 可以通过AppGroup来设置一个公共的存储空间,从而达到 不同的进行相互访问数据。这里我们也是使用AppGroup 把素材资源存储在公共的区域。方便宿主app访问素材数据。具体AppGroup如何来实现?可以参考这篇文文章:iOS App Group实现数据共享
如何唤醒宿主App处理素材数据?
其实iOS提供的Extension当中只有today widget 可以通过url schemes的方式唤醒。其他都是不能唤醒宿主App的。但是通过下面的方法还是可以强行通过url schemes的方式唤醒宿主app的,但是不知道是否可以通过审核?我看到京东的 拍照购 是可以唤醒京东app 的。
- (IBAction)handleVideo:(UIButton *)sender {
UIResponder *responder = self;
while (responder) {
if ([responder respondsToSelector:@selector(openURL:)]) {
[responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:[NSString stringWithFormat:@"livePhoto://data=%@",_lastAppending]]];
break;
}
responder = [responder nextResponder];
}
}
5.项目文件截图

6.注意点
运行demo前请先配置好自己的环境,以及把App Group换成自己的。最后看一下项目运行效果吧。
iOS开发一个制作Live Photo的工具
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
iOS开发一个制作Live Photo的工具的更多相关文章
- iOS 开发人员不可缺少的75个工具
原文出处: Ben Scheirman 译文出处: Njuxjy 假设你去到一位熟练的木匠的工作室,你总是能发现他/她有一堆工具来完毕不同的任务. 软件开发相同如此. 你能够从软件开发人员怎样使用工具 ...
- iOS开发一个用户登录注册模块需要解决的坑
最近和另外一位同事负责公司登录和用户中心模块的开发工作,开发周期计划两周,减去和产品和接口的协调时间,再减去由于原型图和接口的问题,导致强迫症纠结症状高发,情绪不稳定耗费的时间,能在两周基本完成也算是 ...
- iOS开发~制作同时支持armv7,armv7s,arm64,i386,x86_64的静态库.a
一.概要 平时项目开发中,可能使用第三方提供的静态库.a,如果.a提供方技术不成熟,使用的时候就会出现问题,例如: 在真机上编译报错:No architectures to compile for ( ...
- iOS开发~制作同时支持armv7,armv7s,arm64,i386,x86_64的静态库.a以及 FrameWork 的创建
armv7,armv7s,arm64,i386,x86_64 详解 一.概要 平时项目开发中,可能使用第三方提供的静态库.a,如果.a提供方技术不成熟,使用的时候就会出现问题,例如: 在真机上编译报错 ...
- iOS开发之--制作属于自己的frameWork
开发的时候,有时候,我们会遇到协同开发,在协同开发的时候,每个开发者都会创建自己的工具类,还有就是当一个项目需要嵌套到另一个项目里面,这些时候,如果能把所需的部分打包成framework,会方便很多, ...
- IOS开发中制作属于自己的静态库.a、资源库.bundle、.framework
一.什么是库 库实际上是一种代码共享的方式,主要用于代码重用和源码隐藏,通常分为动态库和静态库. 静态库:链接时完整的拷贝至可执行文件中,被多次使用就有多份冗余拷贝. 动态库:链接时不复 ...
- 分享iOS开发常用(三方类库,工具,高仿APP,实用网站,技术干货)
一 . JSONModel (三方类库会有更新,建议大家在线下载) http://pan.baidu.com/s/1i5ybP1z 二.AFNetworkiong http://pan.baidu. ...
- IOS封装一个微信聊天的输入工具
1.实现微信的输入工具 实现了大部分功能,各模块实现的很清晰,有利于更好的二次开发(适合自己的需求),我自己总结出来的, 可以更快的让你实现输入工具,不需要扩展的也可以很方便的使用这个输入工具. 1) ...
- iOS 开发技巧-制作环形进度条
有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现. 先看一下这篇博客,博客地址:ht ...
随机推荐
- noip 2016 day2 t1组合数问题
题目描述 组合数表示的是从n个物品中选出m个物品的方案数.举个例子,从(1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3)这三种选择方法.根据组合数的定 义,我们可以给出计算 ...
- 【推导】【贪心】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem D. Clones and Treasures
给你一行房间,有的是隐身药水,有的是守卫,有的是金币. 你可以任选起点,向右走,每经过一个药水或金币就拿走,每经过一个守卫必须消耗1个药水,问你最多得几个金币. 药水看成左括号,守卫看成右括号, 就从 ...
- 【计算几何】【极角排序】Gym - 101174B - Bribing Eve
把每件物品当成平面上一个点,将第一件物品放在原点.那个权重值相当于一条直线,于是相当于直线绕原点转一圈,统计上侧点的数量. 队友的代码: #include <cmath> #include ...
- 实验四实验报告————Android基础开发
实验四实验报告----Android基础开发 任务一 关于R类 关于apk文件 实验成果 任务二 活动声明周期 实验成果 任务三 关于PendingIntent类 实验成果 任务四 关于布局 实验成果 ...
- 让你的WPF程序在Win7下呈现Win8风格主题
今天在Win8下使用了一个我之前写的一个WPF程序的时候,发现现在也支持Win8效果了(记得以前的.net 4.0的版本是不支持的).由于WPF的控件是自绘的,并不受系统主题所控制,也就是说.net ...
- VisualStudio 发布代码的一个坑
现象:为了测试把时间改为2016-1-1,测试完成后改为实际时间.以后每次发布代码,生成的dll还是2016-1-1,而非发布时间 导致问题:生成的dll和实际代码不匹配,原因不明 解决过程: 1.修 ...
- 利用pca分析fmri的生理噪声
A kernel machine-based fMRI physiological noise removal method 关于,fmri研究中,生理噪声去除的价值:一.现在随着技术的提升,高场fm ...
- Git 学习(一)简介及安装
Git 简介及安装 Git是目前世界上最先进的分布式版本控制系统(没有之一).它的诞生也颇具传奇,Linux创始人Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!有兴趣的话,可 ...
- javascript不依赖JS加载顺序事件对象实现
背景: 在现在WEB开发中,稍复杂一点的页面,都会涉及到多个模块,尤其是类似seajs.LABjs.requireJS等模块工具出来后,前端开发者分模块开发已经慢慢变成一种习惯了,但是多个模块间的常常 ...
- python学习:Windows 下 Python easy_install 的安装
Windows 下 Python easy_install 的安装 下载安装python安装工具下载地址:http://pypi.python.org/pypi/setuptools 可以找到 ...