iPhone图像到视频的视频速度问题

发布于 2024-12-21 02:21:21 字数 6994 浏览 4 评论 0原文

我已经在iPhone中完成了图像到视频的转换(当然我从堆栈溢出问题中得到了代码)。但问题是录制视频的速度非常快,尽管我有大约2250帧,但它在2秒内就跑掉了。我知道问题出在它的帧速率上。 但我不知道如何使其正确。 我的代码在下面,

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *myFilePath = [documentsDirectoryPath stringByAppendingPathComponent:@"test.mov"];

if ([self openVideoFile:myFilePath withSize:CGSizeMake (480.0, 320.0)]) {
    for (int i=1; i<2226; i++) {
        NSString *imagename=[NSString stringWithFormat:@"1 (%i).jpg",i];
        UIImage *image=[ UIImage imageNamed:imagename];
        [self writeImageToMovie:[image CGImage]];
    }
    [videoWriter finishWriting];
}
else {
    NSLog(@"friled to open video file");
}

此代码位于调用函数和下面给出的函数的定义中,

- (BOOL) openVideoFile: (NSString *) path withSize:(CGSize)imageSize {
    CGSize size = CGSizeMake (480.0, 320.0);//imageSize;

    NSError *error = nil;
    videoWriter = [[AVAssetWriter alloc] initWithURL:
                   [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie
                                               error:&error];
    if (error != nil){
        NSLog(@"error>>>> %@",error);
        return NO;
    }

    NSDictionary *videoCleanApertureSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                                [NSNumber numberWithDouble:size.width], AVVideoCleanApertureWidthKey,
                                                [NSNumber numberWithDouble:size.height], AVVideoCleanApertureHeightKey,
                                                [NSNumber numberWithInt:10], AVVideoCleanApertureHorizontalOffsetKey,
                                                [NSNumber numberWithInt:10], AVVideoCleanApertureVerticalOffsetKey,
                                                nil];


    NSDictionary *videoAspectRatioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                              [NSNumber numberWithInt:1], AVVideoPixelAspectRatioHorizontalSpacingKey,
                                              [NSNumber numberWithInt:1],AVVideoPixelAspectRatioVerticalSpacingKey,
                                              nil];



    NSDictionary *codecSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                   videoCleanApertureSettings, AVVideoCleanApertureKey,
                                   videoAspectRatioSettings, AVVideoPixelAspectRatioKey,
                                  nil];

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                   AVVideoCodecH264, AVVideoCodecKey,
                                   codecSettings,AVVideoCompressionPropertiesKey,
                                   [NSNumber numberWithDouble:size.width], AVVideoWidthKey,
                                   [NSNumber numberWithDouble:size.height], AVVideoHeightKey,
                                   nil];
    writerInput = [[AVAssetWriterInput
                    assetWriterInputWithMediaType:AVMediaTypeVideo
                    outputSettings:videoSettings] retain];
    NSMutableDictionary * bufferAttributes = [[NSMutableDictionary alloc] init];
    [bufferAttributes setObject: [NSNumber numberWithInt: kCVPixelFormatType_32ARGB]
                         forKey: (NSString *) kCVPixelBufferPixelFormatTypeKey];
    [bufferAttributes setObject: [NSNumber numberWithInt: 480]
                         forKey: (NSString *) kCVPixelBufferWidthKey];
    [bufferAttributes setObject: [NSNumber numberWithInt: 320]
                         forKey: (NSString *) kCVPixelBufferHeightKey];


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

    NSMutableDictionary*     attributes;
    attributes = [NSMutableDictionary dictionary];

    int width = 480;
    int height = 320;

    [attributes setObject:[NSNumber numberWithInt:kCVPixelFormatType_32ARGB] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
    [attributes setObject:[NSNumber numberWithInt:width] forKey: (NSString*)kCVPixelBufferWidthKey];
    [attributes setObject:[NSNumber numberWithInt:height] forKey: (NSString*)kCVPixelBufferHeightKey];
    CVReturn theError = CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, (CFDictionaryRef) attributes, &pixelBufferPool);                                           


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

    writerInput.expectsMediaDataInRealTime = YES;
    [videoWriter startWriting];
    [videoWriter startSessionAtSourceTime:kCMTimeZero];

    buffer = NULL;
    lastTime = kCMTimeZero;
    presentTime = kCMTimeZero;

    return YES;
}






   - (void) writeImageToMovie:(CGImageRef)image 
{
    if([writerInput isReadyForMoreMediaData])
    {
        buffer = [self pixelBufferFromCGImage:image];
        BOOL success = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
        if (!success) NSLog(@"Failed to appendPixelBuffer");
        CVPixelBufferRelease(buffer);

        presentTime = CMTimeAdd(lastTime, CMTimeMake(1, 1000));//I think problem is here but what will be given for correct output
        lastTime = presentTime;
    }
    else
    {
        NSLog(@"error - writerInput not ready");
    }
}


    - (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image
{
    CGSize size = CGSizeMake (480.0, 320.0);
    CVPixelBufferRef pxbuffer;
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                             nil];
    if (pixelBufferPool == NULL) NSLog(@"pixelBufferPool is null!");
    CVReturn status = CVPixelBufferPoolCreatePixelBuffer (NULL, pixelBufferPool, &pxbuffer); 
    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pxdata, size.width,
                                                 size.height, 8, 4*size.width, rgbColorSpace, 
                                                 kCGImageAlphaNoneSkipFirst);
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
    CGContextDrawImage(context, CGRectMake(90, 10, CGImageGetWidth(image), 
                                           CGImageGetHeight(image)), image);
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);

    return pxbuffer;
}

