美文网首页iOS图形处理相关iOS基础控件iOS开发技术
iOS视频压缩存储至本地并上传至服务器

iOS视频压缩存储至本地并上传至服务器

作者: Snoopy008 | 来源:发表于2016-06-07 10:44 被阅读24444次

    端午节快到了,提前祝大家节日快乐。担心端午没时间写,今天抽空写一下。

    最近做了一个项目,我把其中的核心功能拿出来和大家分享一下,重点还是自己梳理一下。

    这里关于视频转码存储我整理了两个方法,这两个方法都是针对相册内视频进行处理的。

    1、该方法没有对视频进行压缩,只是将视频原封不动地从相册拿出来放到沙盒路径下,目的是拿到视频的NSData以便上传####

    这里我传了一个URL,这个URL有点特别,是相册文件URL,所以我说过只针对相册视频进行处理

        //将原始视频的URL转化为NSData数据,写入沙盒
        + (void)videoWithUrl:(NSString *)url withFileName:(NSString *)fileName
        {
              ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
              dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
                if (url) {
                 [assetLibrary assetForURL:[NSURL URLWithString:url] resultBlock:^(ALAsset *asset) {
                ALAssetRepresentation *rep = [asset defaultRepresentation];
                NSString *pathDocuments = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
                NSString *imagePath = [NSString stringWithFormat:@"%@/Image", pathDocuments];
                NSString *dbFilePath = [imagePath stringByAppendingPathComponent:fileName];
                char const *cvideoPath = [dbFilePath UTF8String];
                FILE *file = fopen(cvideoPath, "a+");
                if (file) {
                    const int bufferSize = 11024 * 1024;
                    // 初始化一个1M的buffer
                    Byte *buffer = (Byte*)malloc(bufferSize);
                    NSUInteger read = 0, offset = 0, written = 0;
                    NSError* err = nil;
                    if (rep.size != 0)
                    {
                        do {
                            read = [rep getBytes:buffer fromOffset:offset length:bufferSize error:&err];
                            written = fwrite(buffer, sizeof(char), read, file);
                            offset += read;
                        } while (read != 0 && !err);//没到结尾,没出错,ok继续
                    }
                    // 释放缓冲区,关闭文件
                    free(buffer);
                    buffer = NULL;
                    fclose(file);
                    file = NULL;
                }
            } failureBlock:nil];
        }
    });
    

    }

    2、推荐使用该方法,该方法对视频进行压缩处理,压缩的程度可调####

    这里我传的是模型过去,将我的URL带过去的,然后压缩完毕用模型把NSData带出来,数据大家根据自己需求自由发挥

    + (void) convertVideoWithModel:(RZProjectFileModel *) model
    {
        model.filename = [NSString stringWithFormat:@"%ld.mp4",RandomNum];
        //保存至沙盒路径
        NSString *pathDocuments = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        NSString *videoPath = [NSString stringWithFormat:@"%@/Image", pathDocuments];
        model.sandBoxFilePath = [videoPath stringByAppendingPathComponent:model.filename];
        
        //转码配置
        AVURLAsset *asset = [AVURLAsset URLAssetWithURL:model.assetFilePath options:nil];
        AVAssetExportSession *exportSession= [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];
        exportSession.shouldOptimizeForNetworkUse = YES;
        exportSession.outputURL = [NSURL fileURLWithPath:model.sandBoxFilePath];
        exportSession.outputFileType = AVFileTypeMPEG4;
        [exportSession exportAsynchronouslyWithCompletionHandler:^{
             int exportStatus = exportSession.status;
            RZLog(@"%d",exportStatus);
            switch (exportStatus)
            {
                case AVAssetExportSessionStatusFailed:
                {
                    // log error to text view
                    NSError *exportError = exportSession.error;
                    NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
                    break;
                }
                case AVAssetExportSessionStatusCompleted:
                {
                    RZLog(@"视频转码成功");
                    NSData *data = [NSData dataWithContentsOfFile:model.sandBoxFilePath];
                    model.fileData = data;
                }
            }
            }];
    
    }
    

    在这里你可以修改压缩比例,苹果官方都封装好了,根据需求调整

    AVAssetExportSession *exportSession= [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];
    

    在这里修改输出类型,正常情况下选MP4不会有什么问题的

    exportSession.outputFileType = AVFileTypeMPEG4;
    

    Mark一下图片压缩用这个,image是图片,0.4是比例,大小可调

    model.fileData = UIImageJPEGRepresentation(image, 0.4);
    

    这样你就很愉快地拿到转码过后的NSData了,然后播放一下试试

     MPMoviePlayerViewController* playerView = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL fileURLWithPath:sandBoxFilePath]];
    [superVC presentViewController:playerView animated:YES completion:nil];
    

    备注一下###

    可以发现我这里使用了沙盒存储,在下一节我整理一下用代码管理应用沙盒。

    更新#

    最近发现好多人联系我,问我要Demo,最近我也整理了一下,目前挂在github上,望大神们指正。https://github.com/Snoopy008/SelectVideoAndConvert
    (如果我的代码对你有帮助,请你不忘在github上给我个Star,谢谢)。

    2017-3-23#

    偶然间帮一位好友看代码,发现了一个更简单的获取本地视频的NSData的方法,大家自己看,我就不解释了。代码放在github上https://github.com/Snoopy008/videoData

    相关文章

      网友评论

      • 何康老鬼:你好,我想问下压缩了之后,视频的清晰度如何保持,我压缩后上传到服务器,很模糊,选了那个AVAssetExportPresetMediumQuality,还是会变模糊,请问下抖音或者微信的那种小视频压缩为啥还是那么清?
        ddffsg:@何康老鬼 好的谢谢
        何康老鬼:@ddffsg 我就没压缩 上传的高质量的视频,只不过服务器用的服务器换的腾讯的,还有就是限制了视频大小 和时间
        ddffsg:同问,兄弟你是怎么解决的啊
      • 崔又淇:太优秀了,为你打call,最近一直再为视频保存犯愁,帮了我大忙了!!!
      • ios肖:exportAsynchronouslyWithCompletionHandler 这个方法,压缩5分钟的视频都需要很久啊。我想上传1-2小时的视频那得压缩多久啊
        Snoopy008:@ios肖 这个你可以测一下,我没测过
      • 落葉封塵:哈喽。如果app从硬件设备中获取到的视频为NSData类型,请问如何压缩呢?
      • 大大大_大哥哥:你好。我对比微信的视频压缩。微信把视频压缩之后后清晰度没有发生什么变化。但是文件大小会压的很低。而且微信压出来的视频分辨率也很奇怪。并不是标准的960*540。 它会在偏小的一方多4个像素。目前在找这方面的资料。请问有什么建议么。
        路有点颠簸:你好,你压缩这块处理好了吗,用系统这个压缩一是时间久,二是有可能几兆的视频压缩完了成十多兆,我也没找到更好的办法
        Snoopy008:@大大大_大哥哥 这个要后台处理吧
      • 午马丶:你好,如果不保存到本地直接从相册中取出的视频的URL可以用来上传吗? 谢谢!
        Snoopy008:@A丶 一样的,都是要转成data,主要还是拿到data。
        午马丶: @Snoopy008 但是你最后给的那中方式就是我我说的那种啊……
        Snoopy008:@A丶 不行,路径只是一个指向,不代表数据,你要上传的是数据。
      • 捏捏你的脸:很好 准备要用, 先存储点知识。
      • angBiu:嗨 请问加入这个 exporturl 是用 沙盒路径 视频导出后 没有调用 [NSFileManager defaultManager] removeItemAtURL: 这个方法 是可以一直调用这个 沙盒路径的视频,但是我把路径保存起来,APP关掉后,调用了这个路径的视频就报error
        Error Domain=NSURLErrorDomain Code=-1100 "在此服务器上找不到所请求的 URL 。" UserInfo={NSLocalizedDescription=在此服务器上找不到所请求的 URL 。, NSUnderlyingError=0x13f606e20 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

        请问会是什么情况呢
        Snoopy008:@angBiu 确定路径是否存在,如果对沙盒路径不清楚可以看我的这篇文章http://www.jianshu.com/p/a421e36cc298
      • f18a4509ea90:你好,有个疑问:将原始视频的URL转化为NSData数据,写入沙盒。这个处理方法有其他解决方法没?

        原因是这样子的,如果我的手机磁盘空间不足了,而视频的大小比如超过1个G,此时要怎么处理?有没有办法直接读取相册视频URL然后上传到服务器,而不经过写沙盒的步骤?
        Snoopy008:@路有点颠簸 没有后来了,找找有没有第三方库可以实现的
        路有点颠簸:大兄弟,你这个后来怎么处理的
        Pusswzy:同问.
      • 庄稼汉还能写代码:你好,如果在上传列表中加入多个较大的视频文件,每个视频文件都需要在沙盒中备份的话,占用大量手机的磁盘空间,怎么办
        Snoopy008:@Cavs_King 这个目前还没遇到过……
        f18a4509ea90:@Snoopy008 上传完毕删除掉是可以,但是如果视频文件太大的话,写入沙盒后依然占据大量的磁盘空间,这种有什么解决方法?
        Snoopy008:@庄稼汉还能写代码 可以上传完毕给它清除掉。生成两个沙盒路径,一个给正常缓存,另一个给上传缓存,上传完毕就把上传缓存路径下的文件删掉
      • b2f70a645712:大牛 我用HSDownloadManager下载的视频 没有扩展名 自己添加扩展名mp4 还是没办法保存到本地 你知道该咋办么
        b2f70a645712:@默认不存在 问题我是这么处理的 下载的东西我自己追加扩展名 另存一份 用完删掉
        Snoopy008:@默认不存在 先检查你的本地存储路径对不对
        Snoopy008:@默认不存在 下载的文件貌似不需要给任何文件名
      • 滚来滚去的桔子:你好,知道怎么从资源库里把音乐取出来吗?URL 拿到了,但是是长 ```ipod-library://item/item.mp3?id=12345``` 这样的,要怎么才能拿到真正的音乐文件数据呢?
        Snoopy008:@滚来滚去的桔子 一样的,都是先要存一份,才能读出来
        滚来滚去的桔子:@Snoopy008 我拿到了,官方文档里有代码,但是用示例代码的重写到其他文件夹一直不成功。可以把读取的byte转data,然后writeToFile写到文件里:joy:
        Snoopy008:@滚来滚去的桔子 额。。回的有点慢,音乐目前没有整理。
      • c67407a96ed0:我把视频文件转成二进制的形式成功上传服务器,但是却播放不了,点开视频窗口一片黑..怎么回事?可以帮帮忙吗??
        Snoopy008:@c67407a96ed0 不知道你用那种方式播放的?
      • c62892561d2f:我上传时,并不是上传到服务器,而是上传到七牛,这样减少服务器压力,这样的话上传时还需要压缩吗?
        Snoopy008:@aven_kang 谢谢您的建议
        aven_kang:上传到7牛后会自动转码压缩的,比起自己服务器转码压缩快捷舒服,前端做压缩,比较影响体验,如果文件还比较大的话。
        Snoopy008:@狂龙乱舞 这个没试过
      • 路在脚下了:您好,我在相册,选择完视频,获取到的是一个,PHAsset,请问我怎么获取视频的URL?这两天一直被这个困扰着
        Snoopy008:@码海求知 你用的是PhotoKit,你可以看我简书里写的关于PhotoKit的内容。
      • 卟师:挺好,我能转载分享吗?我会标注上出处和作者的
        Snoopy008:@卟师 可以的,我写出来就是给大家分享的。
      • 让代码飞:大神,我这会做的刚好和你说的一样,有没有demo让参考一下。试了很多方法效果不好
        Snoopy008:@Amor洋 文中有demo地址
        Amor洋:大神 我也要做视频压缩,求demo啊
        Snoopy008:@让代码飞 加我qq私聊,984603904
      • 吾往千万里:对于iOS系统转码和效果渲染只能在前端处理么?感觉进度好慢,很影响用户体验。能放在本地后台或者服务端去做么?
        7a2b85bf361a:@Snoopy008 怎么理解 ??比如我有个视频要发送 逻辑不就是 点击发送的时候 先转吗 然后发送
        Amor洋:mark
        Snoopy008:@陆庄羽 大型数据不建议,因为流量问题。可以提前你转码的步骤,不要在发送请求时才开始压缩,可以在选取结束后就转码,这样等你要发请求时差不多已经转码完毕。
      • 下弦月丿:mark 一下 :smiley:
      • 文兴:视频压缩是一个非常耗时的工作,移动端通常不推荐这么做,用户体验会很差。
        文兴:还有一个原因就是安卓端原生不支持视频压缩。
        文兴:@Snoopy008 上传之前还是得等待压缩结束吧?我之前也试过压缩5分钟的视频三四百M,要十多秒,所以最后放弃了压缩直接传,在服务器端做压缩
        Snoopy008:@文兴 的确是这样,可以用异步加上提前压缩的方式。在本项目中我是视频选取结束我就开始压缩,这样上传时就不用等着压缩了。
      • 林易析:看来有必要加强学习一下,现在我也在搞这方面,以后多多相互沟通交流
        林易析: @Snoopy008 哈哈😄👊
        Snoopy008:@芳铭几何 嗯嗯

      本文标题:iOS视频压缩存储至本地并上传至服务器

      本文链接:https://www.haomeiwen.com/subject/xgyddttx.html