簡體   English   中英

將 CMTimeRange 拆分為多個 CMTimeRange 塊

[英]Split CMTimeRange into multiple CMTimeRange chunks

讓我們假設我有一個CMTimeRange start time和 40 秒duration構建的CMTimeRange

我想通過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 無效,但它似乎不起作用。

任何幫助將不勝感激。

最好的問候, 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")

到您的函數,以便在開發過程中檢測無效調用。

我也需要跨越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
    }
}

我在操場上玩弄它,它似乎有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM