【问题标题】:Split CMTimeRange into multiple CMTimeRange chunks将 CMTimeRange 拆分为多个 CMTimeRange 块
【发布时间】:2018-02-14 13:00:16
【问题描述】:

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

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

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

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

我尝试过的:

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

我们将不胜感激。

最好的问候,罗伊

【问题讨论】:

    标签: ios swift avfoundation chunks cmtime


    【解决方案1】:

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

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

    【讨论】:

    • 两者都非常完美!我不得不承认,即使多出一两天,我想出的解决方案也远没有那么干净。再次感谢马丁。超级感谢!
    【解决方案2】:

    我也需要跨越CMTime,处理AVCaptureDevice 曝光持续时间并将这些展示给用户。

    事实证明 Martin 的答案不再适用于 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
        }
    }
    

    我在操场上玩过它,它似乎有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-09
      相关资源
      最近更新 更多