Портрет Видео воспроизводится на черном экране

Обновить

Не используйте симулятор для проверки перевода видео. Но у меня есть проблема с кодеком, заданная в другом вопросе здесь. Любая помощь приветствуется.

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

Обновление: я безуспешно пытался использовать CGAffineTransform.

Вот код:

-(void) createVideo{

    AVMutableComposition* mixComposition = [AVMutableComposition composition];
    NSDictionary *options = @{AVURLAssetPreferPreciseDurationAndTimingKey:@YES};


    _videoAsset = [[AVURLAsset alloc]initWithURL:video_url options:options];

    CMTime startTimeV=CMTimeMakeWithSeconds(videoStartTime.floatValue, 1);
    CMTime endTimeV=CMTimeMakeWithSeconds(videoEndTime.floatValue, 1);

    CMTimeRange video_timeRange = CMTimeRangeMake(startTimeV,endTimeV);



    AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    [a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[_videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];

    AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, self.videoAsset.duration);

    AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:a_compositionVideoTrack];
    AVAssetTrack *videoAssetTrack = [[self.videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

    CGSize trackDimensions = {
        .width = 0.0,
        .height = 0.0,
    };
    trackDimensions = [videoAssetTrack naturalSize];

    int width = trackDimensions.width;
    int height = trackDimensions.height;


    UIImageOrientation videoAssetOrientation_  = UIImageOrientationUp;
    BOOL isVideoAssetPortrait_  = NO;
    CGAffineTransform videoTransform = videoAssetTrack.preferredTransform;
    if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
        videoAssetOrientation_ = UIImageOrientationRight;
        isVideoAssetPortrait_ = YES;
    }
    if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {
        videoAssetOrientation_ =  UIImageOrientationLeft;
        isVideoAssetPortrait_ = YES;
    }
    if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
        videoAssetOrientation_ =  UIImageOrientationUp;
    }
    if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
        videoAssetOrientation_ = UIImageOrientationDown;
    }
//    CGAffineTransform transformToApply=CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(90.0));

    [videolayerInstruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];
    [videolayerInstruction setOpacity:0.0 atTime:self.videoAsset.duration];

    mainInstruction.layerInstructions = [NSArray arrayWithObjects:videolayerInstruction,nil];

    AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];

    CGSize naturalSize;
    if(isVideoAssetPortrait_){
        naturalSize = CGSizeMake(videoAssetTrack.naturalSize.height, videoAssetTrack.naturalSize.width);
    } else {
        naturalSize = videoAssetTrack.naturalSize;
    }

    float renderWidth, renderHeight;
    renderWidth = naturalSize.width;
    renderHeight = naturalSize.height;
    mainCompositionInst.renderSize = CGSizeMake(renderWidth, renderHeight);
    mainCompositionInst.instructions = [NSArray arrayWithObject:mainInstruction];
    mainCompositionInst.frameDuration = CMTimeMake(1, 30);

И экспорт:

    -(void)export{

        NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *docsDir = [dirPaths objectAtIndex:0];
        NSString* fileName=[NSString stringWithFormat:@"myvideo%lld.mp4",[@(floor([[NSDate date] timeIntervalSince1970])) longLongValue]+1];

        NSString *outputFilePath = [docsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",fileName]];

        NSURL *outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
        if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
            [[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];


        AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
        _assetExport.outputFileType = AVFileTypeMPEG4;
        _assetExport.outputURL = outputFileUrl;
        _assetExport.videoComposition = mainCompositionInst;

        ShareViewController *newViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"vidShare"];

        [_assetExport exportAsynchronouslyWithCompletionHandler:
         ^(void ) {
             dispatch_async(dispatch_get_main_queue(), ^{

                 newViewController.videoFilePath=outputFileUrl;
[self.navigationController pushViewController:newViewController animated:YES];

             });
         }
         ];
    }

Пейзаж = ОК

Горизонтальное видео = ОК

Портрет = НЕ ПРОШЕЛ

Портретное видео = НЕУДАЧА


person Atif Imran    schedule 17.02.2017    source источник


Ответы (1)


У меня была эта проблема раньше. Установка преобразования videolayerInstruction с помощью videoAssetTrack.preferredTransform работает в большинстве случаев. Но иногда в selectedTransform может отсутствовать значение tx(ty) (вам следует проверить CGAffineTransform в Apple API Reference, если вы не знаете, что такое tx(ty)) или tx(ty) имеет неточное значение, что приводит к неправильному позиционированию видео (например, как при воспроизведении на черном экране).
Итак, дело в том, что вы должны использовать PreferredTransform, чтобы определить исходную ориентацию видео и сделать собственное преобразование.
вот код получения ориентации дорожки:

- (UIInterfaceOrientation)orientationForTrack:(AVAsset *)asset {
    UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait;
    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];

    if([tracks count] > 0) {
        AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
        CGAffineTransform t = videoTrack.preferredTransform;

        // Portrait
        if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0) {
            orientation = UIInterfaceOrientationPortrait;
        }
        // PortraitUpsideDown
        if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0) {
            orientation = UIInterfaceOrientationPortraitUpsideDown;
        }
        // LandscapeRight
        if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0) {
            orientation = UIInterfaceOrientationLandscapeRight;
        }
        // LandscapeLeft
        if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0) {
            orientation = UIInterfaceOrientationLandscapeLeft;
        }
    }
    return orientation;
}

И код для получения необходимого преобразования для применения к преобразованию videolayerInstruction:

- (CGAffineTransform)transformBasedOnAsset:(AVAsset *)asset {
    UIInterfaceOrientation orientation = [AVUtilities orientationForTrack:asset];
    AVAssetTrack *assetTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0];
    CGSize naturalSize = assetTrack.naturalSize;
    CGAffineTransform finalTranform;
    switch (orientation) {
        case UIInterfaceOrientationLandscapeLeft:
            finalTranform = CGAffineTransformMake(-1, 0, 0, -1, naturalSize.width, naturalSize.height);
            break;
        case UIInterfaceOrientationLandscapeRight:
            finalTranform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
            break;
        case UIInterfaceOrientationPortrait:
            finalTranform = CGAffineTransformMake(0, 1, -1, 0, naturalSize.height, 0);
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            finalTranform = CGAffineTransformMake(0, -1, 1, 0, 0, naturalSize.width);
            break;
        default:
            break;
    }
    return finalTranform;
}

Надеюсь, это сработает для вас.

person zhoujialei    schedule 17.02.2017
comment
Жаль, что не получилось. Мне намного проще отлаживать, если вы можете предоставить исходное видео. - person zhoujialei; 20.02.2017
comment
Я не должен говорить, что это не сработало. Проблема с кодеками, для кодека H.264 AAC не работает :( - person Atif Imran; 20.02.2017
comment
Вот отвратительное видео, если вы можете попробовать это: expirebox.com/download/e15898a9a4c31fa989e084323e5f02d7.html - person Atif Imran; 20.02.2017
comment
Спасибо. Я посмотрю что я могу сделать. - person zhoujialei; 20.02.2017
comment
Супер полезно! Спасибо! - person Greenwell; 15.01.2019