ios4 – 从UIImage阵列创建视频并将视频保存到iPhone库. AVAssetLibrary AVFoundation

将视频保存到iPhone库中的问题.
我有一个UI Images的阵列,和两个按钮,“convertToVideo”&“savetoiPhoneLib”

-(IBAction) convertToVideo
{
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);

 Nsstring *documentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

Nsstring *savedVideoPath = [documentsDirectory stringByAppendingPathComponent:@"videoOutput"];

printf(" \n\n\n-Video file == %s--\n\n\n",[savedVideoPath UTF8String]);

[self writeImageAsMovie:imageArray toPath:savedVideoPath size:self.view.frame.size duration:3];
}


here i'm passing the imageArray and savedVideoPath to the function below


-(void)writeImageAsMovie:(NSArray *)array toPath:(Nsstring*)path size:(CGSize)size duration:(int)duration 
{

 NSError *error = nil;

 AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
          [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie
                 error:&error];


 NSParameterassert(videoWriter);

 NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
           AVVideoCodecH264,AVVideoCodecKey,[NSNumber numberWithInt:size.width],AVVideoWidthKey,[NSNumber numberWithInt:size.height],AVVideoHeightKey,nil];
 AVAssetWriterInput* writerInput = [[AVAssetWriterInput
          assetWriterInputWithMediaType:AVMediaTypeVideo
          outputSettings:videoSettings] retain];


// NSDictionary *bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32ARGB],kCVPixelBufferPixelFormatTypeKey,nil];

 AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
              assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
              sourcePixelBufferAttributes:nil];


 NSParameterassert(writerInput);
 NSParameterassert([videoWriter canAddInput:writerInput]);
 [videoWriter addInput:writerInput];


 //Start a session:
 [videoWriter startWriting];
 [videoWriter startSessionAtSourceTime:kCMTimeZero];

 CVPixelBufferRef buffer = NULL;

 //convert uiimage to CGImage.

 buffer = [self pixelBufferFromCGImage:[[array objectAtIndex:0] CGImage]];
 [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];

 //Write samples:
......


 //Finish the session:
 [writerInput markAsFinished];
 [videoWriter finishWriting];
}


generate a CVPixelBufferRef here


- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image
{
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
        [NSNumber numberWithBool:YES],kCVPixelBufferCGImageCompatibilityKey,[NSNumber numberWithBool:YES],kCVPixelBufferCGBitmapContextCompatibilityKey,nil];
    CVPixelBufferRef pxbuffer = NULL;

    CVReturn status = CVPixelBufferCreate(kcfAllocatorDefault,self.view.frame.size.width,self.view.frame.size.height,kCVPixelFormatType_32ARGB,(CFDictionaryRef) options,&pxbuffer);
    NSParameterassert(status == kCVReturnSuccess && pxbuffer != NULL);

    CVPixelBufferLockBaseAddress(pxbuffer,0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
    NSParameterassert(pxdata != NULL);

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pxdata,8,4*self.view.frame.size.width,rgbColorSpace,kCGImageAlphaNoneskipFirst);
    NSParameterassert(context);
    CGContextConcatCTM(context,CGAffineTransformMakeRotation(0));
    CGContextDrawImage(context,CGRectMake(0,CGImageGetWidth(image),CGImageGetHeight(image)),image);
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);

    CVPixelBufferUnlockBaseAddress(pxbuffer,0);

    return pxbuffer;
}

保存到iPhone库


-(IBAction) savetoiPhoneLib
{

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,YES);

 Nsstring *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

 Nsstring *getimagePath = [basePath stringByAppendingPathComponent:@"videoOutput"];

 printf(" \n\n\n-Video file == %s--\n\n\n",[getimagePath UTF8String]);

 UISaveVideoAtPathToSavedPhotosAlbum ( getimagePath,self,@selector(video:didFinishSavingWithError: contextInfo:),nil);
}


- (void) video: (Nsstring *) videoPath didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo {
 NSLog(@"Finished saving video with error: %@",error);
}

但是当我保存我收到错误信息时:

