diff --git a/app.py b/app.py new file mode 100644 index 0000000..b4033fe --- /dev/null +++ b/app.py @@ -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()) diff --git a/credits.lrc b/credits.lrc new file mode 100644 index 0000000..032aa1c --- /dev/null +++ b/credits.lrc @@ -0,0 +1 @@ +[00:00.00] 作曲 : Frums[00:01.00] 编曲 : Frums[00:05.36]Now for the official national weather service forecast for Eastern Massachusetts inside of 1-495.[00:11.06]including Boston,issued at 7:21 PM,Thursday,October 22nd.[00:16.26]Tonight:Mostly cloudy with isolated showers until midnight,then mostly clear after midnight.[00:21.78]Lows in the lower 40's.[00:23.46]West winds 10-15mph with gusts up to 25mph.[00:27.99]Chance of rain 20 percent.[00:30.00]Friday:Sunny.Lush color with highs in the lower 50's.[00:33.85]Northwest winds 10-15mph with gusts up to 25mph.[00:38.88]Friday night,mostly clear.[00:40.73]Lows in the mid-30's.[00:42.23]North winds 10-15mph.[00:44.75]Saturday:Partly cloudy.[00:46.01]igh---[00:46.76]High[00:46.84]igh-[00:46.93]igh--[00:47.09]igh----[00:47.18]igh-----[00:47.26]igh------[00:47.35]igh-------[00:47.43]igh--------[00:47.51]igh---------[00:47.60]igh----------...[01:19.78]F[01:19.86]F[01:19.94]F[01:20.02]F[01:20.11]F[01:20.19]F[01:20.27]F[01:20.36]F[01:20.44]Fun[01:20.61]Funding[01:20.78]Funding for[01:20.95]Funding for this[01:21.12]pro[01:21.28]program[01:21.45]program was[01:21.62]program was made[01:21.78]po[01:21.96]possi[01:22.12]possible[01:22.29]possible by[01:22.46]possible by (x2)[01:22.63]possible by (x3)[01:22.79]possible by (x4)[01:22.96]possible by (x5)[01:23.19]Fun[01:23.30]possible by[01:23.38]possible by (x2)[01:23.45]possible by (x3)[01:23.55]possible by (x4)[01:23.63]Funding[01:23.80]possible by[01:23.88]possible by↓ (x2)[01:23.97]possible by↓↓ (x3)[01:24.05]possible by↓↓↓ (x4)[01:24.13]Funding for[01:24.30]Funding for this[01:24.32]Funding for thi[01:24.33]Funding for thii[01:24.34]Funding for thiii[01:24.35]Funding for thiiii[01:24.36]Funding for thiiiii[01:24.37]Funding for thiiiiii[01:24.38]Funding for thiiiiiii[01:24.39]Funding for thiiiiiiiii[01:24.47]pro[01:24.64]program[01:24.80]pro[01:24.97]program[01:25.14]pro[01:25.14]pro (x2)[01:25.31]pro (x3)[01:25.40]pro (x4)[01:25.47]prog[01:25.56]progr[01:25.64]program[01:25.81]Fun[01:25.98]Funding[01:26.15]Funding for[01:26.31]possible by[01:26.48]possible by (x2)[01:26.65]program was made[01:26.82]po[01:26.90]possi[01:27.07]possible[01:27.15]possible by[01:27.32]view[01:27.49]viewers[01:27.65]viewers like[01:27.82]viewers like you.[01:28.16]viewers like[01:28.32]viewers like you.[01:28.66]viewers like[01:28.83]viewers like you.[01:29.16]viewers like[01:29.33]viewers like you.[01:29.66]viewers like[01:29.83]viewers like you.[01:30.18]viewers like[01:30.33]viewers like you.[01:30.67]viewers like[01:30.84]viewers like you.[01:31.01]Fu[01:31.09]Fu (x2)[01:31.17]Fun[01:31.34]Funding[01:31.51]Funding for[01:31.68]Funding for this[01:31.84]pro[01:32.01]program[01:32.18]program was[01:32.35]program was made[01:32.51]po[01:32.68]possi[01:32.85]possible[01:33.01]possible by[01:33.18]possible by (x2)[01:33.36]possible by (x3)[01:33.52]possible by (x4)[01:33.69]possible by (x5)[01:33.85]Fun[01:34.02]possible by[01:34.12]possible by (x2)[01:34.19]possible by (x3)[01:34.27]possible by (x4)[01:34.36]Funding[01:34.53]possible by[01:34.61]possible by↓ (x2)[01:34.69]possible by↓↓ (x3)[01:34.78]possible by↓↓↓ (x4)[01:34.86]Funding for[01:34.94]Funding for this[01:34.96]Funding for thi[01:34.98]Funding for thii[01:35.00]Funding for thiii[01:35.02]Funding for thiiii[01:35.04]Funding for thiiiiii[01:35.06]Funding for thiiiiiii[01:35.08]Funding for thiiiiiiii[01:35.10]Funding for thiiiiiiiii[01:35.20]pro[01:35.36]program[01:35.53]pro[01:35.70]program[01:35.87]pro[01:35.95]pro (x2)[01:36.03]pro (x3)[01:36.18]pro (x4)[01:36.20]prog[01:36.28]progr[01:36.37]program[01:36.54]Fun[01:36.70]Funding[01:36.87]Funding for[01:37.04]possible by[01:37.21]possible by (x2)[01:37.38]program was made[01:37.54]po[01:37.71]possi[01:37.79]possible[01:37.88]possible by[01:38.04]view[01:38.21]viewers[01:38.21]viewers like[01:38.55]viewers like you.[01:38.88]viewers like[01:39.05]viewers like you.[01:39.39]viewers like[01:39.55]viewers like you.[01:39.89]viewers like[01:40.06]viewers like you.[01:40.39]viewers like[01:40.56]viewers like you.[01:40.89]viewers like[01:41.06]viewers like you.[01:41.56]Broad[01:41.73]Broadcast[01:41.90]Cor[01:42.07]Corpo[01:42.15]Corpora[01:42.32]Corporation[01:42.57]Cor[01:42.73]Corpo[01:42.82]Corpora[01:42.99]Corporation[01:43.24]Cor[01:43.41]Corpo[01:43.49]Corpora[01:43.66]Corporation[01:43.91]Cor[01:44.09]Corpo[01:44.16]Cor[01:44.33]Corpo[01:44.41]Cor[01:44.50]Cor (x2)[01:44.58]Cor (x3)[01:44.75]Corpo[01:44.83]Corpora[01:45.00]Corporation[01:45.25]Cor[01:45.41]Corpo[01:45.50]Corpora[01:45.67]Corporation[01:45.92]Cor[01:46.09]Corpo[01:46.17]Corpora[01:46.27]Corporation[01:46.59]Cor[01:46.68]Corpo[01:46.76]Cor[01:46.82]Cor[01:46.84]Corpo (x2)[01:47.01]Corpo (x3)[01:47.26]Cor[01:47.43]Corpo[01:47.51]Corpora[01:47.68]Corporation[01:47.77]Cor[01:47.85]Cor (x2)[01:47.93]Cor (x3)[01:48.10]Corpo[01:48.18]Corpora[01:48.35]Corporation[01:48.44]Cor[01:48.52]Cor (x2)[01:48.60]Cor (x3)[01:48.77]Corpo[01:48.85]Corpora[01:49.02]Corporation[01:49.11]Cor[01:49.19]Cor (x2)[01:49.27]Cor (x3)[01:49.41]Corpo[01:49.53]Corpora[01:49.69]Corporation[01:49.78]Cor[01:49.86]Cor (x2)[01:49.94]Cor↓[01:50.11]Corpo↓[01:50.20]Corpora↓[01:50.36]Corporation↓[01:50.45]Cor↓[01:50.53]Cor↓ (x2)[01:50.61]Cor[01:50.78]Corpo[01:50.87]Corpora[01:51.03]Corporation[01:51.12]Cor[01:51.20]Cor (x2)[01:51.28]Cor (x3)[01:51.36]Corpo[01:51.45]Corpora[01:51.54]Cor[01:51.62]Corpora[01:51.70]Cor[01:51.79]Corpo[01:51.87]Corpora[01:51.96]Cor[01:52.04]Corpo[01:52.12]Corpora[01:52.21]Corporat[01:52.29]Corporati[01:52.37]Corporation[01:52.62]Cor[01:52.71]Corpo[01:52.79]Corpora[01:52.88]Cor[01:52.96]Corpo[01:53.04]Cor[01:53.13]Corpo[01:53.21]Corpora[01:53.30]Cor[01:53.38]Corpo[01:53.46]Corpora[01:53.55]Cor[01:53.63]Corpo[01:53.72]Cor[01:53.80]Corpo[01:53.88]Corpora[01:53.97]Cor[01:54.05]Corpo[01:54.13]Corpora[01:54.22]Cor[01:54.30]Corpo[01:54.39]Cor[01:54.47]Corpora[01:54.55]Cor[01:54.64]Corpo[01:54.72]Cor[01:54.80]Corpo[01:54.89]Cor[01:54.89]Cor (x2)[01:54.97]Cor (x3)[01:55.05]Corpo[01:55.14]Corpora[01:55.22]Cor[01:55.31]Corpo[01:55.39]Cor[01:55.47]Corpo[01:55.56]Corpora[01:55.64]Cor[01:55.73]Corpo[01:55.81]Corpora[01:55.97]Cor[01:56.06]Corpo[01:56.15]Cor[01:56.23]Corpo[01:56.31]Corpora[01:56.40]Cor[01:56.48]Corpo[01:56.56]Corpora[01:56.65]Cor[01:56.73]Corpo[01:56.82]Cor[01:56.90]Corpo[01:56.98]Corpora[01:57.07]Cor[01:57.15]Corpo[01:57.23]Cor[01:57.32]Corpo[01:57.40]Corpora[01:57.49]Corporat[01:57.57]Corporatio[01:57.65]Corporation[01:57.73]Cor[01:57.82]Cor (x2)[01:57.91]Cor (x3)[01:57.99]Corpo[01:58.07]Corpora[01:58.16]Cor[01:58.24]Corpo[01:58.32]Cor[01:58.41]Corpo[01:58.49]Corpora[01:58.58]Cor[01:58.66]Corpo[01:58.74]Corpora[01:58.83]Cor[01:58.91]Corpo[01:58.99]Cor[01:59.09]Corpo[01:59.16]Corpora[01:59.25]Cor[01:59.33]Corpo[01:59.41]Corpora[01:59.50]Cor[01:59.58]Corpo[01:59.66]Cor[01:59.75]Corpo[01:59.83]Corpora[01:59.92]Cor[02:00.00]Corpo[02:00.08]Cor[02:00.17]Corpo[02:00.25]Cor[02:00.34]Corpo[02:00.42]Cor[02:00.50]Cor (x2)[02:00.59]Cor (x3)[02:00.67]Corpo[02:00.75]Corpora[02:00.84]Cor[02:00.92]Corpo[02:01.00]Cor[02:01.09]Corpo[02:01.17]Corpora[02:01.26]Cor[02:01.34]Corpo[02:01.42]Corpora[02:01.51]Cor[02:01.59]Corpo[02:01.68]Cor[02:01.76]Corpo[02:01.84]Corpora[02:01.93]Cor[02:02.01]Corpo[02:02.09]Corpora[02:02.18]Cor[02:02.26]Corpo[02:02.35]Cor[02:02.43]Corpo[02:02.51]Corpora[02:02.60]Cor[02:02.68]Corpo[02:02.77]Cor[02:02.85]Corpo[02:02.93]Corporat[02:03.02]Corporatt[02:03.10]Corporattt[02:03.15]Corporatttt[02:03.20]Corporattttt[02:03.25]Corporatttttt[02:03.30]Corporattttttt[02:03.35]Corporatttttttt[02:03.40]▒Corporattttttttt[02:03.45]▒▒orporatttttttttt[02:03.50]▒▒▒▒▒▒▒▒tttttttttt[02:03.92]▒▒▒▒▒tion[02:04.61]▒▒▒▒[02:05.92]▒▒▒[02:06.22]▒▒[02:07.37]▒[02:14.92]Annual financial suppor[02:15.08]Annual financial suppor (x2)[02:16.09]por[02:16.26]por (x2)[02:16.26]por (x3)[02:16.59]por (x4)[02:16.76]Annual[02:17.09]Annual financial[02:17.77]Annual financial suppor[02:18.10]Annual[02:18.44]Annual financial[02:19.10]Annual financial suppor[02:19.44]Annual[02:19.78]Annual financial[02:20.45]Annual financial suppor[02:20.78]Annual[02:21.11]Annual financial[02:21.79]Annual financial suppor[02:22.12]Annual[02:22.46]Annual financial[02:23.13]Annual financial suppor[02:23.46]Annual[02:23.80]Annual financial[02:24.13]th[02:24.21]tha[02:24.30]than[02:24.39]thank[02:24.47]thank you.[02:24.80]By[02:24.89]Byci[02:24.97]Bycipo[02:25.05]Bycipor[02:25.13]Bycipo[02:25.22]Bycipor[02:25.31]Bycipo[02:25.39]Byciporoa[02:25.47]Byciporrrr[02:25.59]Byciporrrro[02:25.64]Byciporrrroo[02:25.73]Byciporrrrooo[02:25.81]Byciporoa[02:25.89]Byciporoaa[02:25.98]Byciporoaaa[02:26.06]Byciporoaaaa[02:26.15]Byciporoaaaaa[02:26.23]wers[02:26.31]wersble[02:26.40]wersbb[02:26.48]wersbbb[02:26.56]wersbf[02:26.65]wersbff[02:26.73]wersblefi[02:26.82]wersblefii[02:26.90]wersblefiii[02:27.06]wersblefia[02:27.15]wersblefina[02:27.23]wersblefinaa[02:27.32]wersblefinaaa[02:27.40]wersblefinaaaa[02:27.49]Fun[02:27.65]Fun (x2)[02:27.82]Funding[02:27.99]Fun[02:28.07]Fun (x2)[02:28.24]Fun (x3)[02:28.32]Fun[02:28.49]Funding[02:28.66]Fun[02:28.74]Fun (x2)[02:28.83]Fun (x3)[02:28.99]Fun[02:29.16]Funding[02:29.33]Fun[02:29.41]Fun (x2)[02:29.58]Fun (x3)[02:29.66]Fun[02:29.83]Funding[02:29.92]ding[02:30.08]Fi[02:30.17]porti[02:30.17]Fin[02:30.34]Fina[02:30.42]Finan[02:30.50]po[02:30.59]poc[02:30.67]pocor[02:30.75]by[02:30.84]por[02:31.26]portio[02:31.34]portion[02:31.42]portionn[02:31.51]portionnn[02:31.59]portionnnn[02:31.68]By[02:31.76]By (x2)[02:31.84]By (x3)[02:31.93]By (x4)[02:32.01]B[02:32.09]By[02:32.18]B[02:32.26]B (x2)[02:32.35]B (x3)[02:32.43]B (x4)[02:32.51]By[02:32.60]By (x2)[02:32.85]B[02:33.02]By[02:33.10]By (x2)[02:33.18]By (x3)[02:33.27]By (x4)[02:33.35]By[02:33.44]finan[02:33.52]B[02:33.60]B (x2)[02:33.69]nc[02:33.70]nc (x2)[02:33.85]nc (x3)[02:33.94]nc (x4)[02:34.02]Cor[02:34.07]Corr[02:34.09]Corrr[02:34.11]Corrrr[02:34.13]Corrrrr[02:34.15]Corrrrrr[02:34.17]Corrrrrrr[02:34.19]Corrrrrrrr[02:34.36]viewer[02:34.44]viewer like[02:34.61]viewer like you.[02:34.78]viewer like[02:34.94]viewer like you.[02:35.11]viewer like[02:35.20]viewer like you.[02:35.36]Fun[02:35.53]Funding[02:35.78]Fun[02:35.95]Funding[02:36.12]Fun[02:36.28]Fun (x2)[02:36.37]Fun[02:36.54]Funding[02:36.70]Fun↑[02:36.79]Fun↑↑[02:36.87]Fun↑↑↑[02:36.96]Fun↑↑↑↑[02:37.04]Fun↑↑↑↑↑[02:37.12]Fun↑↑↑↑↑↑[02:37.21]Fun↑↑↑↑↑↑↑[02:37.29]Fun↑↑↑↑↑↑↑↑[02:37.37]Fun↑↑↑↑↑↑↑↑↑[02:37.46]Fun↑↑↑↑↑↑↑↑↑↑[02:37.54]Fun↑↑↑↑↑↑↑↑↑↑↑[02:37.71]Corpora[02:37.87]Corporation[02:37.96]Corporationn[02:38.00]Corporationnn[02:38.03]Corporationnnn[02:38.05]Corporationnnnn[02:38.07]Corporationnnnnn[02:38.09]Corporationnnnnnn[02:38.11]Corporationnnnnnnn[02:38.13]Corporationnnnnnnnn[02:38.21]The[02:38.38]The corporation[02:38.55]The corporation for[02:39.14]and annual[02:39.30]The corporation for public[02:39.55]The corporation for public broadcasting[02:39.97]and[02:40.15]financial su[02:40.64]of[02:40.67]off[02:40.69]offf[02:40.71]offff[02:40.73]offfff[02:40.89]financial[02:41.48]for financial[02:41.73]s-[02:41.83]s--[02:41.90]s---[02:42.06]i[02:42.23]in[02:42.65]viewers[02:43.24]viewers you[02:43.91]this[02:44.26]this is[02:44.92]P[02:45.00]PB[02:45.08]PBS.[02:45.34]PBS..[02:45.42]PBS...[02:45.50]PBS....[02:45.59]PBS.....[02:45.67]PBS......[02:45.75]PBS.......[02:45.84]PBS........[02:45.92]------------[02:46.26]Here are the 7PM observations for the Boston metropolitan area.[02:50.70]At Logan Airport,it was cloudy.[02:53.30]The temperature was 68°.[02:55.64]The dew point,47.[02:56.98]And the relative humidity,46 percent.[03:00.00]The wind was southwest at 13mph.[03:03.18]The pressure was 29.99" and is rising.[03:07.04]Elsewher[03:07.30]Elsewherr[03:07.37]Elsewherrr[03:07.46]Elsewherrrr[03:07.54]Elsewherrrrr[03:07.63]Elsewherrrrrr[03:07.71]Elsewherrrrrrr[03:28.54]F[03:28.62]F[03:28.70]F[03:28.78]F[03:28.86]F[03:28.92]F[03:29.00]F[03:29.08]F[03:29.16]Fun[03:29.33]Funding[03:29.50]Funding for[03:29.66]Funding for this pro[03:30.00]program[03:30.17]program was[03:30.34]program was made[03:30.50]Poss[03:30.67]Possible[03:31.00]Possible by[03:31.17]Possible by (x2)[03:31.34]Possible by (x3)[03:31.51]Possible by (x4)[03:31.68]Possible by (x5)[03:31.84]Fun[03:32.01]By[03:32.02]thi[03:32.04]thii[03:32.06]thiii[03:32.08]thiiii[03:32.09]By (x2)[03:32.10]thiiiii[03:32.12]thiiiiii[03:32.14]thiiiiiii[03:32.16]thiiiiiiii[03:32.18]By (x3)[03:32.18]thiiiiiiiii[03:32.26]By (x4)[03:32.35]Funding[03:32.51]by[03:32.60]by (x2)[03:32.68]by (x3)[03:32.77]by (x4)[03:32.85]for[03:33.35]Program.[03:33.52]Pro[03:33.69]gram.[03:33.94]pro[03:34.02]pro (x2)[03:34.11]pro (x3)[03:34.19]pro (x4)[03:34.53]Fun[03:34.69]Funding[03:34.86]Funding for[03:35.02]by[03:35.20]by[03:35.36]made[03:35.53]poss[03:35.70]possible[03:35.87]possible by[03:36.03]view[03:36.20]viewers[03:36.37]viewers like[03:36.54]viewers like you.[03:36.87]viewers like[03:37.04]viewers like you.[03:37.37]viewers like[03:37.54]viewers like you.[03:37.88]viewers like[03:38.04]viewers like you.[03:38.38]viewers like[03:38.55]viewers like you.[03:38.88]viewers like[03:39.05]viewers like you.[03:39.39]viewers like[03:39.55]viewers like you.[03:39.72]Fun[03:39.80]Fun (x2)[03:39.89]Fun[03:40.05]Funding for[03:40.39]Funding for this[03:40.56]Funding for this program[03:40.73]Funding for this program was[03:40.89]Funding for this program was made[03:41.06]Possi[03:41.23]Possible[03:41.73]By[03:41.90]by (x2)[03:42.07]by (x3)[03:42.23]by (x4)[03:42.40]by (x5)[03:42.57]Fun[03:42.65]By[03:42.74]by (x2)[03:42.82]by (x3)[03:42.90]by (x4)[03:42.99]by (x5)[03:43.07]Funding[03:43.24]Fun↓[03:43.32]Fun↓↓[03:43.40]Fun↓↓↓[03:43.49]Fun↓↓↓↓[03:43.58]Funding[03:43.74]ding[03:43.76]diing[03:43.78]diiing[03:43.80]diiiing[03:43.82]diiiiing[03:43.84]diiiiiing[03:43.86]diiiiiiing[03:43.88]diiiiiiiing[03:43.91]diiiiiiiiing[03:44.08]Pro[03:44.25]Program.[03:44.58]Pro[03:44.66]Pro (x2)[03:44.75]Pro (x3)[03:44.83]Pro[03:44.92]Program.[03:45.25]Fun[03:45.42]Funding[03:45.59]Funding for[03:45.75]by[03:45.92]by (x2)[03:46.09]made[03:46.26]possi[03:46.59]possible[03:46.76]possible view[03:46.93]possible viewers[03:47.01]like[03:47.26]like you.[03:47.60]like[03:47.77]like you.[03:48.10]like[03:48.27]like you.[03:48.60]like[03:48.77]like you.[03:49.11]like[03:49.27]like you.[03:49.61]like[03:49.78]like you.[04:05.36]Funding for this program was made...[04:08.04]Possible by viewers like you.[04:10.73]Funding for this program was made...[04:13.41]Possible by viewers like...[04:15.08]YOU diff --git a/credits.mp3 b/credits.mp3 new file mode 100644 index 0000000..f12275d Binary files /dev/null and b/credits.mp3 differ diff --git a/fakeplayer.py b/fakeplayer.py new file mode 100644 index 0000000..bdac68c --- /dev/null +++ b/fakeplayer.py @@ -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): + ... + diff --git a/lrc.lrc b/lrc.lrc new file mode 100644 index 0000000..786efaa --- /dev/null +++ b/lrc.lrc @@ -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] 君じゃないとさ diff --git a/lyric_parse.py b/lyric_parse.py new file mode 100644 index 0000000..dfeac08 --- /dev/null +++ b/lyric_parse.py @@ -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) + diff --git a/music.mp3 b/music.mp3 new file mode 100644 index 0000000..8ddf20d Binary files /dev/null and b/music.mp3 differ diff --git a/play.py b/play.py new file mode 100644 index 0000000..92c4c55 --- /dev/null +++ b/play.py @@ -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() diff --git a/play_ui.py b/play_ui.py new file mode 100644 index 0000000..853d2df --- /dev/null +++ b/play_ui.py @@ -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() diff --git a/widgets.py b/widgets.py new file mode 100644 index 0000000..7df4af3 --- /dev/null +++ b/widgets.py @@ -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())