iOS 中的视频编辑问题

2023-11-29

我目前正在开发一个 iOS 应用程序,它可以合并所需数量的视频。一旦用户点击按钮来合并视频,视频就会被合并,然后使用 AVPlayer 进行播放,如下所示:

CMTime nextClipStartTime = kCMTimeZero;
NSInteger i;
CMTime transitionDuration = CMTimeMake(1, 1); // Default transition duration is one second.

// Add two video tracks and two audio tracks.
AVMutableCompositionTrack *compositionVideoTracks[2];
AVMutableCompositionTrack *compositionAudioTracks[2];
compositionVideoTracks[0] = [self.mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
compositionVideoTracks[1] = [self.mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
compositionAudioTracks[0] = [self.mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
compositionAudioTracks[1] = [self.mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

CMTimeRange *passThroughTimeRanges = alloca(sizeof(CMTimeRange) * [self.selectedAssets count]);
CMTimeRange *transitionTimeRanges = alloca(sizeof(CMTimeRange) * [self.selectedAssets count]);

// Place clips into alternating video & audio tracks in composition, overlapped by transitionDuration.
for (i = 0; i < [self.selectedAssets count]; i++ )
{
    NSInteger alternatingIndex = i % 2; // alternating targets: 0, 1, 0, 1, ...
    AVURLAsset *asset = [self.selectedAssets objectAtIndex:i];

    NSLog(@"number of tracks %d",asset.tracks.count);

    CMTimeRange assetTimeRange;
    assetTimeRange.start = kCMTimeZero;
    assetTimeRange.duration = asset.duration;
    NSValue *clipTimeRange = [NSValue valueWithCMTimeRange:assetTimeRange];
    CMTimeRange timeRangeInAsset;
    if (clipTimeRange)
        timeRangeInAsset = [clipTimeRange CMTimeRangeValue];
    else
        timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [asset duration]);

    AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    [compositionVideoTracks[alternatingIndex] insertTimeRange:timeRangeInAsset ofTrack:clipVideoTrack atTime:nextClipStartTime error:nil];

    AVAssetTrack *clipAudioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
    [compositionAudioTracks[alternatingIndex] insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:nextClipStartTime error:nil];

    // Remember the time range in which this clip should pass through.
    // Every clip after the first begins with a transition.
    // Every clip before the last ends with a transition.
    // Exclude those transitions from the pass through time ranges.
    passThroughTimeRanges[i] = CMTimeRangeMake(nextClipStartTime, timeRangeInAsset.duration);
    if (i > 0) {
        passThroughTimeRanges[i].start = CMTimeAdd(passThroughTimeRanges[i].start, transitionDuration);
        passThroughTimeRanges[i].duration = CMTimeSubtract(passThroughTimeRanges[i].duration, transitionDuration);
    }
    if (i+1 < [self.selectedAssets count]) {
        passThroughTimeRanges[i].duration = CMTimeSubtract(passThroughTimeRanges[i].duration, transitionDuration);
    }

    // The end of this clip will overlap the start of the next by transitionDuration.
    // (Note: this arithmetic falls apart if timeRangeInAsset.duration < 2 * transitionDuration.)
    nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRangeInAsset.duration);
    nextClipStartTime = CMTimeSubtract(nextClipStartTime, transitionDuration);

    // Remember the time range for the transition to the next item.
    transitionTimeRanges[i] = CMTimeRangeMake(nextClipStartTime, transitionDuration);
}

// Set up the video composition if we are to perform crossfade or push transitions between clips.
NSMutableArray *instructions = [NSMutableArray array];

// Cycle between "pass through A", "transition from A to B", "pass through B", "transition from B to A".
for (i = 0; i < [self.selectedAssets count]; i++ )
{
    NSInteger alternatingIndex = i % 2; // alternating targets

    // Pass through clip i.
    AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    passThroughInstruction.timeRange = passThroughTimeRanges[i];
    AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[alternatingIndex]];

    passThroughInstruction.layerInstructions = [NSArray arrayWithObject:passThroughLayer];
    [instructions addObject:passThroughInstruction];

    AVMutableVideoCompositionLayerInstruction *fromLayer;

    AVMutableVideoCompositionLayerInstruction *toLayer;

    if (i+1 < [self.selectedAssets count])
    {
        // Add transition from clip i to clip i+1.

        AVMutableVideoCompositionInstruction *transitionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
        transitionInstruction.timeRange = transitionTimeRanges[i];
        fromLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[alternatingIndex]];
        toLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[1-alternatingIndex]];


        // Fade out the fromLayer by setting a ramp from 1.0 to 0.0.
        [fromLayer setOpacityRampFromStartOpacity:1.0 toEndOpacity:0.0 timeRange:transitionTimeRanges[i]];

        transitionInstruction.layerInstructions = [NSArray arrayWithObjects:fromLayer, toLayer, nil];
        [instructions addObject:transitionInstruction];



    }

    AVURLAsset *sourceAsset = [AVURLAsset URLAssetWithURL:[self.selectedItemsURL objectAtIndex:i] options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]];

    AVAssetTrack *sourceVideoTrack = [[sourceAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];



    CGSize temp = CGSizeApplyAffineTransform(sourceVideoTrack.naturalSize, sourceVideoTrack.preferredTransform);
    CGSize size = CGSizeMake(fabsf(temp.width), fabsf(temp.height));
    CGAffineTransform transform = sourceVideoTrack.preferredTransform;

    self.videoComposition.renderSize = sourceVideoTrack.naturalSize;
    if (size.width > size.height) {

        [fromLayer setTransform:transform atTime:sourceAsset.duration];
    } else {


        float s = size.width/size.height;


        CGAffineTransform new = CGAffineTransformConcat(transform, CGAffineTransformMakeScale(s,s));

        float x = (size.height - size.width*s)/2;

        CGAffineTransform newer = CGAffineTransformConcat(new, CGAffineTransformMakeTranslation(x, 0));

        [fromLayer setTransform:newer atTime:sourceAsset.duration];
    }



}