如何处理 CMTime 变量以及如何正确地进行它 另一项帮助是如何在此视频中添加音频。

I have done image to video conversion in iphone(of course I got the code from stack overflow questions). But the problem is speed of recorded video is very fast, it ran away within 2 seconds even though I have around 2250 frames. I know the problem is with its frame rate.
But i don't know how to make it correct.
my code is below

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *myFilePath = [documentsDirectoryPath stringByAppendingPathComponent:@"test.mov"];

if ([self openVideoFile:myFilePath withSize:CGSizeMake (480.0, 320.0)]) {
    for (int i=1; i<2226; i++) {
        NSString *imagename=[NSString stringWithFormat:@"1 (%i).jpg",i];
        UIImage *image=[ UIImage imageNamed:imagename];
        [self writeImageToMovie:[image CGImage]];
    }
    [videoWriter finishWriting];
}
else {
    NSLog(@"friled to open video file");
}

this code is in calling function and defenitions of the functions given below

- (BOOL) openVideoFile: (NSString *) path withSize:(CGSize)imageSize {
    CGSize size = CGSizeMake (480.0, 320.0);//imageSize;

    NSError *error = nil;
    videoWriter = [[AVAssetWriter alloc] initWithURL:
                   [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie
                                               error:&error];
    if (error != nil){
        NSLog(@"error>>>> %@",error);
        return NO;
    }

    NSDictionary *videoCleanApertureSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                                [NSNumber numberWithDouble:size.width], AVVideoCleanApertureWidthKey,
                                                [NSNumber numberWithDouble:size.height], AVVideoCleanApertureHeightKey,
                                                [NSNumber numberWithInt:10], AVVideoCleanApertureHorizontalOffsetKey,
                                                [NSNumber numberWithInt:10], AVVideoCleanApertureVerticalOffsetKey,
                                                nil];


    NSDictionary *videoAspectRatioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                              [NSNumber numberWithInt:1], AVVideoPixelAspectRatioHorizontalSpacingKey,
                                              [NSNumber numberWithInt:1],AVVideoPixelAspectRatioVerticalSpacingKey,
                                              nil];



    NSDictionary *codecSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                   videoCleanApertureSettings, AVVideoCleanApertureKey,
                                   videoAspectRatioSettings, AVVideoPixelAspectRatioKey,
                                  nil];

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                   AVVideoCodecH264, AVVideoCodecKey,
                                   codecSettings,AVVideoCompressionPropertiesKey,
                                   [NSNumber numberWithDouble:size.width], AVVideoWidthKey,
                                   [NSNumber numberWithDouble:size.height], AVVideoHeightKey,
                                   nil];
    writerInput = [[AVAssetWriterInput
                    assetWriterInputWithMediaType:AVMediaTypeVideo
                    outputSettings:videoSettings] retain];
    NSMutableDictionary * bufferAttributes = [[NSMutableDictionary alloc] init];
    [bufferAttributes setObject: [NSNumber numberWithInt: kCVPixelFormatType_32ARGB]
                         forKey: (NSString *) kCVPixelBufferPixelFormatTypeKey];
    [bufferAttributes setObject: [NSNumber numberWithInt: 480]
                         forKey: (NSString *) kCVPixelBufferWidthKey];
    [bufferAttributes setObject: [NSNumber numberWithInt: 320]
                         forKey: (NSString *) kCVPixelBufferHeightKey];


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

    NSMutableDictionary*     attributes;
    attributes = [NSMutableDictionary dictionary];

    int width = 480;
    int height = 320;

    [attributes setObject:[NSNumber numberWithInt:kCVPixelFormatType_32ARGB] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
    [attributes setObject:[NSNumber numberWithInt:width] forKey: (NSString*)kCVPixelBufferWidthKey];
    [attributes setObject:[NSNumber numberWithInt:height] forKey: (NSString*)kCVPixelBufferHeightKey];
    CVReturn theError = CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, (CFDictionaryRef) attributes, &pixelBufferPool);                                           


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

    writerInput.expectsMediaDataInRealTime = YES;
    [videoWriter startWriting];
    [videoWriter startSessionAtSourceTime:kCMTimeZero];

    buffer = NULL;
    lastTime = kCMTimeZero;
    presentTime = kCMTimeZero;

    return YES;
}






   - (void) writeImageToMovie:(CGImageRef)image 
{
    if([writerInput isReadyForMoreMediaData])
    {
        buffer = [self pixelBufferFromCGImage:image];
        BOOL success = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
        if (!success) NSLog(@"Failed to appendPixelBuffer");
        CVPixelBufferRelease(buffer);

        presentTime = CMTimeAdd(lastTime, CMTimeMake(1, 1000));//I think problem is here but what will be given for correct output
        lastTime = presentTime;
    }
    else
    {
        NSLog(@"error - writerInput not ready");
    }
}


    - (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image
{
    CGSize size = CGSizeMake (480.0, 320.0);
    CVPixelBufferRef pxbuffer;
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                             nil];
    if (pixelBufferPool == NULL) NSLog(@"pixelBufferPool is null!");
    CVReturn status = CVPixelBufferPoolCreatePixelBuffer (NULL, pixelBufferPool, &pxbuffer); 
    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pxdata, size.width,
                                                 size.height, 8, 4*size.width, rgbColorSpace, 
                                                 kCGImageAlphaNoneSkipFirst);
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
    CGContextDrawImage(context, CGRectMake(90, 10, CGImageGetWidth(image), 
                                           CGImageGetHeight(image)), image);
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);

    return pxbuffer;
}

