pyannote源码阅读(一)
前言
读一读代码,顺便记录一下笔记。
pyannote-core源码
Segment类的设计和实现要点
from dataclasses import dataclass
@dataclass(frozen=True, order=True)
class Segment:
start: float = 0.0
end: float = 0.0
def set_precision(ndigits: Optional[int] = None):
global AUTO_ROUND_TIME
global SEGMENT_PRECISION
def __post_init__(self):
if AUDIO_ROUND_TIME:
object.__setattr__(self, 'start', int(self.start / SEGMENT_PRECISION + 0.5) * SEGMENT_PRECISION)
object.__setattr__(self, 'end', int(self.end / SEGMENT_PRECISION + 0.5) * SEGMENT_PRECISION)
@property
duration(self) -> float:
return self.end - self.start if self else 0.
dataclass装饰器
dataclass是从Python3.7版本开始,作为标准库中的模块被引入。
可以简化数据类的设计,在上面的代码中,直接定义属性并初始化。
start: float = 0.0
end: float = 0.0
frozen=True
创建不可变类,不允许更改属性值。
创建一个Segment对象,可以这样Segment(start=1, end=5)
或者 Segment(1, 5)
。
这里有一个细节,如果设置了数值经度,比如保留2位小数,但初始化时使用了三位以上的小数,要如何处理?因为使用了frozen,是无法对属性进行直接修改的。
方法是在__post_init__
方法中使用如下代码:
object.__setattr__(self, 'start', int(self.start / SEGMENT_PRECISION + 0.5) * SEGMENT_PRECISION)
顾名思义,__post_init__
方法在对象初始化之后调用。
- 全局变量
AUTO_ROUND_TIME 是否四舍五入
SEGMENT_PRECISION 精度
迭代器方法
def __iter__(self): -> Iterator[float]:
yield self.start
yield self.end
通过yield
实现,从而支持
segment = Segment(start, end)
start, end = segment
提供的方法
- copy 复制一个Segment
- contains 判读一个Segment是否包含另一个Segment
- and 求两个Segment的交集
- or 求两个Segment的并集
- intersects 判断连个Segment是否相交
- overlaps 判断一个Segment是否覆盖另一个
字符串和图形表示
def __str__(self):
if self:
return '[%s --> %s]' % (self._str_helper(self.start), self._str_helper(self.end))
可以把Segment(1337, 1337 + 0.42)
表示为:[ 00:22:17.000 --> 00:22:17.420]
,very nice。
小结
这是一个非常不错的设计,在音频处理的很多场景都可以参考。