self.videoComposition.instructions = instructions;

self.videoComposition.frameDuration = CMTimeMake(1, 30);



NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]];

NSURL *url = [NSURL fileURLWithPath:myPathDocs];

self.exporter = [[AVAssetExportSession alloc] initWithAsset:self.mixComposition presetName:AVAssetExportPresetMediumQuality];
self.exporter.outputURL=url;
self.exporter.outputFileType = AVFileTypeQuickTimeMovie;
self.exporter.videoComposition = self.videoComposition;
self.exporter.shouldOptimizeForNetworkUse = YES;

self.playerItem = [AVPlayerItem playerItemWithAsset:self.mixComposition];
self.playerItem.videoComposition = self.videoComposition;
AVPlayer *player = [AVPlayer playerWithPlayerItem:self.playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
[playerLayer setFrame:CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height)];
[[[self imageView] layer] addSublayer:playerLayer];
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[player play];

[[NSNotificationCenter defaultCenter]
 addObserver:self selector:@selector(checkPlayEnded) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];

我目前面临以下问题:

  1. 如果一个视频是纵向的,而另一个是横向的,当我的视图是横向的但纵向视频保留其原始状态时,我如何才能横向旋转纵向视频? (我正在加载存储在相机胶卷中的视频,而不是将它们记录在我的应用程序中)

  2. 忽略上述问题,如果我合并任意数量的视频,它们都可以正常工作。一旦我将该新视频保存在我的库中,然后再次将其加载到我的应用程序中并尝试将该视频与其他一些新视频结合在一起,分辨率就会受到干扰,尽管这两个视频如果在应用程序中单独播放,效果非常好。我该如何解决这个问题?

(我尝试遵循 WWDC 2010 视频编辑教程,因此此代码是从那里提取的。)


当您为 AVMutableVideoComposition 指令创建对象时,您可以在上面的代码中检查视频运行时的方向。

要附加到解决问题的代码中的代码是......

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [mutableComposition duration]);
AVAssetTrack *videoTrack = [[mutableComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

AVMutableVideoCompositionLayerInstruction * layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];

UIImageOrientation videoAssetOrientation_  = UIImageOrientationUp;
BOOL  isVideoAssetPortrait_  = NO;
CGAffineTransform videoTransform = assetVideoTrack.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;
}

