假设我有一个从CMTimeRange 0构造的start time,并且
40秒的duration

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

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

  • 第一个CMTimeRange-开始时间:0,持续时间:15秒。
  • 第二个CMTimeRange-开始时间:15,持续时间:15秒。
  • 第三次CMTimeRange-开始时间:30,持续时间:10秒。 (left overs)

  • 我试过的

    我尝试在总持续时间上使用CMTimeSubtract,然后以递归方式再次使用结果,直到CMTime无效为止,但这似乎不起作用。

    我们将不胜感激任何帮助。

    致谢,Roi

    最佳答案

    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")
    

    功能,以便在开发过程中检测无效调用。

    10-06 06:48