【问题标题】:Creating Video from array of images and saving it to camera roll从图像数组创建视频并将其保存到相机胶卷
【发布时间】:2012-10-22 21:16:08
【问题描述】:

我试图从一组图像中制作视频,但我找到了一些代码并让它工作

但视频不会保存到照片库中,它给了我这个错误:

Documentsa.mov 无法保存到已保存的相册中:Error Domain=NSOSStatusErrorDomain Code=2“无法播放此电影。” UserInfo=0x922cf60 {NSLocalizedDescription=这部电影无法播放。}

这是我使用的代码:

 NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    UIImage * i = [UIImage imageNamed:@"IMG_1650.JPG"];
    CGAffineTransform  transform = CGAffineTransformMakeRotation((M_PI/180)*90);
    GPUImageTransformFilter * filter = [[GPUImageTransformFilter alloc]init];
    [filter setAffineTransform:transform];
   UIImage * im = [filter imageByFilteringImage:i];
    im = [filter imageByFilteringImage:im];

    [self writeImagesToMovieAtPath:[NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,@"a.mov"] withSize:CGSizeMake(i.size.width, i.size.height)];

    NSString* exportVideoPath = [NSString stringWithFormat:@"%@%@",documentsDirectoryPath,@"a.mov"];

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

这是我用来创建视频的代码:

-(void) writeImagesToMovieAtPath:(NSString *) path withSize:(CGSize) size
{
    NSLog(@"Write Started");

    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* videoWriterInput = [[AVAssetWriterInput
                                             assetWriterInputWithMediaType:AVMediaTypeVideo
                                             outputSettings:videoSettings] retain];


    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 = 1;
    int kRecordingFPS = 30;
    UIImage * im = [UIImage imageNamed:@"IMG_1650.JPG"];

    CGAffineTransform  transform = CGAffineTransformMakeRotation((M_PI/180)*90);
    GPUImageTransformFilter * filter = [[GPUImageTransformFilter alloc]init];
    [filter setAffineTransform:transform];
    UIImage * i = [filter imageByFilteringImage:im];
    i = [filter imageByFilteringImage:im];
    NSArray * imageArray = [[NSArray alloc]initWithObjects:i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i, nil];

    for(UIImage * img in imageArray)
    {
        buffer = [self pixelBufferFromCGImage:[img CGImage] andSize:size];

        BOOL append_ok = NO;
        int j = 0;
        while (!append_ok && j < 30)
        {
            if (adaptor.assetWriterInput.readyForMoreMediaData)
            {
                printf("appending %d attemp %d\n", frameCount, j);

                CMTime frameTime = CMTimeMake(frameCount,(int32_t) kRecordingFPS);
                append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];

                if(buffer)
                    CVBufferRelease(buffer);
                [NSThread sleepForTimeInterval:0.05];
            }
            else
            {
                printf("adaptor not ready %d, %d\n", frameCount, j);
                [NSThread sleepForTimeInterval:0.1];
            }
            j++;
        }
        if (!append_ok) {
            printf("error appending image %d times %d\n", frameCount, j);
        }
        frameCount++;
    }


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

我尝试使用

检查视频是否兼容
UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(videoPath)

我发现视频不兼容

但我不知道为什么或如何解决这个问题

【问题讨论】:

  • 哇,这段代码现在有点乱......也许在找到答案后需要在 SE:Code Review 上工作一段时间。
  • 检查图像分辨率,iDevices 对播放格式的支持非常有限。 IMG_1650 看起来像相机照片文件,而 iPad 仅支持 1080p h264。
  • THX @A-Live 我用较小的图像替换了图像并且它有效,没有办法解决这个问题吗?还是我必须调整所有图像的大小?
  • TIL codereview.stackexchange.com 存在。谢谢@CodaFi!

标签: ios video save avassetwriter avasset


【解决方案1】:

视频路径

NSString* exportVideoPath = [NSString stringWithFormat:@"%@%@",documentsDirectoryPath,@"a.mov"]; 

错了。您缺少“/”分隔符。

改成这个

NSString* exportVideoPath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,@"a.mov"]; 

希望这能解决您的问题。

【讨论】:

    【解决方案2】:

    我在之前的评论中尝试过 A-Live 的解决方案

    问题原来是图片太大了

    有没有办法克服这个问题?

    【讨论】:

    • 一个提示 - 随时使用问题下方的Edit 按钮来保持更新。另请注意,该网站在全球范围内均可访问,这意味着时区可能会有很大差异。
    【解决方案3】:

    克服是什么意思?我相信您可以将文件从文档发送到任何后端服务器以存储它,并且具有更好(您知道我的意思)视频支持的其他设备将能够播放它。但是,即使可能通过一些“黑客”,超出操作系统限制也不太可能顺利。

    我的意思是 1080p 是库中最大的视频文件分辨率,因为库中的媒体必须可播放。您仍然可以将文件存储在应用程序文档中并手动解码,这听起来像是一项有趣的任务 :) 确保您不会将其与 iCloud 同步,以避免大量流量泄漏使客户抓狂。

    【讨论】:

      猜你喜欢
      • 2015-09-25
      • 1970-01-01
      • 1970-01-01
      • 2016-05-01
      • 2015-01-06
      • 2015-05-12
      • 2015-11-18
      • 2014-02-02
      • 1970-01-01
      相关资源
      最近更新 更多