CGFloat FirstAssetScaleToFitRatio = 320.0 / assetVideoTrack.naturalSize.width;
if(isVideoAssetPortrait_)
{
    videoSize=CGSizeMake(350,400);
    FirstAssetScaleToFitRatio = 320.0/assetVideoTrack.naturalSize.height;
    CGAffineTransform FirstAssetScaleFactor = CGAffineTransformMakeScale(FirstAssetScaleToFitRatio,FirstAssetScaleToFitRatio);
    [layerInstruction setTransform:CGAffineTransformConcat(assetVideoTrack.preferredTransform, FirstAssetScaleFactor) atTime:kCMTimeZero];
}
else
{
    videoSize=CGSizeMake(assetVideoTrack.naturalSize.width,assetVideoTrack.naturalSize.height);
}

上面的代码将使横向视频保持横向,并防止视频从纵向转换为横向。

我希望这会有所帮助。而不是首先转换为正确的方向,然后应用编辑。如果您附加此代码,您的一步将会减少,并且可以在一个代码中以更快的方式完成两件事(即编辑和方向)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS 中的视频编辑问题 的相关文章

  • 如何使用 iOS 可达性

    我正在开发一个使用网络的 iPhone 应用程序 iPhone 通过 HTTP 请求与我的服务器通信 并且应该可以在 WiFi 和 3G 上运行 我目前使用NSURLConnection initWithRequest向我的服务器发送异步请
  • 使用 UItableviewCell 实现 Google 地图

    我正在尝试在 UItableviewCell 组件内实现谷歌地图 我这样做的方法是在原型单元中定义 GMSMapView 然后使用 dequeueReusableCell 方法配置地图单元 但是 我尝试应用的任何更改都会失败 例如添加标记
  • NSCalendar 返回明年第一周上周一的错误日期

    我使用下面的代码使用随机日期来计算上周一 哪个工作文件但我的代码在明年日期中断 下面是相同的代码 NSDate date NSDate dateWithTimeIntervalSince1970 1483620311 228 NSLog c
  • Swift 3:如何访问48字节CFData中matrix_float3x3的值?

    我正在尝试访问内在矩阵answer https stackoverflow com a 48159895 9296667 通过运行下面的命令 我能够得到一个 48 字节的任意对象 https developer apple com docu
  • NSCFData isRessized 崩溃?

    我目前在控制台中收到此崩溃日志 2011 08 23 19 18 40 064 App 1697 707 NSCFData isResizable unrecognized selector sent to instance 0x11f1c
  • mgwt - 以编程方式改变方向

    是否可以在 gwt mgwt 应用程序中更改强制执行特定的屏幕方向 可以说我希望用户始终以横向模式使用应用程序 这取决于 是作为phonegap应用程序 而不是在浏览器内部 如果您作为 Web 应用程序运行 则不需要t get any co
  • 如何正确创建迦太基 cartfile?

    我正在研究购物车文件 迫不及待地想 简单地创建一个购物车文件 就像所有说明所说的那样 只是 如何 简单地 创建一个 Cartfile 我创建了一个纯文本文档 将其命名为 cartfile 并在其中复制了一些依赖项 Ran carthage
  • .showsPhysics 内存泄漏

    我最近花了 5 个小时尝试调试 Spritekit 应用程序中的内存泄漏 应用程序启动后 我注意到内存使用量略有上升 我花了 5 个小时中的 3 个小时挖掘参考资料 了解强与弱的关系ARC https developer apple com
  • 错误域=kAFAssistantErrorDomain 代码=209“(空)”

    我面临着一个问题SFSpeechRecognizer 启动应用程序几秒钟后 我开始收到错误消息 错误域 kAFAssistantErrorDomain 代码 209 空 和 错误 域 kAFAssistantErrorDomain 代码 2
  • dyld:无法加载插入的库

    当我尝试运行 UI 和单元测试时 出现异常 dyld 无法加载插入的库 private var containers Bundle Application AutoTestingApp app Frameworks IDEBundleInj
  • 在 iPhone 3GS 与 iPhone 4 上为 Mobile Safari 嵌入 HTML5 视频

    我在服务器上的 mp4 文件中有 H 264 AAC 编码的视频 mime 类型的视频 mp4 添加到 Web 服务器 IIS 7 并且我有一个带有视频标签的页面
  • 调整 UIImage 的大小而不将其完全加载到内存中?

    我正在开发一个应用程序 用户可以在其中尝试加载非常非常大的图像 这些图像首先在表格视图中显示为缩略图 我的原始代码会在大图像上崩溃 因此我重写它以首先将图像直接下载到磁盘 是否有一种已知的方法可以调整磁盘上图像的大小 而无需通过以下方式将其
  • 贴纸包会在模拟器上使 iMessage 崩溃,但在 iPhone 上不会崩溃

    按照 Apple 的在线说明和视频在 Xcode 中创建了一个贴纸包 所有图像的尺寸均正确且远低于文件大小阈值 如果我在我的实体 iPhone 上构建并运行贴纸包 一切都会完美运行 如果我在模拟器上构建并运行贴纸包 对于任何模拟的 iPho
  • 在 UIWebView 中播放 Facebook 视频

    有谁知道如何在 Facebook 上播放视频UIWebView 我的应用程序将视频上 传到 Facebook 并检索视频的网址 我想将此网址嵌入到UIWebView播放 我已经为 youtube 解决了这个问题 但没有为 Facebook
  • 在实例化对象之前是否可以检查故事板中是否存在标识符?

    在我的代码中我有这一行 但我想知道是否有办法检查是否 一些控制器 在我将它与 一起使用之前就存在实例化ViewControllerWithIdentifier 方法 如果标识符不存在 则应用程序崩溃 如果没有好的方法 这并不是一个大问题 我
  • 如何在 UICollectionView 中将行居中?

    我有一个UICollectionView与随机细胞 有什么方法可以让我将行居中吗 默认情况下它是这样的 x x x x x x x x x x x x x x 这是所需的布局 x x x x x x x x x x x x 我必须做这样的事
  • 像 TraceGL 一样分析 Objective C 中的代码路径?

    TraceGL 是一个非常简洁的项目 它允许 JS 程序员跟踪 Javascript 中的代码路径 它看起来像这样 我想为 Objective C 构建类似的东西 我知道运行时使跟踪方法调用变得相当容易 但是我如何跟踪控制流 例如 在上面的
  • 更改 iOS7 中 UIAlertView 的字体大小

    我想更改alertView中消息文本和标题文本的字体大小 苹果网站上没有任何文档谈到这一点 但苹果在其子类注释中表示 UIAlertView 类旨在按原样使用 请参考以下链接 https developer apple com librar
  • ios - 如何声明静态变量? [复制]

    这个问题在这里已经有答案了 C 中声明的静态变量如下 private const string Host http 80dfgf7c22634nbbfb82339d46 cloudapp net private const string S
  • 隐藏选项卡栏项目并对齐其他选项卡项目

    在我的应用程序中 我有 4 个选项卡栏项目 我正在 XIB 文件中添加这 4 个选项卡栏项目 最初我必须显示 3 个选项卡栏项目 同步后我必须在我的应用程序中显示第 4 个选项卡栏项目 因此 为此 我使用以下代码隐藏第四个选项卡栏项目 se

