图片,视频上传&视频内容旋转

简介: 图片,视频上传&视频内容旋转

前言

我最近在接手一个智能盒子的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*)inputURL
                      outputURL:(NSURL*)outputURL
                   blockHandler:(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){
            // Portrait
            degress = 90;
        }else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){
            // PortraitUpsideDown
            degress = 270;
        }else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){
            // LandscapeRight
            degress = 0;
        }else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){
            // LandscapeLeft
            degress = 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 tracks
    if ([[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 asset
    if (!mutableComposition) {
        // Check whether a composition has already been created, i.e, some other tool has already been applied
        // Create a new composition
        mutableComposition = [AVMutableComposition composition];
        // Insert the video and audio tracks from AVAsset
        if (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 transforms
    if (!mutableVideoComposition) {
        // Create a new video composition
        mutableVideoComposition = [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 instruction
        instruction = [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 mutableVideoComposition
        instruction = (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 edits
        CGAffineTransform 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 origin
            CGAffineTransform 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 composition
    instruction.layerInstructions = @[layerInstruction];
    mutableVideoComposition.instructions = @[instruction];

到这个时候呢视频的旋转已经完成了。
上面我们不是写了一个视频压缩的方法吗?把这个时候生成的mutableVideoComposition赋值给session.videoComposition = mutableVideoComposition;就好了。这样就是先旋转视频然后直接压缩完成我们的需求。

相关文章
|
数据采集 分布式计算 搜索推荐
使用Python实现网页中图片的批量下载和水印添加保存
使用Python实现网页中图片的批量下载和水印添加保存
|
5月前
|
存储 Python
python实现图片与视频转换:将视频保存为图片,将批量图片保存为视频
python实现图片与视频转换:将视频保存为图片,将批量图片保存为视频
|
Web App开发 移动开发 前端开发
移动端图片操作(二)——预览、旋转、合成
在上一节中已经提到了预览,预览可以通过data: URL格式或URL对象。
移动端图片操作(二)——预览、旋转、合成
|
JavaScript 前端开发
图片转base64、判断图片大小、图片压缩、图片上传
文章主要介绍 `js` 实现压缩上传图片转base64,其他的框架(如React、Vue、Angular)也可借此参考。**这个方法真实可用,已在实际项目中运行**。
322 0
【图片操作】给图片添加滤镜
现在我们都喜欢给图片添加滤镜,现在很多相机也自带了许多滤镜。我们可以在拍照的时候选择需要的滤镜。但是有时候我们需要给大量图片添加同样的滤镜,这个时候手动添加就非常麻烦了。为了方便,我们可以使用程序来帮我们完成添加滤镜的操作。
263 0
|
文件存储 Android开发 数据安全/隐私保护
Android图片添加水印图片并把图片保存到文件存储
Android图片添加水印图片并把图片保存到文件存储 package zhangphil.test; import android.
1495 0
|
计算机视觉
【图片操作】生成动态图片
动态图片我们使用的还是比较频繁的,平时的表情包有很多动图。今天我们要做的就是自己制作动态图片,其实就是将视频转换成动图,操作起来非常简单。下面我们就来看看如何实现吧。
577 0
|
Java API Maven
一行代码搞定图片缩略图处理
不知道大家现在工作中还有没有使用过Java处理图片的。强哥在大学毕业后,从事服务端WEB开发,就很少接触图片处理。有接触图片的,大多也就是图片的上传下载。所以,对Java处理图片相关的技术也都没怎么接触。
一行代码搞定图片缩略图处理
|
缓存 Java 数据安全/隐私保护
给图片加水印?这是我见过最简单的实现方式
大家好,我是指北君。 在项目中经常有需要在图片上添加水印的需求以及在某些场合下需要身份证图片,这时就可以对身份证上加水印防止被用于其他用途,java 在处理图片水印时不需要额外的第三方包,使用 BufferedImage 和 Graphics2D 就可以搞定
给图片加水印?这是我见过最简单的实现方式
Halcon打开图片:单个图片以及遍历读取文件夹里的所有图片
Halcon打开图片:单个图片以及遍历读取文件夹里的所有图片
983 0