将CMTimeRange拆分为多个CMTimeRange块

时间:2018-02-14 13:00:16

标签: ios swift avfoundation chunks cmtime

假设我有CMTimeRangestart time零构造,并且  duration 40秒。

我想通过 X 秒分隔符将此CMTimeRange拆分为多个块。因此,total duration块的duration与原始持续时间相同startTime,每个endTime将反映前一个块的CMTimeRange。最后一个块将是左侧的模数

例如,对于 40 秒的视频,以及每个块 15 秒的分隔符:

  1. 首先CMTimeRange - 开始时间:0,持续时间:15秒。
  2. CMTimeRange - 开始时间:15,持续时间:15秒。
  3. 第三(left overs) - 开始时间:30,持续时间:10秒。 CMTimeSubtract
  4. 我尝试过的事情:

    我尝试在总持续时间上使用{{1}},并以递归方式再次使用结果,直到CMTime无效,但它似乎没有效果。

    任何帮助都将受到高度赞赏。

    最诚挚的问候,Roi

2 个答案:

答案 0 :(得分:2)

range.start开始,创建给定长度的范围 直到达到range.end

func splitIntoChunks(range: CMTimeRange, length: CMTime) -> [CMTimeRange] {

    var chunks: [CMTimeRange] = []
    var from = range.start
    while from < range.end {
        chunks.append(CMTimeRange(start: from, duration: length).intersection(range))
        from = from + length
    }

    return chunks
}
此处使用

intersection将最后一个块修剪到原始范围。

替代解决方案:

func splitIntoChunks(range: CMTimeRange, length: CMTime) -> [CMTimeRange] {

    return stride(from: range.start.seconds, to: range.end.seconds, by: length.seconds).map {
        CMTimeRange(start: CMTime(seconds: $0, preferredTimescale: length.timescale), duration: length)
            .intersection(range)
    }

}

使用自定义扩展程序CMTime采用Strideable 协议

extension CMTime: Strideable {
    public func distance(to other: CMTime) -> TimeInterval {
        return other - self
    }

    public func advanced(by n: TimeInterval) -> CMTime {
        return self + n
    }
}

这可以进一步简化为

func splitIntoChunks(range: CMTimeRange, length: CMTime) -> [CMTimeRange] {

    return stride(from: range.start, to: range.end, by: length.seconds).map {
        CMTimeRange(start: $0, duration: length) .intersection(range)
    }
}

无论如何,您可能想要添加支票

precondition(length.seconds > 0, "length must be positive")

到您的函数,以便在开发过程中检测无效调用。

答案 1 :(得分:0)

我也需要大步前进CMTime,以应对AVCaptureDevice的曝光时间并将其显示给用户。

结果发现,在Swift 4.x / XCode 10中,Martin的答案不再起作用了。这是我对CMTime的{​​{1}}遵从性版本:

Strideable

我在操场上玩着它,似乎很正常。