我试图在我的iOS设备上传之前旋转视频,因为其他平台(如
Android)不能正确解释iOS记录视频中的旋转信息,因此播放它们不正确地旋转.
我看过下面的堆栈帖子,但没有成功应用任何一个我的情况:
> iOS rotate every frame of video
> Rotating Video w/ AVMutableVideoCompositionLayerInstruction
> AVMutableVideoComposition rotated video captured in portrait mode
> iOS AVFoundation: Setting Orientation of Video
我处理了Apple AVSimpleEditor项目示例,但不幸的是,在创建AVAssetExportSession并调用exportAsynchronouslyWithCompletionHandler时,不会执行任何旋转,更糟糕的是,旋转元数据从生成的文件中被删除.
以下是运行导出的代码:
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:[_mutableComposition copy] presetName:AVAssetExportPresetPassthrough]; exportSession.outputURL = outputURL; exportSession.outputFileType = AVFileType3GPP; exportSession.shouldOptimizeForNetworkUse = YES; exportSession.videoComposition = _mutableVideoComposition; [exportSession exportAsynchronouslyWithCompletionHandler:^(void) { NSLog(@"Status is %d %@",exportSession.status,exportSession.error); handler(exportSession); [exportSession release]; }];
_mutableComposition和_mutableVideoComposition的值由此方法初始化:
- (void) getVideoComposition:(AVAsset*)asset { AVMutableComposition *mutableComposition = nil; AVMutableVideoComposition *mutableVideoComposition = nil; AVMutableVideoCompositionInstruction *instruction = nil; AVMutableVideoCompositionLayerInstruction *layerInstruction = nil; CGAffineTransform t1; CGAffineTransform t2; AVAssetTrack *assetVideoTrack = nil; AVAssetTrack *assetAudioTrack = nil; // Check if the asset contains video and audio tracks if ([[asset tracksWithMediaType:AVMediaTypeVideo] count] != 0) { assetVideoTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0]; } if ([[asset tracksWithMediaType:AVMediaTypeAudio] count] != 0) { assetAudioTrack = [asset tracksWithMediaType:AVMediaTypeAudio][0]; } CMTime insertionPoint = kCMTimeZero; NSError *error = nil; // Step 1 // Create a composition with the given asset and insert audio and video tracks into it from the asset // Check whether a composition has already been created,i.e,some other tool has already been applied // Create a new composition mutableComposition = [AVMutableComposition composition]; // Insert the video and audio tracks from AVAsset if (assetVideoTrack != nil) { AVMutableCompositionTrack *compositionVideoTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,[asset duration]) ofTrack:assetVideoTrack atTime:insertionPoint error:&error]; } if (assetAudioTrack != nil) { AVMutableCompositionTrack *compositionAudioTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,[asset duration]) ofTrack:assetAudioTrack atTime:insertionPoint error:&error]; } // Step 2 // Translate the composition to compensate the movement caused by rotation (since rotation would cause it to move out of frame) t1 = CGAffineTransformMakeTranslation(assetVideoTrack.naturalSize.height,0.0); // Rotate transformation t2 = CGAffineTransformRotate(t1,degreesToRadians(90.0)); // Step 3 // Set the appropriate render sizes and rotational transforms // Create a new video composition mutableVideoComposition = [AVMutableVideoComposition videoComposition]; mutableVideoComposition.renderSize = CGSizeMake(assetVideoTrack.naturalSize.height,assetVideoTrack.naturalSize.width); mutableVideoComposition.frameDuration = CMTimeMake(1,30); // The rotate transform is set on a layer instruction instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; instruction.timeRange = CMTimeRangeMake(kCMTimeZero,[mutableComposition duration]); layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:(mutableComposition.tracks)[0]]; [layerInstruction setTransform:t2 atTime:kCMTimeZero]; // Step 4 // Add the transform instructions to the video composition instruction.layerInstructions = @[layerInstruction]; mutableVideoComposition.instructions = @[instruction]; TT_RELEASE_SAFELY(_mutableComposition); _mutableComposition = [mutableComposition retain]; TT_RELEASE_SAFELY(_mutableVideoComposition); _mutableVideoComposition = [mutableVideoComposition retain]; }
我从AVSERotateCommand from here中提取了这种方法.任何人都可以提出为什么这种方法不能将视频成功旋转90度?
解决方法
因为您正在使用AVAssetExportPresetPassthrough,AVAssetExportSession将忽略videoComposition,请使用任何其他预设.