initial commit

This commit is contained in:
David-123 2024-11-17 11:17:14 +08:00
parent aca646d087
commit b17a59c735
10 changed files with 274 additions and 0 deletions

54
app.py Normal file
View File

@ -0,0 +1,54 @@
import sys
from tracemalloc import Frame
from PySide6.QtCore import Qt
from PySide6.QtGui import QColor
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QMainWindow, QFrame
from widgets import OutlinedLabel
class Lyric(QWidget):
def __init__(self):
super().__init__()
self.setLayout(QVBoxLayout())
self.lyrics = []
self.label_now = QLabel()
self.label_now.setObjectName("label_now")
self.label_now.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.label_next = QLabel()
self.label_next.setObjectName("label_next")
self.label_next.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.label_now.setStyleSheet("font-size: 30px; color: pink;")
self.label_next.setStyleSheet("font-size: 30px;")
self.layout().addWidget(self.label_now)
self.layout().addWidget(self.label_next)
self.setStyleSheet("background-color: rgba(255, 255, 255, 0);")
self.label_now.setText("asdasd")
self.label_next.setText("asdasd")
def set_lyrics(self, lyrics):
self.label_now.setText(lyrics[0])
self.label_next.setText(lyrics[1])
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.lyrics = Lyric()
self.frame = QFrame()
self.setCentralWidget(self.frame)
# self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)
self.setWindowFlag(Qt.WindowType.FramelessWindowHint, True)
self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint, True)
self.frame.setLayout(QVBoxLayout())
self.frame.layout().addWidget(self.lyrics)
self.frame.setStyleSheet("background-color: rgba(255, 255, 255, 50);")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Lyric()
window.show()
sys.exit(app.exec())

1
credits.lrc Normal file

File diff suppressed because one or more lines are too long

BIN
credits.mp3 Normal file

Binary file not shown.

16
fakeplayer.py Normal file
View File

@ -0,0 +1,16 @@
class FakePlayer:
def __init__(self):
self.curr_pos = 0.0
def seek(self, pos):
self.curr_pos = float(pos)
def add(self, num):
self.curr_pos += num
def play(self):
...
def stop(self):
...

1
lrc.lrc Normal file
View File

@ -0,0 +1 @@
[00:00.000] 作词 : 後藤正文[00:01.000] 作曲 : 後藤正文/山田貴洋[00:02.000] 编曲 : 三井律郎[01:16.022] 君を待った[01:17.476] 僕は待った[01:19.170] 途切れない明日も過ぎて行って[01:22.161] 立ち止まって振り返って[01:25.318] とめどない今日を嘆き合った[01:28.189][01:28.514] 記憶だって 永遠になんて[01:31.541] 残らないものとおもい知って[01:34.575] 僕はずっと掻きむしって[01:37.718] 心の隅っこで泣いた[01:39.976][01:40.032] そしてどうかなくさないでよって[01:43.884] 高架下、過ぎる日々を[01:46.837] 後悔してんだよって そう言い逃したあの日[01:54.171][02:05.529] 繋ぎ合った時もあった[02:08.720] ほどけない感情持ち寄って[02:11.753] それが僕のすべてだった[02:14.817] それもたった今 失くしたんだ[02:17.930][02:17.998] 形だって 時が経って[02:21.012] 変わりゆくものとおもい知って[02:24.094] 僕はずっと掻きむしって[02:27.232] 塞がれた今日を恨んだ[02:29.518][02:29.553] そしてどうかなくさないでよって[02:33.381] 高架下、過ぎる日々を[02:36.376] 後悔してんだよって そう言い逃したあの日[02:43.652][03:26.096] 君を待った[03:27.668] 僕は待った[03:29.181] 途切れない明日も過ぎて行って[03:32.291] 僕は今日も掻きむしって[03:35.462] 忘れない傷をつけているんだよ[03:43.207] 君じゃないとさ

35
lyric_parse.py Normal file
View File

@ -0,0 +1,35 @@
from re import match
def split_lyric(lyric_str):
lyrics = []
temp_str = ''
for index in range(len(lyric_str)):
if lyric_str[index] == '[' and lyric_str[(index - 1) if index > 0 else index] != ']':
lyrics.append(temp_str)
temp_str = ''
temp_str += lyric_str[index] if lyric_str[index] != '\n' else ''
lyrics.append(temp_str)
return lyrics[1:]
def parse_lyric(lyric_str):
total = {}
lyrics = split_lyric(lyric_str)
for lyric in lyrics:
if not match(r'^(\[[a-zA-Z])', lyric):
temp = lyric.replace('[', '').split(']')
timestamps = temp[:-1]
lyric = temp[-1].strip()
for ts in timestamps:
total[ts] = lyric
sort = {}
for k in sorted(total.keys()):
sort[k] = total[k]
return sort
if __name__ == '__main__':
with open('y.lrc', encoding='utf-8') as f:
for k, v in parse_lyric(f.read()).items():
print(k, v)

BIN
music.mp3 Normal file

Binary file not shown.

66
play.py Normal file
View File

