AVAssetExportSession не экспортирует аудиодорожки

У меня есть приложение, которое позволяет добавлять несколько видеоресурсов и добавлять одну или несколько звуковых дорожек в композицию. Кажется, все работает, я могу воспроизвести получившуюся композицию с помощью AVPlayer (хотя уровень звука кажется низким). После экспорта композиции в файл звуковая дорожка отсутствует.

Мой код в значительной степени основан на примере кода AVEditDemo из сеансов WWDC10. Я дважды проверил свой код на соответствие с кодом AVEditDemo и не могу найти, в чем может быть проблема. Я также проверял форумы, но там не так много сообщений / решений, связанных с AVFoundation.

Любая помощь приветствуется. Ура,

Жан-Пьер


Метод построения композиции с дополнительными звуковыми дорожками

Примечания:

CompositionArray: содержит ресурсы для создания композиции.
Я могу воспроизвести полученную композицию с помощью AVPlayer (хотя уровень звука кажется низким). После экспорта композиции в файл звуковая дорожка отсутствует.

Мой код в значительной степени основан на примере кода AVEditDemo из сеансов WWDC10. Я дважды проверил свой код на соответствие с кодом AVEditDemo и не могу найти, в чем может быть проблема. Я также проверял форумы, но там не так много сообщений / решений, связанных с AVFoundation.

Любая помощь приветствуется. Ура,

Жан-Пьер


Метод построения композиции с дополнительными звуковыми дорожками

Примечания:

CompositionArray: содержит ресурсы для создания композиции.
Я могу воспроизвести полученную композицию с помощью AVPlayer (хотя уровень звука кажется низким). После экспорта композиции в файл звуковая дорожка отсутствует.

Мой код в значительной степени основан на примере кода AVEditDemo из сеансов WWDC10. Я дважды проверил свой код на соответствие коду AVEditDemo и не могу найти, в чем может быть проблема. Я также проверял форумы, но там не так много сообщений / решений, связанных с AVFoundation.

Любая помощь приветствуется. Ура,

Жан-Пьер


Метод построения композиции с дополнительными звуковыми дорожками

Примечания:

CompositionArray: содержит ресурсы для создания композиции.

Мой код в значительной степени основан на примере кода AVEditDemo из сеансов WWDC10. Я дважды проверил свой код на соответствие коду AVEditDemo и не могу найти, в чем может быть проблема. Я также проверял форумы, но там не так много сообщений / решений, связанных с AVFoundation.

Любая помощь приветствуется. Ура,

Жан-Пьер


Метод построения композиции с дополнительными звуковыми дорожками

Примечания:

CompositionArray: содержит ресурсы для построения композиции.

Мой код в значительной степени основан на примере кода AVEditDemo из сеансов WWDC10. Я дважды проверил свой код на соответствие с кодом AVEditDemo и не могу найти, в чем может быть проблема. Я также проверял форумы, но там не так много сообщений / решений, связанных с AVFoundation.

Любая помощь приветствуется. Ура,

Жан-Пьер


Метод построения композиции с дополнительными звуковыми дорожками

Примечания:

CompositionArray: содержит ресурсы для построения композиции.
AssetView: объект, содержащий AVURLAsset.

- (AVMutableComposition *)buildCompositionObjects
{
// no assets available, return nil
if ([compositionArray count] < 1)
{
    return nil;
}

// get the asset video size
AssetView * view =  [compositionArray objectAtIndex:0];
AVURLAsset * asset = view.asset;

CGSize videoSize = [asset naturalSize];

// create new composition
AVMutableComposition * cmp = [AVMutableComposition composition];

// set the size
cmp.naturalSize = videoSize;

// build composition
[self buildComposition:cmp];

// add any extra audio track
[self addAudioTrackToComposition:cmp];

// return the new composition
return cmp;
}

Метод для создания базовой композиции

- (void) buildComposition:(AVMutableComposition *)cmp
{
// set the start time of contiguous tracks
CMTime nextClipStartTime = kCMTimeZero;

// clear the composition
[cmp removeTimeRange:CMTimeRangeMake(CMTimeMake(0, 600), cmp.duration)];

// add audio and video tracks
AVMutableCompositionTrack *compositionVideoTrack = [cmp addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *compositionAudioTrack = [cmp addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

// loop through all available assets
for (AssetView * view in compositionArray)
{
    AVURLAsset *asset = view.asset;

    CMTimeRange timeRangeInAsset;
    timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [asset duration]);

    AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    [compositionVideoTrack insertTimeRange:timeRangeInAsset ofTrack:clipVideoTrack atTime:nextClipStartTime error:nil];

    // make sure there is an audio track. Had to do this becaaause of this missing audio track issue. Crashes if check is not done  (out of bounds).
    if ([[asset tracksWithMediaType:AVMediaTypeAudio] count] > 0)
    {
        AVAssetTrack *clipAudioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
        [compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:nextClipStartTime error:nil];
    }

    // adjust next asset start
    nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRangeInAsset.duration);
}
}

Метод для добавления дополнительных аудиодорожек

- (void)addAudioTrackToComposition:(AVMutableComposition *)cmp
{
// no audio track, return
if ([audioTracks count] < 1)
{
    return;
}

// base track ID for additional audio tracks 
long baseTrackID = 100;

for (AVURLAsset * audioAsset in audioTracks)
{
    // make sure the audio track fits in the composition
    CMTimeRange commentaryTimeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration);

    if (CMTIME_COMPARE_INLINE(CMTimeRangeGetEnd(commentaryTimeRange), >, [cmp duration]))
    {
        commentaryTimeRange.duration = CMTimeSubtract([cmp duration], commentaryTimeRange.start);
    }

    // Add the audio track.
    AVMutableCompositionTrack *compositionCommentaryTrack = [cmp addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:baseTrackID++];

    [compositionCommentaryTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, commentaryTimeRange.duration) ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:commentaryTimeRange.start error:nil];
}    

}

Метод для экспорта композиции

- (void) save
{

NSString * eventFolder = [NSString stringWithFormat:@"%@/%@-%@", 
               DOCUMENTS_FOLDER, 
               event.title,
               [StringUtils stringForDate:event.timeStamp]];


NSString * exportVideoPath = [NSString stringWithFormat:@"%@/Edits/%@.MOV", eventFolder, [StringUtils stringForDate:[NSDate date]]];

video.path = exportVideoPath;

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetHighestQuality];

NSURL *exportURL = [NSURL fileURLWithPath:exportVideoPath];
exportSession.outputURL = exportURL;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:^
{
    switch (exportSession.status) 
    {
        case AVAssetExportSessionStatusFailed:
        {
            NSLog (@"FAIL");
            [self performSelectorOnMainThread:@selector (doPostExportFailed:)
                                   withObject:nil
                                waitUntilDone:NO];
            break;
        }
        case AVAssetExportSessionStatusCompleted: 
        {
            NSLog (@"SUCCESS");
            [self performSelectorOnMainThread:@selector (doPostExportSuccess:)
                                   withObject:nil
                                waitUntilDone:NO];
            break;
        }
        case AVAssetExportSessionStatusCancelled: 
        {
            NSLog (@"CANCELED");
            [self performSelectorOnMainThread:@selector (doPostExportCancelled:)
                                   withObject:nil
                                waitUntilDone:NO];
            break;
        }
    };
}];

}
5
задан zoul 18 June 2011 в 16:40
поделиться