如何控制使用 AVMutableComposition 组装的视频的方向

发布于 2024-10-03 01:59:43 字数 369 浏览 3 评论 0原文

我正在整理一堆在 iPhone 上以纵向模式拍摄的视频剪辑。为了组装它们,我采用如下简单的方法:

AVURLAsset 来获取不同的视频,然后将它们推入 AVMutableCompositionTrack 中,然后将其放入 AVMutableComposition 中,我将使用 AVAssetExportSession 导出到文件中

我的问题是,当我开始显示时UIWebView 中的视频以横向模式显示。但是,如果我查看任何组件视图,它们就会以纵向视图显示。有谁知道如何确定方向。我尝试用 AVMutableComposition naturalSize 改变宽度和高度,但这只会让我的人看起来又矮又胖! (同时在他们这边)

提前感谢

都铎的任何想法/建议

I am assembling a bunch of video clips filmed on the iPhone in portrait mode. To assemble them I am taking straightforward approach as follows:

AVURLAsset to get hold of the different videos then shoving these into an AVMutableCompositionTrack and then putting this into an AVMutableComposition which I'm exporting to file with AVAssetExportSession

My problem is that when I come to display the video in a UIWebView, it is appearing in landscape mode. However, if I view any of the component views they appear in Portrait view. Does anyone know how to sort out the orientation. I tried messing around with the AVMutableComposition naturalSize changing the width and height around but that just made my people look short and fat! (whilst on their side)

Thanks in advance for any thoughts / suggestions

Tudor

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月棠 2024-10-10 01:59:43

如果您想要的只是保留视频方向,您可能需要从 AVAssetTrack 分配 AVMutableCompositionTrack prefferedTransition 值,如下所示:

AVAssetTrack *videoAssetTrack= [[videoAsset tracksWithMediaType:AVMediaTypeVideo] lastObject];

AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:videoAssetTrack atTime:kCMTimeZero error:&error];

videoCompositionTrack.preferredTransform = videoAssetTrack.preferredTransform;

If all you want is preserve you video orientation you may want to assign AVMutableCompositionTrack prefferedTransition value from AVAssetTrack like this:

AVAssetTrack *videoAssetTrack= [[videoAsset tracksWithMediaType:AVMediaTypeVideo] lastObject];

AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:videoAssetTrack atTime:kCMTimeZero error:&error];

videoCompositionTrack.preferredTransform = videoAssetTrack.preferredTransform;
云归处 2024-10-10 01:59:43

设置将处理旋转+缩放的视频合成:

AVMutableVideoComposition* videoComposition = [[AVMutableVideoComposition videoComposition]retain];
videoComposition.renderSize = CGSizeMake(320, 240);
videoComposition.frameDuration = CMTimeMake(1, 30);

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30) );

AVMutableVideoCompositionLayerInstruction* rotator = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]];
CGAffineTransform translateToCenter = CGAffineTransformMakeTranslation( 0,-320);    
CGAffineTransform rotateBy90Degrees = CGAffineTransformMakeRotation( M_PI_2);
CGAffineTransform shrinkWidth = CGAffineTransformMakeScale(0.66, 1); // needed because Apple does a "stretch" by default - really, we should find and undo apple's stretch - I suspect it'll be a CALayer defaultTransform, or UIView property causing this
CGAffineTransform finalTransform = CGAffineTransformConcat( shrinkWidth, CGAffineTransformConcat(translateToCenter, rotateBy90Degrees) );
[rotator setTransform:finalTransform atTime:kCMTimeZero];

instruction.layerInstructions = [NSArray arrayWithObject: rotator];
videoComposition.instructions = [NSArray arrayWithObject: instruction];

Setup a video composition that will handle rotate + scale:

AVMutableVideoComposition* videoComposition = [[AVMutableVideoComposition videoComposition]retain];
videoComposition.renderSize = CGSizeMake(320, 240);
videoComposition.frameDuration = CMTimeMake(1, 30);

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30) );

AVMutableVideoCompositionLayerInstruction* rotator = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:[[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]];
CGAffineTransform translateToCenter = CGAffineTransformMakeTranslation( 0,-320);    
CGAffineTransform rotateBy90Degrees = CGAffineTransformMakeRotation( M_PI_2);
CGAffineTransform shrinkWidth = CGAffineTransformMakeScale(0.66, 1); // needed because Apple does a "stretch" by default - really, we should find and undo apple's stretch - I suspect it'll be a CALayer defaultTransform, or UIView property causing this
CGAffineTransform finalTransform = CGAffineTransformConcat( shrinkWidth, CGAffineTransformConcat(translateToCenter, rotateBy90Degrees) );
[rotator setTransform:finalTransform atTime:kCMTimeZero];