完成保存视频,错误错误域= ALAssetsLibraryErrorDomain代码= -3302“无效数据”UserInfo = 0x1d59f0 {NSLocalizedFailureReason =由于数据无效,无法查看或播放,因此写入此资产时出现问题,NSLocalizedRecoverySuggestion =尝试使用不同的数据,NSLocalizedDescription =无效数据}

请让我知道我的错误.提前致谢

解决方法

-(void)convertimagetoVideo
{
    ///////////// setup OR function def if we move this to a separate function ////////////
    // this should be moved to its own function,that can take an imageArray,videoOutputPath,etc...


NSError *error = nil;


// set up file manager,and file videoOutputPath,remove "test_output.mp4" if it exists...
//Nsstring *videoOutputPath = @"/Users/someuser/Desktop/test_output.mp4";
NSFileManager *fileMgr = [NSFileManager defaultManager];
Nsstring *documentsDirectory = [NSHomeDirectory()
                                stringByAppendingPathComponent:@"Documents"];
Nsstring *videoOutputPath = [documentsDirectory stringByAppendingPathComponent:@"test_output.mp4"];
//NSLog(@"-->videoOutputPath= %@",videoOutputPath);
// get rid of existing mp4 if exists...
if ([fileMgr removeItemAtPath:videoOutputPath error:&error] != YES)
    NSLog(@"Unable to delete file: %@",[error localizedDescription]);


CGSize imageSize = CGSizeMake(400,200);
//    NSUInteger fps = 30;
    NSUInteger fps = 30;

//NSMutableArray *imageArray;
//imageArray = [[NSMutableArray alloc] initWithObjects:@"download.jpeg",@"download2.jpeg",nil];
NSMutableArray *imageArray;
NSArray* imagePaths = [[NSBundle mainBundle] pathsForResourcesOfType:@"png" inDirectory:nil];
imageArray = [[NSMutableArray alloc] initWithCapacity:imagePaths.count];
NSLog(@"-->imageArray.count= %i",imageArray.count);
for (Nsstring* path in imagePaths)
{
    [imageArray addobject:[UIImage imageWithContentsOfFile:path]];
    //NSLog(@"-->image path= %@",path);
}

//////////////     end setup    ///////////////////////////////////

NSLog(@"Start building video from defined frames.");

AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
                              [NSURL fileURLWithPath:videoOutputPath] fileType:AVFileTypeQuickTimeMovie
                                                          error:&error];
NSParameterassert(videoWriter);

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                               AVVideoCodecH264,[NSNumber numberWithInt:imageSize.width],[NSNumber numberWithInt:imageSize.height],nil];

AVAssetWriterInput* videoWriterInput = [AVAssetWriterInput
                                        assetWriterInputWithMediaType:AVMediaTypeVideo
                                        outputSettings:videoSettings];


AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
                                                 assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput
                                                 sourcePixelBufferAttributes:nil];

NSParameterassert(videoWriterInput);
NSParameterassert([videoWriter canAddInput:videoWriterInput]);
videoWriterInput.expectsMediaDataInRealTime = YES;
[videoWriter addInput:videoWriterInput];

//Start a session:
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:kCMTimeZero];

CVPixelBufferRef buffer = NULL;

//convert uiimage to CGImage.
int frameCount = 0;
double numberOfSecondsPerFrame = 6;
double frameDuration = fps * numberOfSecondsPerFrame;

//for(VideoFrame * frm in imageArray)
NSLog(@"**************************************************");
for(UIImage * img in imageArray)
{
    //UIImage * img = frm._imageFrame;
    buffer = [self pixelBufferFromCGImage:[img CGImage]];

    BOOL append_ok = NO;
    int j = 0;
    while (!append_ok && j < 30) {
        if (adaptor.assetWriterInput.readyForMoreMediaData)  {
            //print out status:
            NSLog(@"Processing video frame (%d,%d)",frameCount,[imageArray count]);

            //CMTime frameTime = CMTimeMake((int64_t),(int32_t)2);

            CMTime frameTime = CMTimeMake(frameCount*frameDuration,(int32_t) fps);
            NSLog(@"seconds = %f,%u,%d",CMTimeGetSeconds(frameTime),fps,j);
            append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
            if(!append_ok){
                NSError *error = videoWriter.error;
                if(error!=nil) {
                    NSLog(@"Unresolved error %@,%@.",error,[error userInfo]);
                }
            }
        }
        else {
            printf("adaptor not ready %d,%d\n",j);
            [NSThread sleepForTimeInterval:0.1];
        }
        j++;
    }
    if (!append_ok) {
        printf("error appending image %d times %d\n,with error.",j);
    }
    frameCount++;
}
NSLog(@"**************************************************");

