-
Notifications
You must be signed in to change notification settings - Fork 0
/
__init__.py
80 lines (66 loc) · 2.12 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2021-03-14 14:37:35
# @Author : Chenghao Mou ([email protected])
import html
import regex as re
from typing import Dict, Optional, Tuple, List
from dataclasses import dataclass
from touchbar_lyric.utility import search_intervals
@dataclass
class Song:
title: str
artists: str
target_title: str
target_artists: str
lyric: str
lines: Optional[Dict[Tuple[float, float], str]] = None
intervals: Optional[List[Tuple[float, float]]] = None
def __post_init__(self):
lyric = self.lyric
lyric = html.unescape(lyric)
self.lines = []
self.intervals = []
offset = 0
for line in lyric.split("\n"):
if "[offset:" in line:
offset = int(line[8:-1])
info, *words = line.rsplit("]", 1)
timestamp = re.search(r"\[([0-9]+):([0-9]+)\.([0-9]+)\]", info + "]")
if not timestamp:
continue
minute, second, subsecond = (
timestamp.group(1),
timestamp.group(2),
timestamp.group(3),
)
curr_stamp = int(minute) * 60 + int(second) + int(subsecond) / 100 - offset/1000
self.lines.append((curr_stamp, "".join(words)))
self.intervals.append(curr_stamp)
def anchor(self, timestamp: float) -> Optional[str]:
"""Find current timestamp for this song.
Parameters
----------
timestamp : float
Current timestamp
Returns
-------
Optional[str]
A line or None
Examples
--------
>>> song = Song("Hello", "Adele", "Hello", "Adele", "[01:12.34]Hello")
>>> song.anchor(60)
'Hello'
>>> song.anchor(120)
'Hello'
>>> song = Song("Hello", "Adele", "Hello", "Adele", "")
>>> song.anchor(10) is None
True
"""
if not self.intervals:
return None
idx = search_intervals(self.intervals, timestamp)
if idx != -1:
return self.lines[idx][-1]
return None