iOS图片,视频上传视频内容旋转
#前言
我最近在接手一个智能盒子的iOS应用,上面有一个功能是这样的。把你本地的照片和视频可以甩屏到你绑定的盒子上。
我的上一位前辈做的时候必须要求再同一个局域网,但是当我做的时候要求不同的局域网也要实现这样的一个功能,优化用户的使用感受。
#那么 我们下面就进入正题。
#内容一:图片上传
我做的图片上传是用的AF,原理就是把你想上传的照片取出来,如果有文件大小的要求就先做相应的图片压缩。
然后用AFHTTPSessionManager 类去做的上传,下面就是代码:
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];[session.requestSerializer willChangeValueForKey:@"timeoutInterval"];session.requestSerializer.timeoutInterval = 60.f;[session.requestSerializer didChangeValueForKey:@"timeoutInterval"];session.responseSerializer = [AFHTTPResponseSerializer serializer];NSString *imageTitle =_imageSource[pageIndex].title;imageTitle = [imageTitle substringToIndex:imageTitle.length-4];NSDictionary *params = @{@"fileType":@"jpg",@"fileName":imageTitle};[session POST:@"你上传的接口地址" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {for (NSString *key in dict.allKeys) {[formData appendPartWithFileData:[dict objectForKey:key] name:@"myFile" fileName:[NSString stringWithFormat:@"%@.jpg",key] mimeType:@"image/jpeg"];}} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {}];
这里主要就是和你们的后台确认好相应的参数设置就好了。
#内容二:视频上传
视频上传和图片上传其实是类似的,只不过就是参数的设置不一样而已。也是用上面的方法。关键也是设置好参数。
在这里我想说的是,有的时候视频太大要做相应的压缩处理。因为我之前对视频这面接触的比较少,也上网找了一些资料然后看到这样的一个方法:
- (void)lowQuailtyWithInputURL:(NSURL*)inputURLoutputURL:(NSURL*)outputURLblockHandler:(void (^)(AVAssetExportSession*))handler
{
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];session.outputURL = outputURL;session.outputFileType = AVFileTypeQuickTimeMovie;[session exportAsynchronouslyWithCompletionHandler:^(void){handler(session);}];
}
通过这个方法就可以对视频进行相应的压缩处理。
#下面就是视频内容的旋转问题了。
一开始我听到了这个需求的时候我的脑子里真的是瞬间万马飞奔啊!! 这是什么鬼需求啊!鬼知道我经历了什么?
我想,那我就上网找一下吧!我找了一下,还真的有这么样的技术博客。但是一上来就是把他的代码网上一贴。我先大概的浏览了一下那代码的长度。写的我实在是没有耐心去仔细的看到底是怎么实现的。我就关掉了。可是后来一看,也没有别的什么博客供我参考了。在我走投无路的时候,我看到了这么一个博客,说是Apple自己就有Demo,我就抱着好奇的态度去看了看。下载了那个Demo仔细的研究了一下。果然就好使了。 那么,接下来就说一下。
再旋转视频之前我们先要确认一下,这个视频是要旋转多少度。
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];NSInteger degress;if([tracks count] > 0) {AVAssetTrack *videoTrack = [tracks objectAtIndex:0];CGAffineTransform t = videoTrack.preferredTransform;//这里的矩阵有旋转角度,转换一下即可if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){// Portraitdegress = 90;}else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){// PortraitUpsideDowndegress = 270;}else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){// LandscapeRightdegress = 0;}else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){// LandscapeLeftdegress = 180;}}
这样我们就可以通过degress来确认旋转的角度了。
那么我们接下来就开始旋转视频
AVMutableVideoCompositionInstruction *instruction = nil;AVMutableVideoCompositionLayerInstruction *layerInstruction = nil;CGAffineTransform t1;CGAffineTransform t2;AVAssetTrack *assetVideoTrack = nil;AVAssetTrack *assetAudioTrack = nil;// Check if the asset contains video and audio tracksif ([[asset tracksWithMediaType:AVMediaTypeVideo] count] != 0) {assetVideoTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0];}if ([[asset tracksWithMediaType:AVMediaTypeAudio] count] != 0) {assetAudioTrack = [asset tracksWithMediaType:AVMediaTypeAudio][0];}CMTime insertionPoint = kCMTimeZero;NSError *error = nil;// Step 1// Create a composition with the given asset and insert audio and video tracks into it from the assetif (!mutableComposition) {// Check whether a composition has already been created, i.e, some other tool has already been applied// Create a new compositionmutableComposition = [AVMutableComposition composition];// Insert the video and audio tracks from AVAssetif (assetVideoTrack != nil) {AVMutableCompositionTrack *compositionVideoTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:assetVideoTrack atTime:insertionPoint error:&error];}if (assetAudioTrack != nil) {AVMutableCompositionTrack *compositionAudioTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:assetAudioTrack atTime:insertionPoint error:&error];}}
// // Step 2
// // Translate the composition to compensate the movement caused by rotation (since rotation would cause it to move out of frame)
// t1 = CGAffineTransformMakeTranslation(assetVideoTrack.naturalSize.height, 0.0);
// // Rotate transformation
// t2 = CGAffineTransformRotate(t1, degreesToRadians(90));if (degress == 0) {t1 = CGAffineTransformMakeTranslation(0.0, 0.0);t2 = CGAffineTransformRotate(t1, degreesToRadians(0));}else if (degress == 90){t1 = CGAffineTransformMakeTranslation(assetVideoTrack.naturalSize.height, 0.0);t2 = CGAffineTransformRotate(t1, degreesToRadians(90));}else if (degress == 180){t1 = CGAffineTransformMakeTranslation(assetVideoTrack.naturalSize.width, assetVideoTrack.naturalSize.height);t2 = CGAffineTransformRotate(t1, degreesToRadians(180));}else if (degress == 270){t1 = CGAffineTransformMakeTranslation(0,assetVideoTrack.naturalSize.height*1.78);t2 = CGAffineTransformRotate(t1, degreesToRadians(-90));}// Step 3// Set the appropriate render sizes and rotational transformsif (!mutableVideoComposition) {// Create a new video compositionmutableVideoComposition = [AVMutableVideoComposition videoComposition];if (degress == 0 || degress == 180) {mutableVideoComposition.renderSize = CGSizeMake(assetVideoTrack.naturalSize.width,assetVideoTrack.naturalSize.height);}else{mutableVideoComposition.renderSize = CGSizeMake(assetVideoTrack.naturalSize.height,assetVideoTrack.naturalSize.width);}mutableVideoComposition.frameDuration = CMTimeMake(1, 30);// The rotate transform is set on a layer instructioninstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [mutableComposition duration]);layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:(mutableComposition.tracks)[0]];[layerInstruction setTransform:t2 atTime:kCMTimeZero];} else {mutableVideoComposition.renderSize = CGSizeMake(mutableVideoComposition.renderSize.height, mutableVideoComposition.renderSize.width);// Extract the existing layer instruction on the mutableVideoCompositioninstruction = (mutableVideoComposition.instructions)[0];layerInstruction = (instruction.layerInstructions)[0];// Check if a transform already exists on this layer instruction, this is done to add the current transform on top of previous editsCGAffineTransform existingTransform;if (![layerInstruction getTransformRampForTime:[mutableComposition duration] startTransform:&existingTransform endTransform:NULL timeRange:NULL]) {[layerInstruction setTransform:t2 atTime:kCMTimeZero];} else {// Note: the point of origin for rotation is the upper left corner of the composition, t3 is to compensate for originCGAffineTransform t3 = CGAffineTransformMakeTranslation(-1*assetVideoTrack.naturalSize.height/2, 0.0);CGAffineTransform newTransform = CGAffineTransformConcat(existingTransform, CGAffineTransformConcat(t2, t3));[layerInstruction setTransform:newTransform atTime:kCMTimeZero];}}// Step 4// Add the transform instructions to the video compositioninstruction.layerInstructions = @[layerInstruction];mutableVideoComposition.instructions = @[instruction];
到这个时候呢视频的旋转已经完成了。
上面我们不是写了一个视频压缩的方法吗?把这个时候生成的mutableVideoComposition赋值给session.videoComposition = mutableVideoComposition;就好了。这样就是先旋转视频然后直接压缩完成我们的需求。
相关文章:

jackson 解析json问题
1、json串中有key为A,但指定转换的mybean中未定义属性A,会抛异常。处理:mapper.configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false),加上这一条,就没问题了,正常转换。 2、 默认的json串,如…

