Cocoa: AVAsset, загруженный из файла, имеет 0 дорожек

Я пытаюсь объединить некоторые аудиофайлы, используя технику, показанную здесь. Мои аудиофайлы -.m4a, и я могу проверить, что они отлично работают в Quicktime. Вот код, который я пытаюсь использовать для их конкатенации:

 [currFile.audioContent writeToFile:tempOldFilePath atomically:NO];

    AVURLAsset *oldAudioAsset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:tempOldFilePath] options:nil];
    AVURLAsset *newAudioAsset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:tempInputFilePath] options:nil];

    NSLog(@"oldAsset num tracks = %lu",(unsigned long)oldAudioAsset.tracks.count);
    NSLog(@"newAsset num tracks = %lu",(unsigned long)newAudioAsset.tracks.count);
    AVAssetTrack *oldTrack = [[oldAudioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    AVAssetTrack *newTrack = [[newAudioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

    AVMutableComposition *mutableComposition = [AVMutableComposition composition];

    AVMutableCompositionTrack *compTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

    NSError *error=nil;
    [compTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, oldTrack.timeRange.duration) ofTrack:oldTrack atTime:kCMTimeZero error:&error];
    if (error) {
        NSLog(@"%@",error.localizedDescription);
        error=nil;
    }
    [compTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, newTrack.timeRange.duration) ofTrack:newTrack
                        atTime:oldTrack.timeRange.duration error:&error];

    if (error) {
        NSLog(@"%@",error.localizedDescription);
        error=nil;
    }

    exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPresetAppleM4A];


    exporter.outputURL = [NSURL URLWithString:tempCompFilePath];

    exporter.outputFileType = AVFileTypeAppleM4A;

    [exporter exportAsynchronouslyWithCompletionHandler:^{
        NSLog(@"handller");
        NSError *error=nil;
        NSData *newData = [NSData dataWithContentsOfFile:tempCompFilePath options:0 error:&error];
        NSLog(@"%lu",(unsigned long)newData.length);
        if (error) {
            NSLog(@"%@",error.localizedDescription);
        }

        currFile.audioContent = newData;
        [[AppDelegate sharedDelegate] saveAction:nil];

    }];

Первая проблема, которую я заметил, заключается в том, что метод обработчика-экспортера никогда не вызывается. Я предполагаю, что причина в том, что это другая проблема, которую я заметил: после создания моих AVAssets из URL-адресов, операторы журналов показывают, что они содержат 0 треков. Пример Apple точно не показывает, как загружаются AVAssets.

Любые советы о том, как это сделать?

Ответ 1

Как вы уже нашли, для создания своих URL-адресов вам нужно использовать fileURLWithPath:, а не URLWithString:.

URLWithString: ожидает строку, которая описывает URL-адрес, например @"file:///path/to/file" или @"http://example.com/". Когда ваша строка описывает один путь, например @"/path/to/file", вы должны использовать fileURLWithPath:, который правильно заполнит недостающие части.

Более технически, URLWithString: интерпретирует путь как просто URL-адрес с единственным путем, но не с конкретной схемой, которую вы могли бы использовать относительно базового URL-адреса в любой файловой схеме, такой как HTTP (GET /path/to/file). fileURLWithPath: интерпретирует путь как локальный путь к файлу и возвращает соответственно URL file:.

Ответ 2

Я нашел причину, по которой эта ошибка произошла и в конечном итоге решила ее.

Первоначально я установил путь к исходному файлу как ".mp4". Но тип записанного видеофайла был MOV, поэтому я изменился как ".mov".

NSString *source_file_path = @"temp_video.mov"

вместо

NSString *source_file_path = @"temp_video.mp4"

Проблема была исправлена, и теперь она работает хорошо.

Надеюсь, что это будет полезно для всех.

Ответ 3

По-видимому, я использовал неправильный метод NSURL. Я изменил его на следующее:

AVURLAsset *oldAudioAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:tempOldFilePath] options:nil];

Теперь мои AVAssets имеют по 1 трек. Если кто-то может дать хорошее объяснение, почему это необходимо, я буду принимать этот ответ.