//Finish the session:
[videoWriterInput markAsFinished];
[videoWriter finishWriting];
NSLog(@"Write Ended");

}


-(void)CompileFilestomakeVideo
{

    // set up file manager,remove "test_output.mp4" if it exists...
    //Nsstring *videoOutputPath = @"/Users/someuser/Desktop/test_output.mp4";
    Nsstring *documentsDirectory = [NSHomeDirectory()
                                    stringByAppendingPathComponent:@"Documents"];
    Nsstring *videoOutputPath = [documentsDirectory stringByAppendingPathComponent:@"test_output.mp4"];
    //NSLog(@"-->videoOutputPath= %@",videoOutputPath);
    // get rid of existing mp4 if exists...

    AVMutableComposition* mixComposition = [AVMutableComposition composition];

    Nsstring *bundleDirectory = [[NSBundle mainBundle] bundlePath];
    // audio input file...
    Nsstring *audio_inputFilePath = [bundleDirectory stringByAppendingPathComponent:@"30secs.mp3"];
    NSURL    *audio_inputFileUrl = [NSURL fileURLWithPath:audio_inputFilePath];

    // this is the video file that was just written above,full path to file is in --> videoOutputPath
    NSURL    *video_inputFileUrl = [NSURL fileURLWithPath:videoOutputPath];

    // create the final video output file as MOV file - may need to be MP4,but this works so far...
    Nsstring *outputFilePath = [documentsDirectory stringByAppendingPathComponent:@"final_video.mp4"];
    NSURL    *outputFileUrl = [NSURL fileURLWithPath:outputFilePath];

    if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
        [[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];

    CMTime nextClipStartTime = kCMTimeZero;

    AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:video_inputFileUrl options:nil];
    CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
    AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    [a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:nextClipStartTime error:nil];

    //nextClipStartTime = CMTimeAdd(nextClipStartTime,a_timeRange.duration);

    AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:audio_inputFileUrl options:nil];
    CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero,audioAsset.duration);
    AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    [b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:nextClipStartTime error:nil];



    AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
    _assetExport.outputFileType = @"com.apple.quicktime-movie";
    //_assetExport.outputFileType = @"public.mpeg-4";
    //NSLog(@"support file types= %@",[_assetExport supportedFileTypes]);
    _assetExport.outputURL = outputFileUrl;

    [_assetExport exportAsynchronouslyWithCompletionHandler:
     ^(void ) {
         [self saveVideoToAlbum:outputFilePath];
     }
     ];

    ///// THAT IS IT DONE... the final video file will be written here...
    NSLog(@"DONE.....outputFilePath--->%@",outputFilePath);

    // the final video file will be located somewhere like here:
    // /Users/caferrara/Library/Application Support/iPhone Simulator/6.0/Applications/D4B12FEE-E09C-4B12-B772-7F1BD6011BE1/Documents/outputFile.mov


    ////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
}
- (void) saveVideoToAlbum:(Nsstring*)path {

    NSLog(@"saveVideoToAlbum");

    if(UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path)){
        UISaveVideoAtPathToSavedPhotosAlbum (path,nil);
    }
}

-(void) video:(Nsstring *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    if(error)
        NSLog(@"error: %@",error);
    else
        NSLog(@" OK");
}