instruction.layerInstructions = [NSArray arrayWithObject: rotator];
videoComposition.instructions = [NSArray arrayWithObject: instruction];
来世叙缘 2024-10-10 01:59:43

以下是一些使用首选变换调整旋转的代码:

    // our composition, with one video and one audio track
AVMutableComposition* composition = [AVMutableComposition composition];
AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

// loop through all the clips, adding them to our track and inserting composition instructions
NSDictionary* options = @{ AVURLAssetPreferPreciseDurationAndTimingKey: @YES };
CMTime insertionPoint = kCMTimeZero;
NSMutableArray* instructions = [NSMutableArray array];
NSError* error = nil;
for (NSURL* outputFileURL in self.movieFileURLs) {
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:outputFileURL options:options];

    // insert this clip's video track into our composition
    NSArray *videoAssetTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    AVAssetTrack *videoAssetTrack = (videoAssetTracks.count > 0 ? [videoAssetTracks objectAtIndex:0] : nil);
    [videoTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, asset.duration) ofTrack:videoAssetTrack atTime:insertionPoint error:&error];

    // create a layer instruction at the start of this clip to apply the preferred transform to correct orientation issues
    AVMutableVideoCompositionLayerInstruction *instruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoAssetTrack];
    [instruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];

    // create the composition instructions for the range of this clip
    AVMutableVideoCompositionInstruction * videoTrackInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    videoTrackInstruction.timeRange = CMTimeRangeMake(insertionPoint, asset.duration);
    videoTrackInstruction.layerInstructions = @[instruction];
    [instructions addObject:videoTrackInstruction];

    // insert this clip's audio track into our composition
    NSArray *audioAssetTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *audioAssetTrack = (audioAssetTracks.count > 0 ? [audioAssetTracks objectAtIndex:0] : nil);
    [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:audioAssetTrack atTime:insertionPoint error:nil];

    // advance the insertion point to the end of the clip
    insertionPoint = CMTimeAdd(insertionPoint, asset.duration);
}

// create our video composition which will be assigned to the player item
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.instructions = instructions;
videoComposition.frameDuration = CMTimeMake(1, videoTrack.naturalTimeScale);
videoComposition.renderSize = videoTrack.naturalSize;
_videoComposition = videoComposition;

Here's some code that adjusted the rotation using the preferred transform:

    // our composition, with one video and one audio track
AVMutableComposition* composition = [AVMutableComposition composition];
AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

// loop through all the clips, adding them to our track and inserting composition instructions
NSDictionary* options = @{ AVURLAssetPreferPreciseDurationAndTimingKey: @YES };
CMTime insertionPoint = kCMTimeZero;
NSMutableArray* instructions = [NSMutableArray array];
NSError* error = nil;
for (NSURL* outputFileURL in self.movieFileURLs) {
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:outputFileURL options:options];

    // insert this clip's video track into our composition
    NSArray *videoAssetTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    AVAssetTrack *videoAssetTrack = (videoAssetTracks.count > 0 ? [videoAssetTracks objectAtIndex:0] : nil);
    [videoTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, asset.duration) ofTrack:videoAssetTrack atTime:insertionPoint error:&error];

    // create a layer instruction at the start of this clip to apply the preferred transform to correct orientation issues
    AVMutableVideoCompositionLayerInstruction *instruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoAssetTrack];
    [instruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];

    // create the composition instructions for the range of this clip
    AVMutableVideoCompositionInstruction * videoTrackInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    videoTrackInstruction.timeRange = CMTimeRangeMake(insertionPoint, asset.duration);
    videoTrackInstruction.layerInstructions = @[instruction];
    [instructions addObject:videoTrackInstruction];

    // insert this clip's audio track into our composition
    NSArray *audioAssetTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *audioAssetTrack = (audioAssetTracks.count > 0 ? [audioAssetTracks objectAtIndex:0] : nil);
    [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:audioAssetTrack atTime:insertionPoint error:nil];

    // advance the insertion point to the end of the clip
    insertionPoint = CMTimeAdd(insertionPoint, asset.duration);
}

// create our video composition which will be assigned to the player item
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.instructions = instructions;
videoComposition.frameDuration = CMTimeMake(1, videoTrack.naturalTimeScale);
videoComposition.renderSize = videoTrack.naturalSize;
_videoComposition = videoComposition;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文