@@ -9,6 +9,7 @@ import { isElectron } from "@/utils/env";
99import { applyBracketReplacement } from "@/utils/lyric/lyricFormat" ;
1010import { applyProfanityUncensor } from "@/utils/lyric/lyricProfanity" ;
1111import {
12+ alignLyricLines ,
1213 alignLyrics ,
1314 isWordLevelFormat ,
1415 parseQRCLyric ,
@@ -110,48 +111,6 @@ class LyricManager {
110111 }
111112 }
112113
113- /**
114- * 对齐本地歌词
115- * @param lyricData 本地歌词数据
116- * @returns 对齐后的本地歌词数据
117- */
118- private alignLocalLyrics ( lyricData : SongLyric ) : SongLyric {
119- // 同一时间的两/三行分别作为主句、翻译、音译
120- const toTime = ( line : LyricLine ) => Number ( line ?. startTime ?? line ?. words ?. [ 0 ] ?. startTime ?? 0 ) ;
121- // 获取结束时间
122- const toEndTime = ( line : LyricLine ) =>
123- Number ( line ?. endTime ?? line ?. words ?. [ line ?. words ?. length - 1 ] ?. endTime ?? 0 ) ;
124- // 取内容
125- const toText = ( line : LyricLine ) => String ( line ?. words ?. [ 0 ] ?. word || "" ) . trim ( ) ;
126- const lrc = lyricData . lrcData || [ ] ;
127- if ( ! lrc . length ) return lyricData ;
128- // 按开始时间分组,时间差 < 0.6s 视为同组
129- const sorted = [ ...lrc ] . sort ( ( a , b ) => toTime ( a ) - toTime ( b ) ) ;
130- const groups : LyricLine [ ] [ ] = [ ] ;
131- for ( const line of sorted ) {
132- const st = toTime ( line ) ;
133- const last = groups [ groups . length - 1 ] ?. [ 0 ] ;
134- if ( last && Math . abs ( st - toTime ( last ) ) < 0.6 ) groups [ groups . length - 1 ] . push ( line ) ;
135- else groups . push ( [ line ] ) ;
136- }
137- // 组装:第 1 行主句;第 2 行翻译;第 3 行音译;不调整时长
138- const aligned = groups . map ( ( group ) => {
139- const base = { ...group [ 0 ] } as LyricLine ;
140- const tran = group [ 1 ] ;
141- const roma = group [ 2 ] ;
142- if ( ! base . translatedLyric && tran ) {
143- base . translatedLyric = toText ( tran ) ;
144- base . endTime = Math . max ( toEndTime ( base ) , toEndTime ( tran ) ) ;
145- }
146- if ( ! base . romanLyric && roma ) {
147- base . romanLyric = toText ( roma ) ;
148- base . endTime = Math . max ( toEndTime ( base ) , toEndTime ( roma ) ) ;
149- }
150- return base ;
151- } ) ;
152- return { lrcData : aligned , yrcData : lyricData . yrcData } ;
153- }
154-
155114 /**
156115 * 从 QQ 音乐获取歌词(封装方法,供在线和本地歌曲使用)
157116 * @param song 歌曲对象,内部自动判断本地/在线并生成缓存 key
@@ -478,7 +437,7 @@ class LyricManager {
478437 } ;
479438 }
480439 // 普通格式
481- let aligned = this . alignLocalLyrics ( { lrcData : parsedLines , yrcData : [ ] } ) ;
440+ let aligned : SongLyric = { lrcData : alignLyricLines ( parsedLines ) , yrcData : [ ] } ;
482441 let usingQRCLyric = false ;
483442 // 如果开启了本地歌曲 QQ 音乐匹配,尝试获取逐字歌词
484443 if ( settingStore . localLyricQQMusicMatch && song ) {
@@ -806,11 +765,8 @@ class LyricManager {
806765 if ( isWordLevelFormat ( format ) ) {
807766 result . yrcData = lines ;
808767 } else {
809- result . lrcData = lines ;
810768 // 应用翻译对齐逻辑
811- const aligned = this . alignLocalLyrics ( result ) ;
812- result . lrcData = aligned . lrcData ;
813- result . yrcData = aligned . yrcData ;
769+ result . lrcData = alignLyricLines ( lines ) ;
814770 }
815771 }
816772 }
@@ -887,7 +843,7 @@ class LyricManager {
887843 const overrideResult = await this . fetchLocalOverrideLyric ( song . id ) ;
888844 if ( ! isEmpty ( overrideResult . data . lrcData ) || ! isEmpty ( overrideResult . data . yrcData ) ) {
889845 // 对齐
890- overrideResult . data = this . alignLocalLyrics ( overrideResult . data ) ;
846+ overrideResult . data . lrcData = alignLyricLines ( overrideResult . data . lrcData ) ;
891847 fetchResult = overrideResult ;
892848 } else if ( song . path ) {
893849 // 本地文件
0 commit comments