2

让我们假设我有一个从零开始 CMTimeRange构建的 40 秒。start timeduration

我想通过X秒分隔符将其CMTimeRange分成多个块。因此,块的 将与原始持续时间相同,并且每个将反映前一个块的。最后一个块将是剩余秒数的模数。total durationdurationstartTimeendTime

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

  1. 第一次CMTimeRange- 开始时间:0,持续时间:15 秒。
  2. CMTimeRange- 开始时间:15,持续时间:15 秒。
  3. 第三CMTimeRange- 开始时间:30,持续时间:10秒。(left overs)

我试过的:

我尝试使用CMTimeSubtract总持续时间并以递归方式再次使用结果,直到 CMTime 无效,但它似乎不起作用。

任何帮助将不胜感激。

最好的问候, 罗伊

4

2 回答 2

4

从 开始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")

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

于 2018-02-14T13:11:57.707 回答
0

我也需要大步前进CMTime,处理AVCaptureDevice曝光时间并将这些展示给用户。

结果马丁的答案不再适用于 Swift 4.x / XCode 10 中的更改。这是我的CMTime一致性版本Strideable

extension CMTime: Strideable {
    public func distance(to other: CMTime) -> TimeInterval {
        return TimeInterval((Double(other.value) / Double(other.timescale)) - (Double(self.value) /  Double(self.timescale)))
    }

    public func advanced(by n: TimeInterval) -> CMTime {
        var retval = self
        retval.value += CMTimeValue(n * TimeInterval(self.timescale))
        return retval
    }
}

我在操场上使用它,它似乎有效。

于 2018-11-24T01:02:48.847 回答