@ -0,0 +1,66 @@
from just_playback import Playback
from time import sleep, time
from lyric_parse import parse_lyric
from threading import Thread
from datetime import datetime
from wcwidth import wcswidth
music = 'music.mp3'
lyric = 'lrc.lrc'
player = Playback(music)
def time_convert(raw):
if isinstance(raw, float):
minutes = int(raw // 60)
seconds = int(raw % 60)
microsec = raw % 1
return datetime.strptime(f'{minutes}:{seconds}.{("%.6f" % microsec)[2:]}', '%M:%S.%f')
elif isinstance(raw, str):
return datetime.strptime(raw, '%M:%S.%f')
else:
return datetime.strptime('00', '%S')
def print_lyric(player, lyrics):
global stopped
lyrics['59:59.999999'] = ''
index = 1
times = list(lyrics.keys())
previous_lrc = ''
while index < len(lyrics) and not stopped:
if index < (len(lyrics) - 1) and time_convert(times[index]) < time_convert(player.curr_pos):
index += 1
continue
if index >= 1 and time_convert(times[index - 1]) > time_convert(player.curr_pos):
index -= 1
continue
if previous_lrc != lyrics[times[index - 1]]:
previous_lrc = lyrics[times[index - 1]]
print('\r' + previous_lrc + '.' * ((40 - wcswidth(previous_lrc)) if 40 > len(previous_lrc) else 0), end='')
sleep(0.01)
if True:
stopped = False
player.play()
player.current_time = 80
with open(lyric, encoding='utf-8') as f:
lyrics = parse_lyric(f.read())
Thread(target=print_lyric, args=(player, lyrics)).start()
try:
while True:
#print_lyric(player, lyrics)
#print(player.current_time)
r = input()
delta = r.count('k') * 5 - (len(r) - r.count('k')) * 5
player.seek(player.curr_pos + delta)
except KeyboardInterrupt:
pass
stopped = True
player.stop()

74
play_ui.py Normal file
View File

@ -0,0 +1,74 @@
from just_playback import Playback
from time import sleep, time
from lyric_parse import parse_lyric
from threading import Thread
from datetime import datetime
from wcwidth import wcswidth
from app import MainWindow, QApplication
music = 'credits.mp3'
lyric = 'credits.lrc'
player = Playback(music)
def time_convert(raw):
if isinstance(raw, float):
minutes = int(raw // 60)
seconds = int(raw % 60)
microsec = raw % 1
return datetime.strptime(f'{minutes}:{seconds}.{("%.6f" % microsec)[2:]}', '%M:%S.%f')
elif isinstance(raw, str):
return datetime.strptime(raw, '%M:%S.%f')
else:
return datetime.strptime('00', '%S')
def display_lyric(player, lyrics, app):
global stopped
lyrics['59:59.999999'] = ''
index = 1
times = list(lyrics.keys())
previous_lrc = ''
while index < len(lyrics) and not stopped:
if index < (len(lyrics) - 1) and time_convert(times[index]) < time_convert(player.curr_pos):
index += 1
continue
if index >= 1 and time_convert(times[index - 1]) > time_convert(player.curr_pos):
index -= 1
continue
if previous_lrc != lyrics[times[index - 1]]:
previous_lrc = lyrics[times[index - 1]]
app.lyrics.set_lyrics([previous_lrc, lyrics[times[index]]])
sleep(0.01)
def catch():
global player
try:
while True:
#print_lyric(player, lyrics)
#print(player.current_time)
r = input()
delta = r.count('k') * 5 - (len(r) - r.count('k')) * 5
player.seek(player.curr_pos + delta)
except KeyboardInterrupt:
pass
if True:
stopped = False
player.play()
player.current_time = 80
app = QApplication()
window = MainWindow()
window.show()
with open(lyric, encoding='utf-8') as f:
lyrics = parse_lyric(f.read())
Thread(target=display_lyric, args=(player, lyrics, window)).start()
Thread(target=catch).start()
app.exec()
stopped = True
player.stop()

27
widgets.py Normal file
View File

@ -0,0 +1,27 @@
from PySide6.QtWidgets import QLabel
from PySide6.QtGui import QPainter, QColor
from PySide6.QtCore import Qt
class OutlinedLabel(QLabel):
def __init__(self, text='', outline_color=QColor(0, 0, 0), outline_width=2, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setText(text)
self.outline_color = outline_color
self.outline_width = outline_width
def paintEvent(self, event):
painter = QPainter(self)
painter.setFont(self.font())
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
# 绘制描边
painter.setPen(self.outline_color)
for dx in range(-self.outline_width, self.outline_width + 1):
for dy in range(-self.outline_width, self.outline_width + 1):
if abs(dx) + abs(dy) <= self.outline_width:
painter.drawText(self.rect().adjusted(dx, dy, dx, dy), Qt.AlignmentFlag.AlignCenter, self.text())
# 绘制文本
painter.setPen(self.palette().windowText().color())
painter.drawText(self.rect(), Qt.AlignmentFlag.AlignCenter, self.text())