随机推荐

  • Linux下如何给进程分配更多内存

    我正在 64 位 Fedora 16 上使用 CAD 程序 有一次该程序突然崩溃并完全退出 我最初的猜测是没有足够的内存可供该程序执行该操作 并且它退出了 为了测试它 我想为该特定程序分配更多内存 这样做时 如果其他程序没有足够的内存 我也
  • 处理“大量”数据时的 WinForms UI 响应能力

    我正在修改一个 Windows 窗体 以允许在后台加载数据 同时 UI 保持响应 数据的检索和绑定都需要相当长的时间 理想情况下 我会在后台执行这两项操作 但是对于我应该在后台执行哪种 UI 更新 如在主线程之外 存在一些模糊性 一个在后台
  • C++ 中的字符串没有越界异常/错误吗? [复制]

    这个问题在这里已经有答案了 string p a cout lt
  • 从 asp.net core api 添加用户声明到 firebase auth

    给定一个 asp net core api 和仅使用 Authorize 属性的工作 firebase 身份验证 如何将自定义声明添加到令牌以使用 Authorize Policy admin 管理 SDK 仅适用于 Node js Jav
  • 创建一种通过网络发送整数的有效方法。传输控制协议

    如何将整数值转换为字节数组 然后通过字节流将它们发送到客户端程序 客户端程序将字节数组转换回整数 我的程序是乒乓球游戏 运行后 它会创建一个服务器 客户端使用对象流通过互联网连接到该服务器现在 一切都运转良好 但似乎效率不高 我的意思是 当
  • 如何检查 Javascript 数组中是否存在多个值

    所以 我正在使用 Jquery 并有两个具有多个值的数组 我想检查是否all第一个数组中的值存在于第二个数组中 例如 例1 数组 A 包含以下值 34 78 89 数组 B 包含以下值 78 67 34 99 56 89 这将返回true
  • 带有伪元素之前的 Z 索引

    我创建了一个带有 before pseudo 元素的 header 元素 伪元素必须位于父元素后面 一切都工作得很好 直到我给我的 标题 一个 z 索引 我想要的 前景中的黄色 标题 背景中的红色伪元素以及黄色 标题 元素上的简单 z 索引
  • 对 IText 7 中的所有 PDF 页面使用单一模板

    我有以下内容PDF模板这对于所有的应该是一致的pages添加到我正在创建的 PDF 中 问题是 我只得到这个模板Page 1仅适用于其余页面空白模板已使用 这是现在正在使用的代码 PdfDocument pdfDoc new PdfDocu
  • 在 Java 中对从数据库检索的一小部分数据执行连接操作。 (上下文:网络应用程序)

    在 Web 应用程序的上下文中 是否适合在 Java 中对从数据库检索的数据 从第一个查询 执行一些 JOIN 操作 并使用该 JOIN 数据进行第二个也是最后一个数据库查询以获得所需的数据 Java 是否为此类实现提供任何内置机制 或者实
  • Laravel 5.2 通过 API 进行身份验证

    我正在使用 Laravel 5 2 开发 RESTful API 在令牌守卫中位于 Illuminate Auth TokenGuard TokenGuard php在第 46 行 标记的列名称定义为api token this gt st
  • Selenium 测试在本地工作但在 Jenkins 中失败

    在工作中 我们为我们的一个应用程序提供了一个自动化套件 该套件设置为在每次提交到 master 部署到产品时运行 并且很长一段时间以来 我们一直在尝试使其足够可靠 测试在 Jenkins 中运行 使用 Selenium webDriver
  • 如何在 Android Canvas 上制作路径动画

    是否可以将动画师附加到路径上 还有其他方法可以在画布上绘制动画线条吗 我在发布之前搜索过此内容 但找不到任何内容 在另外两篇文章中在 Android 的 Canvas 上绘制路径作为动画 and 如何在 Android Canvas 上用动
  • 使用JS或Jquery读取css比例值

    我有这个div div div 我如何获得 transform scale x y 使用 JS 或 jQuery 的元素 id css transform 给我矩阵 但我需要元素的实际比例值 或者 如果我无法直接获得比例 那么将矩阵 转换为
  • Fortran 中不区分大小写的字符串比较

    尽管 Fortran 不区分大小写 但我观察到使用以下命令比较字符串时情况并非如此if查看 当然 用户应该意识到这一点 然而 Fortran 不区分大小写 我潜意识里希望同样适用于字符串检查 实现不区分大小写的字符串比较的有效方法是什么 这
  • ld 在 OSX Leopard 上找不到 X11 库

    我有一个在 Linux 上运行的非常基本的 X11 应用程序 我试图在 OSX 10 5 8 下编译它 我已经安装了X11和X11 SDK 并修改了makefile如下 CFLAGS L usr X11 lib I usr X11 incl
  • 如何从DataFrame中获取Array[Seq[String]]?

    如何通过DataFrame cc into Array Seq String val factors ccCols split val cc dataset select factors head factors tail 我尝试过这种方式
  • 扩展 Typescript 中的内置类型

    我有以下结构 project types global d ts string d ts wdio d ts src Models Resources Components Extensions string ts tsconfig jso
  • 使用 CURRENT_TIMESTAMP 的 Rails 5.2 和 Active Record 迁移

    我有一些属性需要有默认值 我已经设置了迁移以在数据库中设置默认值 如下所示 class AddDefaultsToModel lt ActiveRecord Migration 5 2 def change change column po
  • 如何使用 Perl 动态获取 Web 内容?

    这有点棘手 我猜这个网页使用某种 AJAX 来根据搜索查询提取内容 当我在 Perl 中使用 get 获取页面时 它会获取 php html 后面的脚本代码 但不会获取手动搜索查询时显示的结果 我需要能够获取结果页面的内容 无论如何 在 P
  • iOS 中的视频编辑问题

    我目前正在开发一个 iOS 应用程序 它可以合并所需数量的视频 一旦用户点击按钮来合并视频 视频就会被合并 然后使用 AVPlayer 进行播放 如下所示 CMTime nextClipStartTime kCMTimeZero NSInt