使用QTKit组合和转换MP3文件

时间:2010-08-13 09:03:24

标签: objective-c core-audio qtkit

我正在尝试使用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循环。我将来会切换到使用通知。但是现在,它应该没关系......)

3 个答案:

答案 0 :(得分:2)

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

2)在某些情况下(至少如果合并文件的格式相同),您可以简单地将文件合并为二进制数据(不使用QTKit)。更为谨慎:为目标文件写入RIFF-WAV标头;从第一个文件中追出声音流(即源文件,如果存在,则排除标题和尾部标记);从第二个文件中追出声音流;更新RIFF-WAV标题。

答案 1 :(得分: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];

答案 2 :(得分:0)

您也可以简单地将movie / mp3加载程序设置为同步而不是异步 像这样使用QTMovieOpenAsyncOKAttribute:

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;