2010-08-13 18 views
0

J'essaie de combiner deux .mp3 en un seul fichier .wav en utilisant QTKit. Cela semble fonctionner, mais les dernières secondes du deuxième fichier sont tronquées. Des idées?Combiner et convertir des fichiers MP3 en utilisant QTKit

- (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 
    } 
} 

(Ignore la boucle en attendant QTMovieLoadStateComplete. Je vais passer à l'aide de notifications à l'avenir. Mais pour l'instant, il ne faut pas la matière ...)

Répondre

0

Il semble que le vrai problème était que j'effectuais des requêtes sur l'objet QTMovie juste après sa création. Avant de demander la durée d'un objet QTMovie, vous devez vous assurer qu'il est entièrement chargé. J'ai ajouté ce qui suit:

Cette méthode s'invoqué chaque fois que le LoadState des changements d'objet QTMovie:

QTMovie *segmentTwo = [QTMovie movieWithFile:fileTwo error:NULL]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pasteSegmentToConcatenatedFile:) name:QTMovieLoadStateDidChangeNotification object:segmentTwo]; 
2

1) En général, il y a pas moyen d'obtenir rapidement la durée exacte d'un fichier MP3 arbitraire. Le seul moyen fiable - décoder le fichier entier. Cela est vrai même pour les fichiers CBR (certains encodeurs MP3 ne fournissent pas un débit précis). La [durée du segment] peut donc ne pas convenir aux cas où la durée exacte est requise. Pour vos pupposes, vous pouvez essayer d'utiliser quelque chose comme [segment duration] + delta, ou même un MaxDuration au lieu de [segment duration].

2) Dans certains cas (au moins si les formats des fichiers fusionnés sont les mêmes), vous pouvez simplement fusionner les fichiers en tant que données binaires (sans utiliser QTKit). Plus pricicely: écrire en-tête RIFF-WAV pour le fichier cible; appenguer le flux sonore du premier fichier (c'est-à-dire le fichier source excluant les balises d'en-tête et de queue si présentes); Appeng flux sonore à partir du deuxième fichier; mettre à jour l'en-tête RIFF-WAV.

+0

Existe-t-il un moyen facile de décoder le fichier en utilisant QTKit? Sinon, je peux juste utiliser un delta pour m'assurer que la longueur est suffisamment longue pour que le fichier entier soit ajouté. –

+0

Je ne suis pas sûr en ce qui concerne QTKit, mais cela peut être fait par Core Audio (je commence juste à apprendre Cocoa). Mais si possible, vous devriez éviter de décoder (au moins pour gagner du temps de traitement). Je ne vois pas le besoin de décoder pour vos objectifs particuliers. C'est-à-dire: utilisez simplement une énorme MaxDuration, ou utilisez la suggestion N 2). – VitalyVal

0

Vous pouvez aussi tout simplement mis le film/mp3 chargeur pour être synchrone au lieu de async en utilisant la QTMovieOpenAsyncOKAttribute comme ceci:

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

cette façon la durée est correcte lorsque vous le vérifier comme ceci:

[[myMovie attributeForKey:QTMovieDurationAttribute] QTTimeValue].timeValue;