0

我正在用一组图像和一个音频文件制作视频

但我似乎无法将其保存到相机胶卷

有时它会保存,但有时它不会并给我一个奇怪的错误

outputFile.mp4 无法保存到已保存的相册中:Error Domain=NSOSStatusErrorDomain Code=-12848 "电影无法播放。" UserInfo=0x7bd7370 {NSLocalizedDescription=电影无法播放。}

此函数从图像数组创建视频:

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

    NSError *error = nil;

    AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
                                  [NSURL fileURLWithPath:path] fileType:AVFileTypeMPEG4
                                                              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 = 16;
    int kRecordingFPS = 30;
    UIImage * im = [UIImage imageNamed:@"IMG_0103.JPG"];

    NSArray * imageArray = [[NSArray alloc]initWithObjects:im,im,im,im,im,im,im,im,im,im,im,im,im,im,im,im, 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");
    [videoWriterInput release];
    [videoWriter release];
    [imageArray release];
}

此函数添加音频:

    -(void)CompileFilesToMakeMovie{
        AVMutableComposition* mixComposition = [AVMutableComposition composition];

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

        NSString* audio_inputFileName = @"Rihanna-Take a Bow.mp3";

        NSString* audio_inputFilePath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,audio_inputFileName];

        NSURL*    audio_inputFileUrl = [NSURL fileURLWithPath:audio_inputFilePath];

        NSString* video_inputFileName = @"a.mp4";
        NSString* video_inputFilePath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,video_inputFileName];
        NSURL*    video_inputFileUrl = [NSURL fileURLWithPath:video_inputFilePath];

        NSString* outputFileName = @"outputFile.mp4";
        NSString* outputFilePath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,outputFileName];

        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, videoAsset.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:AVAssetExportPresetMediumQuality];
        _assetExport.outputFileType = AVFileTypeMPEG4;
        _assetExport.outputURL = outputFileUrl;
        [_assetExport setTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)];
        [_assetExport exportAsynchronouslyWithCompletionHandler:nil];

        [audioAsset release];
        [videoAsset release];


        [_assetExport release];
    }

该函数调用:

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    UIImage * i = [UIImage imageNamed:@"IMG_0103.JPG"];

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

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


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

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

}
4

1 回答 1

0

就我而言,原因是 AVAssetWriter 还没有写完。使用以下代码解决了它:

__block BOOL _finished = NO;

[assetWriter finishWritingWithCompletionHandler:^{
    _finished = YES;
}];

while (!_finished) {
    [NSThread sleepForTimeInterval:0.1];
}
于 2013-06-06T03:45:25.383 回答