[英]Split CMTimeRange into multiple CMTimeRange chunks
Lets assume I have a CMTimeRange
constructed from start time
zero, and duration
of 40 seconds.让我们假设我有一个CMTimeRange
start time
和 40 秒duration
构建的CMTimeRange
。
I want to split this CMTimeRange
into multiple chunks by a X seconds divider.我想通过X秒分隔符将此CMTimeRange
拆分为多个块。 So the total duration
of the chunks will be the same duration
as the original duration, and each startTime
will reflect the endTime
of of the previous chunk.所以, total duration
大块的将是相同的duration
为原始持续时间,以及每个startTime
将反映endTime
的前一块的。 The last chunk will be the modulus of the left over seconds.最后一个块将是剩余秒数的模数。
For example, for video of 40 seconds, and divider of 15 seconds per chunk:例如,对于40秒的视频,以及每块15秒的分隔符:
CMTimeRange
- start time: 0, duration: 15 seconds.第一个CMTimeRange
- 开始时间:0,持续时间:15 秒。CMTimeRange
- start time: 15, duration: 15 seconds.第二个CMTimeRange
- 开始时间:15,持续时间:15 秒。CMTimeRange
- start time: 30, duration: 10 seconds.第三个CMTimeRange
- 开始时间:30,持续时间:10 秒。 (left overs)
What I've tried:我试过的:
I tried using CMTimeSubtract
on the total duration and use the result again, in recursive way untill the CMTime in invalid, But it doesn't seems to work.我尝试在总持续时间上使用CMTimeSubtract
并再次使用结果,以递归方式直到 CMTime 无效,但它似乎不起作用。
Any help will be highly appreciated.任何帮助将不胜感激。
Best Regards, Roi最好的问候, Roi
Starting at range.start
, create ranges of the given length until range.end
is reached:在开始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
is used here to prune the last chunk to the original range.在这里使用intersection
将最后一个块修剪到原始范围。
Alternative solution:替代解决方案:
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)
}
}
With a custom extension to make CMTime
adopt the Strideable
protocol带有自定义扩展,使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
}
}
this can be further simplified to这可以进一步简化为
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)
}
}
In any case, you'll might want to add a check无论如何,您可能需要添加支票
precondition(length.seconds > 0, "length must be positive")
to your function, in order to detect invalid calls during development.到您的函数,以便在开发过程中检测无效调用。
I too needed to stride CMTime
, to deal with AVCaptureDevice
exposure durations & showing these to users.我也需要跨越CMTime
来处理AVCaptureDevice
曝光持续时间并将这些显示给用户。
Turns out Martin's answer doesn't work anymore with the changes in Swift 4.x / XCode 10. Here's my version of CMTime
conformance to Strideable
:原来 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
}
}
I derped with it in a playground and it seems to work.我在操场上玩弄它,它似乎有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.