【转】UIColor对颜色的自定义
原文网址:http://blog.sina.com.cn/s/blog_5f19ccb10101bhqh.html 在iOS开发中,我们使用UIColor来对我们的界面进行颜色设置,一般我们通过以下两种方法使用UIColor:1,label.textColor [UIColor blueColor];2,label.textColor [U…

数据通信技术(八:OSPF单区域配置实验)
OSPF单区域配置实验(Cisco) 一.知识准备 1.掌握了OSPF动态路由协议的定义和功能; 2.掌握了OSPF动态路由协议的特征和工作原理。 二.实验目的 掌握OSPF动态路由单区域的基本配置方法和结果验证。 掌握OSPF单区域配置的作用 三ÿ…

redis在php中的使用介绍
redis介绍 redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hashs(哈希类型)。这些数据类型都 支持push/pop、add/remo…

控制发光二极管
一 LED驱动的实现原理 尽管Linux驱动直接与硬件打交道,但并不是Linux驱动直接向硬件中的内存写数据,而是与本机的I/O内存进行交互。每一个连接Linux的硬件在I/O内存中都会有映射首地址,开发板上的LED也有其映射首地址。 二 编写LED驱动 第一…

iOS 跑马灯之 TXScrollLabelView
前言 前段时间在开发一个广播的功能,网上也自己找了一些库,没有发现非常好用的,于是自己抽时间写了一个,在 Github 上发布一天收获六十多个 star,这里首先感谢大家在微博上的转发,使得 TXScrollLabelView 被…

