AVMutableComposition поворачивает видео

Недавно я обнаружил проблему с использованием AVMutableComposition, и я ищу некоторое представление об этом.

Я хочу иметь возможность записывать видео в двух направлениях - влево и вправо. Когда я записываю видео в альбомной ориентации (кнопка справа находится справа), они добавляются в композицию и воспроизводятся в правильной ориентации. Однако, если я записываю его влево влево (главная кнопка слева), эти клипы воспроизводятся вверх ногами.

НО, они воспроизводятся только вверх дном, если они вставлены в композицию. В противном случае они играют в правильной ориентации. Почему композиция меняет направление вращения клипов, снятых в ландшафте? Как я могу это исправить? Любая помощь приветствуется!

Ответ 1

Здесь немного проще, если вы просто хотите сохранить оригинальное вращение.

// Grab the source track from AVURLAsset for example.
AVAssetTrack *assetVideoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].lastObject;

// Grab the composition video track from AVMutableComposition you already made.
AVMutableCompositionTrack *compositionVideoTrack = [composition tracksWithMediaType:AVMediaTypeVideo].lastObject;

// Apply the original transform.    
if (assetVideoTrack && compositionVideoTrack) {
   [compositionVideoTrack setPreferredTransform:assetVideoTrack.preferredTransform];
}

// Export...

Ответ 2

Решила мою проблему. Наконец, он смог повернуть дорожку и перевести ее в кадр. Работает как шарм.

    //setting up the first video based on previous recording
    CMTimeRange videoDuration = CMTimeRangeMake(kCMTimeZero, [self.previousRecording duration]);
    AVAssetTrack *clipVideoTrack = [[self.previousRecording tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    AVAssetTrack *clipAudioTrack = [[self.previousRecording tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    [compositionVideoTrack insertTimeRange:videoDuration ofTrack:clipVideoTrack atTime:nextClipStartTime error:nil];
    [compositionAudioTrack insertTimeRange:videoDuration ofTrack:clipAudioTrack atTime:nextClipStartTime error:nil];

    //our first track instruction - set up the instruction layer, then check the orientation of the track
    //if the track is in landscape-left mode, it needs to be rotated 180 degrees (PI)
    AVMutableVideoCompositionLayerInstruction *firstTrackInstruction =
         [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack];

    if([self orientationForTrack:clipVideoTrack] == UIDeviceOrientationLandscapeLeft) {
        CGAffineTransform rotation = CGAffineTransformMakeRotation(M_PI);
        CGAffineTransform translateToCenter = CGAffineTransformMakeTranslation(640, 480);
        CGAffineTransform mixedTransform = CGAffineTransformConcat(rotation, translateToCenter);
        [firstTrackInstruction setTransform:mixedTransform atTime:kCMTimeZero];
    }

Ответ 3

Я думаю, что ответ наверняка лучший вариант, но он лишь частично правильный. На самом деле, чтобы заставить его работать, нам также нужно отрегулировать размер рендеринга экспорта, высоту и ширину размера естественного размера портретной дорожки.

Я только что протестировал его, и я также цитирую раздел "Руководство по программированию AVFoundation" - "Редактирование", в котором предлагается реализовать то, что на самом деле предлагается в ответ @dizy, но с указанным дополнением:

Все объекты AVAssetTrack имеют свойство preferredTransform, которое содержит информацию о ориентации для этой дорожки актива. Это преобразование применяется всякий раз, когда дорожка актива отображается на экране. В предыдущем коде преобразование инструкций слоя устанавливается на преобразование дорожек актива, чтобы видео в новой композиции отображалось правильно после того, как вы отредактируете его размер рендеринга.

Затем код должен быть таким же (только две строки для добавления):

// Grab the source track from AVURLAsset for example.
AVAssetTrack *assetVideoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].lastObject;

// Grab the composition video track from AVMutableComposition you already made.
AVMutableCompositionTrack *compositionVideoTrack = [composition tracksWithMediaType:AVMediaTypeVideo].lastObject;

// Apply the original transform.    
if (assetVideoTrack && compositionVideoTrack) {
   [compositionVideoTrack setPreferredTransform:assetVideoTrack.preferredTransform];
}

flippedSize = CGSize(compositionVideoTrack.naturalSize.height, compositionVideoTrack.naturalSize.width);
composition.renderSize = flippedSize;

// Export..