QTMovie在29.97与QTMakeTime

时间:2012-01-12 04:26:40

标签: objective-c video quicktime qtkit

我正在尝试使用QTKit将图像列表转换为快速电影。除了得到29.97的帧率之外,我已经想出了如何做所有事情。通过其他论坛和资源,诀窍似乎是使用这样的东西:

QTTime frameDuration = QTMakeTime(1001, 30000)

然而,我使用此方法的所有尝试,甚至(1000,29970)仍然以30fps的速度制作电影。这个fps是玩Quicktime播放器时显示的内容。

有什么想法吗?有没有其他方法可以在整个电影创建后设置帧速率?

以下是一些示例代码:

NSDictionary *outputMovieAttribs = [NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", QTAddImageCodecType, [NSNumber numberWithLong:codecHighQuality], QTAddImageCodecQuality, nil];
QTTime frameDuration = QTMakeTime(1001, 30000);
QTMovie *outputMovie = [[QTMovie alloc] initToWritableFile:@"/tmp/testing.mov" error:nil];
[outputMovie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];
[outputMovie setAttribute:[NSNumber numberWithLong:30000] forKey:QTMovieTimeScaleAttribute];

if (!outputMovie) {
    printf("ERROR: Chunk: Could not create movie object:\n");
} else {
    int frameID = 0;
    while (frameID < [framePaths count]) {
        NSAutoreleasePool *readPool = [[NSAutoreleasePool alloc] init];
        NSData *currFrameData = [NSData dataWithContentsOfFile:[framePaths objectAtIndex:frameID]];
        NSImage *currFrame = [[NSImage alloc] initWithData:currFrameData];

        if (currFrame) {
            [outputMovie addImage:currFrame forDuration:frameDuration withAttributes:outputMovieAttribs];
            [outputMovie updateMovieFile];
            NSString *newDuration = QTStringFromTime([outputMovie duration]);
            printf("new Duration: %s\n", [newDuration UTF8String]);
            currFrame = nil;
        } else {
            printf("ERROR: Could not add image to movie");
        }
        frameID++;
        [readPool drain];
    }
}

NSString *outputDuration = QTStringFromTime([outputMovie duration]);
printf("output Duration: %s\n", [outputDuration UTF8String]);

2 个答案:

答案 0 :(得分:0)

我从未做过你想做的事情,但我可以告诉你如何获得所需的帧速率。 如果您“询问”电影的当前时序信息,您总是会得到一个QTTime结构,其中包含timeScale和timeValue。 对于29.97 fps的视频,您将获得2997的timeScale(例如,见下文)。 这是每秒“单位”的数量。

因此,如果电影的播放位置当前正好是2秒,那么你将获得5994的timeValue。 因此frameDuration为100,因为2997/100 = 29.97 fps。

QuickTime无法处理浮点值,因此您必须通过乘法将所有值转换为long值。 顺便说一下,你不必使用100,你也可以使用1000和timeScale为29970,或200作为帧持续时间和5994 timeScale。如果您从已有的剪辑中读取计时信息,那么我可以告诉您所有内容。 您写道,这对您来说不起作用,但这就是QuickTime在内部的工作方式。 你应该再看看它!

祝你好运

答案 1 :(得分:0)

好的,多亏了你的代码,我可以解决这个问题。我使用名为Atom Inpector的开发工具来查看数据结构与我目前使用的电影完全不同。正如我所说的那样,我从来没有像你那样用图像创作一部电影,但是如果你想要一部电影,这似乎不是你要走的路。 QuickTime将剪辑识别为“Photo-JPEG”,因此不是普通的电影文件。这样做的原因似乎是,添加的图片不会添加到电影轨道中,而只会添加到电影中的某个位置。 Atom Inspector也可以看到这一点。 使用“movieTimeScaleAttribute”,您可以设置未使用的timeScale!

为解决这个问题,我稍微改了一下代码。

NSDictionary *outputMovieAttribs = [NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", 
                      QTAddImageCodecType, [NSNumber numberWithLong:codecHighQuality],
                      QTAddImageCodecQuality,[NSNumber numberWithLong:2997], QTTrackTimeScaleAttribute, nil];

QTTime frameDuration = QTMakeTime(100, 2997);
QTMovie *outputMovie = [[QTMovie alloc] initToWritableFile:@"/Users/flo/Desktop/testing.mov" error:nil];
[outputMovie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];
[outputMovie setAttribute:[NSNumber numberWithLong:2997] forKey:QTMovieTimeScaleAttribute];

其他一切都没有改变。 哦,顺便说一下。要打印timeValue和timeScale,您还可以执行以下操作:

NSLog(@"new Duration timeScale : %ld timeValue : %lld \n", 
       [outputMovie duration].timeScale, [outputMovie duration].timeValue);

通过这种方式,如果您的代码符合要求,您可以更好地查看。

希望有所帮助! 最好的问候