将 CMTimeRange 拆分为多个 CMTimeRange 块
Split CMTimeRange into multiple CMTimeRange chunks
假设我有一个从 start time
零构造的 CMTimeRange
,并且
duration
40 秒。
我想通过 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
将最后一个chunk剪枝到原来的范围。
备选方案:
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: [=11=], 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: [=13=], duration: length) .intersection(range)
}
}
无论如何,您可能需要添加支票
precondition(length.seconds > 0, "length must be positive")
您的函数,以便在开发过程中检测无效调用。
我也需要大步前进 CMTime
,以处理 AVCaptureDevice
曝光持续时间并将这些显示给用户。
事实证明,随着 Swift 4.x / XCode 10 中的更改,Martin 的回答不再有效。这是我的 CMTime
版本与 [=14 的一致性=]:
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
}
}
我在操场上玩过它,它似乎有效。
假设我有一个从 start time
零构造的 CMTimeRange
,并且
duration
40 秒。
我想通过 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
将最后一个chunk剪枝到原来的范围。
备选方案:
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: [=11=], 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: [=13=], duration: length) .intersection(range)
}
}
无论如何,您可能需要添加支票
precondition(length.seconds > 0, "length must be positive")
您的函数,以便在开发过程中检测无效调用。
我也需要大步前进 CMTime
,以处理 AVCaptureDevice
曝光持续时间并将这些显示给用户。
事实证明,随着 Swift 4.x / XCode 10 中的更改,Martin 的回答不再有效。这是我的 CMTime
版本与 [=14 的一致性=]:
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
}
}
我在操场上玩过它,它似乎有效。