////////////////////////
- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image {

    CGSize size = CGSizeMake(400,200);

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES],size.width,size.height,(__bridge CFDictionaryRef) options,&pxbuffer);
    if (status != kCVReturnSuccess){
        NSLog(@"Failed to create pixel buffer");
    }

    CVPixelBufferLockBaseAddress(pxbuffer,0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pxdata,4*size.width,kCGImageAlphaPremultipliedFirst);
    //kCGImageAlphaNoneskipFirst);
    CGContextConcatCTM(context,0);

    return pxbuffer;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple 最新软件的错误和性能问题。
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只有5%的概率会遇到选择运营商界面且部分必须连接到iTunes才可以激活
一般在接外包的时候, 通常第三方需要安装你的app进行测试(这时候你的app肯定是还没传到app store之前)。
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应用变灰了。那么接下来我们看一下Flutter是如何实现的。Flutter中实现整个App变为灰色在Flutter中实现整个App变为灰色是非常简单的,只需要在最外层的控件上包裹ColorFiltered,用法如下:ColorFiltered(颜色过滤器)看名字就知道是增加颜色滤镜效果的,ColorFiltered( colorFilter:ColorFilter.mode(Colors.grey, BlendMode.
flutter升级/版本切换
(1)在C++11标准时,open函数的文件路径可以传char指针也可以传string指针,而在C++98标准,open函数的文件路径只能传char指针;(2)open函数的第二个参数是打开文件的模式,从函数定义可以看出,如果调用open函数时省略mode模式参数,则默认按照可读可写(ios_base:in | ios_base::out)的方式打开;(3)打开文件时的mode的模式是从内存的角度来定义的,比如:in表示可读,就是从文件读数据往内存读写;out表示可写,就是把内存数据写到文件中;
文章目录方法一:分别将图片和文字置灰UIImage转成灰度图UIColor转成灰度颜色方法二:给App整体添加灰色滤镜参考App页面置灰,本质是将彩色图像转换为灰度图像,本文提供两种方法实现,一种是App整体置灰,一种是单个页面置灰,可结合具体的业务场景使用。方法一:分别将图片和文字置灰一般情况下,App页面的颜色深度是24bit,也就是RGB各8bit;如果算上Alpha通道的话就是32bit,RGBA(或者ARGB)各8bit。灰度图像的颜色深度是8bit,这8bit表示的颜色不是彩色,而是256
领导让调研下黑(灰)白化实现方案,自己调研了两天,根据网上资料,做下记录只是学习过程中的记录,还是写作者牛逼
让学前端不再害怕英语单词(二),通过本文,可以对css,js和es6的单词进行了在逻辑上和联想上的记忆,让初学者更快的上手前端代码
用Python送你一颗跳动的爱心
在uni-app项目中实现人脸识别,既使用uni-app中的live-pusher开启摄像头,创建直播推流。通过快照截取和压缩图片,以base64格式发往后端。
商户APP调用微信提供的SDK调用微信支付模块,商户APP会跳转到微信中完成支付,支付完后跳回到商户APP内,最后展示支付结果。CSDN前端领域优质创作者,资深前端开发工程师,专注前端开发,在CSDN总结工作中遇到的问题或者问题解决方法以及对新技术的分享,欢迎咨询交流,共同学习。),验证通过打开选择支付方式弹窗页面,选择微信支付或者支付宝支付;4.可取消支付,放弃支付会返回会员页面,页面提示支付取消;2.判断支付方式,如果是1,则是微信支付方式。1.判断是否在微信内支付,需要在微信外支付。
Mac命令行修改ipa并重新签名打包
首先在 iOS 设备中打开开发者模式。位于:设置 - 隐私&安全 - 开发者模式(需重启)
一 现象导入MBProgressHUD显示信息时,出现如下异常现象Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_MBProgressHUD", referenced from: objc-class-ref in ViewController.old: symbol(s) not found for architecture x86_64clang: error: linker command failed wit
Profiles >> 加号添加 >> Distribution >> "App Store" >> 选择 2.1 创建的App ID >> 选择绑定 2.3 的发布证书(.cer)>> 输入描述文件名称 >> Generate 生成描述文件 >> Download。Certificates >> 加号添加 >> "App Store and Ad Hoc" >> “Choose File...” >> 选择上一步生成的证书请求文件 >> Continue >> Download。
今天有需求,要实现的功能大致如下:在安卓和ios端实现分享功能可以分享链接,图片,文字,视频,文件,等欢迎大佬多多来给萌新指正,欢迎大家来共同探讨。如果各位看官觉得文章有点点帮助,跪求各位给点个“一键三连”,谢啦~声明:本博文章若非特殊注明皆为原创原文链接。