数据通信技术(六:静态路由实验)
数据通信静态路由实验 1、R1路由的端口配置 2、R2路由的端口配置 3、R3路由器端口配置 4、互通性验证 5、拓扑结构 数据通信技术(一:IP划分) https://blog.csdn.net/qq_37823605/article/details/90345408 数据通信技术(二&#…

172. Factorial Trailing Zeroes
/**172. Factorial Trailing Zeroes *2016-6-4 by Mingyang* 首先别忘了什么是factorial,就是阶乘。那么很容易想到需要统计* (2,5)对的个数,因为2510。但是这个条件放松一下就会发现其实只要数5的个数就好了,* 因为2实在是比5要多的多。那么…
MarkdownView:Markdown 文档预览视图组件
原文链接:https://github.com/keitaoouchi/MarkdownViewMarkdownView:Markdown 文档预览视图组件。# 为开源点赞# —— 由SwiftLanguage分享MarkdownView is a WKWebView based UI element, and internally use bootstrap, highlight.js, markdown-it. H…

项目管理过程中,如何编制初步工作说明书
最近在做一个项目的时候,客户特别苛刻,在制定工作说明书的时候,费了很多周折,把很多以前做项目的时候都不怎么会专门考虑的细枝末节和例外情况都进行了详细说明和约定,但是在项目实施过程中,却发现这样的说…

数据通信技术(七:RIP路由水平分割配置)
RIP路由水平分割配置实验报告 一、知识准备 掌握RIP动态路由的定义和特征。掌握RIP路由环路的危害和解决技术。掌握水平分割的工作原理。二、实验目的 掌握路由器中RIP动态路由水平分割功能的配置方法和结果验证,并通过实验结果更好的理解水平分割的作用和原理。…

android蓝牙4.0(BLE)开发之ibeacon初步
一个april beacon里携带的信息如下 ?1<code class" hljs ">0201061AFF4C0002159069BDB88C11416BAC3F33468C2788A3044B0378C60C09417072696C426561636F6E051250002003020A0000000000000000000000</code>具体是什么意思呢 ?1234567891011121314151617181…
APP程序内部打开某个APP的AppStore页面
作者 呀咪9527 关注 2017.03.21 16:44* 字数 222 阅读 154评论 0喜欢 9最近在做内购用到了StoreKit.framework库,偶然间发现中SKStoreProductViewController这个类,查看文档后发现一个妙用,解决了我一个痛点:APP每次更新或者跳转至…

sql server 2014预览版发布
MSDN发布sql server2014预览版,如下图: SQL Server 2014新特性: 微软SQL Server部门主管Eron Kelly介绍,通过将交易处理放到内存中进行,新的SQL Server 2014在测试中能够将性能提升50倍以上。在新版本中,DB…

数据通信技术(九:OSPF特殊区域配置(Cisco))
OSPF单区域配置实验(Cisco) 一.知识准备 1、掌握了OSPF动态路由协议的定义和功能; 2、掌握了OSPF动态路由协议的特征和工作原理。 二.实验目的 1、掌握路由器中OSPF特殊区域STUB配置方法和功能验证; 2、掌握OSPF特殊区域STUB…

iOS 屏幕亮度和闪光灯控制
所用涉及框架:AVFoundation框架和ImageIO 读取屏幕亮度:[UIScreen mainScreen].brightness; 设置屏幕亮度:[[UIScreen mainScreen] setBrightness:0.5]; 获取环境亮度主要代码: - (void)getTorch {AVCaptureDevice *device [AV…

一个几何不等式的最佳常数
今天上午动用win7旗舰版64位SP1(英特尔第二代酷睿I7-2630QM 2.00GHz 4核 内存 8G)下基于maple 16平台的BOTTEMA2009费时2899.02s,消耗内存633.56M,得到使不等式 $m_{a}w_{a}m_{b}w_{b}m_{c}w_{c}\leq k\cdot s^2$ 成立的最佳常数 $k$ 为如下一 $7$ 次方程 $729k^7-7599k^6-276…

数据通信技术(十:OSPF特殊区域TOTALLY STUB配置(ZTE))
OSPF特殊区域TOTALLY STUB配置(ZTE) 一.知识准备 1、掌握了OSPF动态路由协议的定义和功能; 2、掌握了OSPF动态路由协议的特征和工作原理。 二.实验目的 1、掌握路由器中OSPF特殊区域TOTAL STUB配置方法和功能验证; 2、掌握OS…

apue第四章习题的一些拙见(不定时更新)
写在前面:最近要期末考试,看来真的是要不定时更新啦XD apue4.1: 由于在这里lstat是不跟随符号文件的,而stat是跟随符号文件的,这样一来,如果使用stat,而不使用lstat那么就无法观察到符号文件。在书上4.3姐中有提到。 a…

容器使用之vector
出处:http://blog.csdn.net/edify/article/details/4035243 C内置的数组支持容器的机制,但是它不支持容器抽象的语义。要解决此问题我们自己实现这样的类。在标准C中,用容器向量(vector)实现。容器向量也是一个类模板。…
Hyperloop 让发布简洁高效
原文链接:https://mp.weixin.qq.com/s/MZMqzaKLqQN0zJikNYEbwgHyperloop 是服务于美团点评客户端的组件发版、持续集成、App 打包构建、资源调度等各个环节的发布调度系统。名称起源于美国 Elon Musk 构想的 Hyperloop 超级高铁,象征着现代、简洁、高效。…

数据通信技术(十一:无中继的DHCP配置(ZTE))
路由器的无中继DHCP配置(ZTE) 一.知识准备 1、掌握DHCP的基本原理和作用; 2、掌握DHCP的网络架构。 二.实验目的 1、掌握中兴路由器DHCP的配置方法和功能验证; 三.实验内容 1、完成中兴路由器DHCP的基本配置和结…

小米4手机在DDMS下获取data/data目录权限
1.首先先root手机 2.进入adb adb shell su //获取root权限 mount -0 remount,rw /data //重新挂载分区为可读写(可以用 df命令查看分区情况) chmod 777 /data //更改文件夹权限可读写 3.adb 常用命令大全 1. 显示系统中全部Android平台: android list targets 2. 显…

工程大小优化之图片资源
工程大小优化之图片资源 摘要:点点iOS项目本身功能较多,导致应用体积也比较大。一个Xcode工程下图片资源占用了很大的空间,且如果有些App需要一键换肤功能,呵呵,不知道得做多少图片。每套图片还需要设置1x,2x,3x等 简介…

鼠标悬浮变手指
style"cursor:pointer" 转载于:https://www.cnblogs.com/dreamzcy/p/3200897.html

Spring Boot项目快速搭建
实验要求及目的: (1)掌握ApplicationContext容器使用属性setter方法注入的实现; (2)了解Spring的概念和优点; (3)熟悉Spring中的IOC和DI; 实验环境࿱…

wcf入门教程
一、概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分。由 .NET Framework 3.0 开始引入。 WCF的最终目标是通过进程或不同的系统、通过本地网络或是通过Inter…

Swift iOS : 字体图标
厌倦了使用位图在xcode的Assets.xcassets内,因为麻烦,包括如下的麻烦: 找图图需要分尺寸需要操作员类似工作去管理 然后,现在有了字体图标,就方便多了: 比较成熟的几套库,用名字就可以查矢量…

巧用Excel 2010数据透视表制作销售报表
小刘需要根据2010-2011两年间的订单记录创建季度报表,以便分析各类图书的销售情况。面对如此庞大的订单记录,该从何下手呢? 其实最快捷的办法是使用Excel 2010创建数据透视表,以快速合并和比较这些数据。在数据透视表中,可以很清…

Spring的基础应用
实验目的及要求 掌握ApplicationContext容器使用属性setter方法注入的实现;了解Spring的概念和优点; 熟悉Spring中的IOC和DI 实验环境 Java jdk 1.8;apache-maven-3.6.0;Myeclipse C10; 实验内容: 任务一…