What to do with the CMTime variables and how can I made it correctly
One more help how can I add audio with this video.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

熟人话多 2024-12-28 02:21:21

你们的 PTS 非常接近。为什么不是 30FPS:CMTimeMake(1, 30)) 而不是 CMTimeMake(1, 1000)

Your PTSs are very close together. Instead of CMTimeMake(1, 1000), why not 30FPS: CMTimeMake(1, 30))?

不一样的天空 2024-12-28 02:21:21

我修改了你的代码并提出了解决方案,在我的例子中,我在 0.1 秒内记录了我视图中的每个图像,所以我的 fps 是 0.1fps。

presentTime = CMTimeAdd(lastTime, CMTimeMake(1, 10));

你的视频太快的原因是你的比例是1秒变成1000张图像。您可以使其每秒 1 张图像。

presentTime = CMTimeAdd(lastTime, CMTimeMake(1, 1));

尝试一下这个,希望对你有帮助。

I revised you code and came up to the solution, in my case I record every image in my view in 0.1 seconds so my fps is 0.1fps.

presentTime = CMTimeAdd(lastTime, CMTimeMake(1, 10));

The reason why your video is too fast because your ratio is 1 seconds into 1000 image. You can make it 1 image per second.

presentTime = CMTimeAdd(lastTime, CMTimeMake(1, 1));

Try this out, hope it will help you.

天赋异禀 2024-12-28 02:21:21

添加这个库
AV基金会
核心媒体
CoreVideo

我能够生成视频,但无法获取音频是否有人使用此代码并创建带有音频的视频

Add this library
AVFoundation
CoreMedia
CoreVideo

i am able to generate video , but not able to get audio is anyone had use this code and create video with audio

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文