Compare commits

...

6 Commits

Author SHA1 Message Date
底层用户
207f84fcd7 Merge pull request #550 from MoYingJi/feat-settings
refactor(LyricsSetting): 增加歌词内容分组
2025-11-11 22:40:36 +08:00
底层用户
2985aa5977 Merge pull request #549 from MoYingJi/feat-unlock
refactor(unlock): 重写部分 getUnlockSongUrl
2025-11-11 22:39:24 +08:00
底层用户
ffd7aeff49 Merge pull request #548 from MoYingJi/fix-ttml
fix(ttml): 行结束时间过早
2025-11-11 22:37:57 +08:00
MoYingJi
7f4a88daa1 refactor(LyricsSetting): 增加歌词内容分组 2025-11-11 19:26:33 +08:00
MoYingJi
91171465b2 refactor(unlock): 重写部分 getUnlockSongUrl
只是重写,没有改变逻辑,没有改变源和优先级,但使源更容易更改
2025-11-11 19:11:27 +08:00
MoYingJi
1744a5a678 fix(ttml): 行结束时间过早
TTML 有时会为了触发一些效果(比如和下一行连起来)而故意延后行的结束时间(同时词的结束时间不变),`parseTTMLToAMLL` 直接忽略了行的开始结束时间而采用词的开始结束时间
2025-11-11 19:04:30 +08:00
3 changed files with 42 additions and 27 deletions

View File

@@ -244,6 +244,24 @@
</div>
<n-switch v-model:value="settingStore.lyricsBlur" class="set" :round="false" />
</n-card>
</div>
<div class="set-list">
<n-h3 prefix="bar">
歌词内容
</n-h3>
<n-card class="set-item">
<div class="label">
<n-text class="name">
启用在线 TTML 歌词
<n-tag type="warning" size="small" round style="display: inline; vertical-align: middle;">Beta</n-tag>
</n-text>
<n-text class="tip" :depth="3">
是否从 AMLL TTML DB 获取歌词如有TTML
歌词支持逐字翻译音译等功能将会在下一首歌生效
</n-text>
</div>
<n-switch v-model:value="settingStore.enableTTMLLyric" class="set" :round="false" />
</n-card>
<n-card class="set-item">
<div class="label">
<n-text class="name">启用歌词排除</n-text>
@@ -307,17 +325,12 @@
是否使用物理弹簧算法实现歌词动画效果需要高性能设备
</n-text>
</div>
<n-switch v-model:value="settingStore.useAMSpring" class="set" :round="false" />
</n-card>
<n-card class="set-item">
<div class="label">
<n-text class="name">启用在线 TTML 歌词</n-text>
<n-text class="tip" :depth="3">
是否从 AMLL TTML DB 获取歌词如有TTML
歌词支持逐字翻译音译等功能将会在下一首歌生效
</n-text>
</div>
<n-switch v-model:value="settingStore.enableTTMLLyric" class="set" :round="false" />
<n-switch
v-model:value="settingStore.useAMSpring"
class="set"
:round="false"
:disabled="!settingStore.useAMLyrics"
/>
</n-card>
</div>
<div v-if="isElectron" class="set-list">

View File

@@ -423,8 +423,8 @@ export const parseTTMLToAMLL = (
return null;
}
const startTime = words[0].startTime;
const endTime = words[words.length - 1].endTime;
const startTime = line.startTime || words[0].startTime;
const endTime = line.endTime || words[words.length - 1].endTime;
return {
words,

View File

@@ -84,22 +84,24 @@ export const getUnlockSongUrl = async (songData: SongType): Promise<string | nul
const artist = Array.isArray(songData.artists) ? songData.artists[0].name : songData.artists;
const keyWord = songData.name + "-" + artist;
if (!songId || !keyWord) return null;
const servers: any[] = [
"bodian",
"netease",
];
// 尝试解锁
const results = await Promise.allSettled([
unlockSongUrl(songId, keyWord, "bodian"),
unlockSongUrl(songId, keyWord, "netease"),
]);
const promises = servers.map(server => unlockSongUrl(songId, keyWord, server));
const results = await Promise.allSettled(promises);
// 解析结果
const [neteaseRes, kuwoRes] = results;
if (
neteaseRes.status === "fulfilled" &&
neteaseRes.value.code === 200 &&
neteaseRes.value.url
) {
return neteaseRes.value.url;
}
if (kuwoRes.status === "fulfilled" && kuwoRes.value.code === 200 && kuwoRes.value.url) {
return kuwoRes.value.url;
for (const result of results) {
if (
result.status === "fulfilled" &&
result.value.code === 200 &&
result.value.url
) {
return result.value.url;
}
}
return null;
} catch (error) {