0

我正在尝试使用 QTKit 将两个 .mp3 组合成一个 .wav 文件。它似乎正在工作,但第二个文件的最后几秒钟被截断了。有任何想法吗?

- (IBAction)combineSelectedFilesAndOutputAsWAV {
    QTMovie *movie = [QTMovie movieWithFile:fileOne error:NULL];
    [movie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];  
    QTMovie *segmentTwo = [QTMovie movieWithFile:fileTwo error:NULL];
    QTTimeRange range = { .time = QTZeroTime, .duration = [segmentTwo duration] };
    [segmentTwo setSelection:range];
    [movie appendSelectionFromMovie:segmentTwo];
    while([[movie attributeForKey:QTMovieLoadStateAttribute] longValue] != 100000L) {
        //wait until QTMovieLoadStateComplete
    }
    NSDictionary *exportAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                     [NSNumber numberWithBool:YES], QTMovieExport,
                                     [NSNumber numberWithLong:kQTFileTypeWave], QTMovieExportType, nil];
    NSString *outputFile = [NSString stringWithFormat:@"%@.wav", outputFilename];
    NSString *filepath = [destinationDirectory stringByAppendingPathComponent:outputFile];
    if (![movie writeToFile:filepath withAttributes:exportAttributes]) {
       //ERROR
    } 
}

(忽略等待 QTMovieLoadStateComplete 的 while 循环。我将来会切换到使用通知。但现在,它应该没关系......)

4

3 回答 3

2

1) 通常,没有办法快速获得任意 MP3 文件的确切持续时间。唯一可靠的方法 - 解码整个文件。即使对于 CBR 文件也是如此(某些 MP3 编码器不提供​​准确的比特率)。因此 [segment duration] 可能不适合需要确切持续时间的情况。对于您的 puppose,您可以尝试使用 [segment duration]+delta 之类的东西,甚至是 MaxDuration 而不是 [segment duration]。

2)在某些情况下(至少如果合并文件的格式相同),您可以简单地将文件合并为二进制数据(不使用 QTKit)。更昂贵:为目标文件编写 RIFF-WAV 头;从第一个文件中附加声音流(即源文件,如果存在,则不包括标题和尾标);从第二个文件添加声音流;更新 RIFF-WAV 标头。

于 2010-09-14T23:45:52.110 回答
0

看起来真正的问题是我在创建 QTMovie 对象后立即对其进行查询。在请求 QTMovie 对象的持续时间之前,您应该确保它已完全加载。我添加了以下内容:

- (void)pasteSegmentToConcatenatedFile:(QTMovie *)segment {
    NSLog(@"LoadStateChanged for movie : %@", segment);
    if ([[segment attributeForKey:QTMovieLoadStateAttribute] longValue] >= kMovieLoadStateComplete) {
        NSLog(@"The movie is fully loaded.");
        QTTimeRange range = { .time = QTZeroTime, .duration = [segment duration] };
        [segment setSelection:range];
        [concatenatedFile appendSelectionFromMovie:segment];
        [self convertAndOutputConcatenatedMovie];
    }
}

每当 QTMovie 对象的 LoadState 发生变化时,都会调用此方法:

QTMovie *segmentTwo = [QTMovie movieWithFile:fileTwo error:NULL];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pasteSegmentToConcatenatedFile:) name:QTMovieLoadStateDidChangeNotification object:segmentTwo];
于 2010-09-21T19:54:48.997 回答
0

您还可以使用 QTMovieOpenAsyncOKAttribute 简单地将电影/mp3 加载器设置为同步而不是异步,如下所示:

NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithBool:NO] , QTMovieOpenAsyncOKAttribute,
    @"path to file", QTMovieFileNameAttribute,
    [NSNumber numberWithBool:YES], QTMovieEditableAttribute,
     nil];
QTMovie *myMovie = [QTMovie movieWithAttributes:movieAttributes error:nil];

这样,当您像这样检查时,持续时间应该是正确的:

[[myMovie attributeForKey:QTMovieDurationAttribute] QTTimeValue].timeValue;
于 2010-11-04T08:09:53.620 回答