肖像video播放黑屏

更新

不要使用模拟器来testingvideo翻译 。 但我在这里有另一个问题的编解码器问题。 任何帮助表示赞赏。

我正在使用AVURLAsset来创build我的video,并且只要从画廊中选取的video处于横向模式,它们就能正常工作。 但是,当我使用纵向video时,它会以黑色屏幕(audio播放)播放,或者帧被扭曲(请参阅图像)。

更新:我尝试使用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]; }); } ]; } 

景观= OK

横向视频=确定

肖像=失败

肖像视频=失败

我以前有过这个问题。 在大多数情况下,使用videoAssetTrack.preferredTransform设置videolayerInstruction的转换。 但有时,首选转换可能缺乏tx(ty)的值(如果您不知道tx(ty)是什么,或者tx(ty)的值不准确,您应该检查CGAffineTransform在Apple API Reference中,导致错误的video定位如在黑屏中播放)。
所以重点是:你应该使用preferredTransform来确定原始的video方向,并进行自己的转换。
这里是获取轨道方向的代码:

 - (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(ta == 0 && tb == 1.0 && tc == -1.0 && td == 0) { orientation = UIInterfaceOrientationPortrait; } // PortraitUpsideDown if(ta == 0 && tb == -1.0 && tc == 1.0 && td == 0) { orientation = UIInterfaceOrientationPortraitUpsideDown; } // LandscapeRight if(ta == 1.0 && tb == 0 && tc == 0 && td == 1.0) { orientation = UIInterfaceOrientationLandscapeRight; } // LandscapeLeft if(ta == -1.0 && tb == 0 && tc == 0 && td == -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; } 

希望对你有效。