iPhone SDK. Можно ли вращать видео в AVplayer с помощью AVURLlAsset / AVMutableComposition? - PullRequest
9 голосов
/ 01 марта 2011

У меня есть простой вид для редактирования видео, который использует AVPlayer.Я создаю AVMutableComposition, используя один или несколько AVURLAsset.Все работает нормально, но видео всегда поворачивается на 90 градусов.т.е. если исходное видео было снято в портретном режиме.AVPlayer показывает его в ландшафтном режиме и наоборот.Я просмотрел документацию и «забил» ее до смерти и не могу найти решение.Может, я смотрю не в том месте.

Кто-нибудь может помочь?

Заранее спасибо;

Жан-Пьер

Ответы [ 2 ]

4 голосов
/ 15 мая 2013

Насколько я понимаю, у вас есть некоторые проблемы с ориентацией, например, Портретное видео находится в альбомном режиме, а иногда видео переворачивается с ног на голову. Это связано с ориентацией AVAsset по умолчанию.Все видеофайлы и файлы изображений, записанные с помощью приложения камеры iPhone по умолчанию, имеют видеокадр, установленный на альбомную ориентацию, и поэтому носитель сохраняется в альбомной ориентации.У AVAsset есть свойство lovelyTransform, которое содержит информацию об ориентации мультимедиа, и это применяется к файлу мультимедиа всякий раз, когда вы просматриваете его с помощью приложения «Фотографии» или QuickTime.Вы можете легко исправить это, применив необходимые преобразования к вашим объектам AVAsset.Но поскольку ваши два видеофайла могут иметь разную ориентацию, вам нужно использовать два отдельных экземпляра AVMutableCompositionTrack вместо одного (предположим), как вы это делали изначально.Создайте две видеодорожки AVMutableCompositionTrack Поскольку у вас теперь есть два отдельных экземпляра AVMutableCompositionTrack, вам нужно применить AVMutableVideoCompositionLayerInstruction к каждой дорожке, чтобы исправить ориентацию.Поэтому добавьте следующий код

    //  Create AVMutableVideoCompositionInstruction
AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeAdd(firstAsset.duration, secondAsset.duration));
// Create an AVMutableVideoCompositionLayerInstruction for the first track
AVMutableVideoCompositionLayerInstruction *firstlayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:firstTrack];
AVAssetTrack *firstAssetTrack = [[firstAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
UIImageOrientation firstAssetOrientation_  = UIImageOrientationUp;
BOOL isFirstAssetPortrait_  = NO;
CGAffineTransform firstTransform = firstAssetTrack.preferredTransform;
if (firstTransform.a == 0 && firstTransform.b == 1.0 && firstTransform.c == -1.0 && firstTransform.d == 0) {
    firstAssetOrientation_ = UIImageOrientationRight; 
    isFirstAssetPortrait_ = YES;
}
if (firstTransform.a == 0 && firstTransform.b == -1.0 && firstTransform.c == 1.0 && firstTransform.d == 0) {
    firstAssetOrientation_ =  UIImageOrientationLeft; 
    isFirstAssetPortrait_ = YES;
}
if (firstTransform.a == 1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == 1.0) {
    firstAssetOrientation_ =  UIImageOrientationUp;
}
if (firstTransform.a == -1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == -1.0) {
    firstAssetOrientation_ = UIImageOrientationDown;
}
[firstlayerInstruction setTransform:firstAsset.preferredTransform atTime:kCMTimeZero];
[firstlayerInstruction setOpacity:0.0 atTime:firstAsset.duration];
//  Create an AVMutableVideoCompositionLayerInstruction for the second track
AVMutableVideoCompositionLayerInstruction *secondlayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:secondTrack];
AVAssetTrack *secondAssetTrack = [[secondAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
UIImageOrientation secondAssetOrientation_  = UIImageOrientationUp;
BOOL isSecondAssetPortrait_  = NO;
CGAffineTransform secondTransform = secondAssetTrack.preferredTransform;
if (secondTransform.a == 0 && secondTransform.b == 1.0 && secondTransform.c == -1.0 && secondTransform.d == 0) {
    secondAssetOrientation_= UIImageOrientationRight; 
    isSecondAssetPortrait_ = YES;
}
if (secondTransform.a == 0 && secondTransform.b == -1.0 && secondTransform.c == 1.0 && secondTransform.d == 0) {
    secondAssetOrientation_ =  UIImageOrientationLeft; 
    isSecondAssetPortrait_ = YES;
}
if (secondTransform.a == 1.0 && secondTransform.b == 0 && secondTransform.c == 0 && secondTransform.d == 1.0) {
    secondAssetOrientation_ =  UIImageOrientationUp;
}
if (secondTransform.a == -1.0 && secondTransform.b == 0 && secondTransform.c == 0 && secondTransform.d == -1.0) {
    secondAssetOrientation_ = UIImageOrientationDown;
}
[secondlayerInstruction setTransform:secondAsset.preferredTransform atTime:firstAsset.duration];
}

и, наконец, добавьте инструкции. Это просто исправление ориентации, примененное ко второй дорожке.

    mainInstruction.layerInstructions = [NSArray arrayWithObjects:firstlayerInstruction, secondlayerInstruction,nil];
AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];
mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
mainCompositionInst.frameDuration = CMTimeMake(1, 30);

CGSize naturalSizeFirst, naturalSizeSecond;
if(isFirstAssetPortrait_){
    naturalSizeFirst = CGSizeMake(FirstAssetTrack.naturalSize.height, FirstAssetTrack.naturalSize.width);
} else {
    naturalSizeFirst = FirstAssetTrack.naturalSize;
}
if(isSecondAssetPortrait_){
    naturalSizeSecond = CGSizeMake(SecondAssetTrack.naturalSize.height, SecondAssetTrack.naturalSize.width);
} else {
    naturalSizeSecond = SecondAssetTrack.naturalSize;
}

float renderWidth, renderHeight;
if(naturalSizeFirst.width > naturalSizeSecond.width) {
    renderWidth = naturalSizeFirst.width;
} else {
    renderWidth = naturalSizeSecond.width;
}
if(naturalSizeFirst.height > naturalSizeSecond.height) {
    renderHeight = naturalSizeFirst.height;
} else {
    renderHeight = naturalSizeSecond.height;
}
MainCompositionInst.renderSize = CGSizeMake(renderWidth, renderHeight);

надеюсь, это поможет

1 голос
/ 08 октября 2012

Без кода для проверки трудно понять, что происходит ... Но, скорее всего, ваша проблема вызвана тем, что вы теряете значение своего preferredTransform свойства.

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

...