Merge pull request #241 from Java-wyx/speed-up

feat: 添加播放速度控制功能
This commit is contained in:
Alger
2025-05-19 19:17:26 +08:00
committed by GitHub
5 changed files with 115 additions and 4 deletions

View File

@@ -58,7 +58,8 @@ export default {
next: 'Next',
volume: 'Volume',
favorite: 'Favorite {name}',
unFavorite: 'Unfavorite {name}'
unFavorite: 'Unfavorite {name}',
playbackSpeed: 'Playback Speed'
},
eq: {
title: 'Equalizer',

View File

@@ -59,7 +59,8 @@ export default {
volume: '音量',
favorite: '已收藏{name}',
unFavorite: '已取消收藏{name}',
miniPlayBar: '迷你播放栏'
miniPlayBar: '迷你播放栏',
playbackSpeed: '播放速度'
},
eq: {
title: '均衡器',

View File

@@ -161,6 +161,23 @@
</template>
{{ t('player.playBar.playList') }}
</n-tooltip>
<!-- 添加播放速度控制按钮 -->
<n-dropdown
v-if="!isMobile"
:options="playbackRateOptions"
@select="handlePlaybackRateChange"
trigger="click"
:z-index="9999999"
>
<n-tooltip trigger="hover" :z-index="9999999">
<template #trigger>
<div class="play-speed">
<span class="speed-button">{{ playbackRate }}x</span>
</div>
</template>
{{ t('player.playBar.playbackSpeed') }}
</n-tooltip>
</n-dropdown>
</div>
<!-- 播放音乐 -->
<music-full ref="MusicFullRef" v-model="musicFullVisible" :background="background" />
@@ -319,6 +336,23 @@ const playModeText = computed(() => {
}
});
// 播放速度控制
const playbackRate = ref(1.0);
const playbackRateOptions = [
{ label: '0.5x', key: 0.5 },
{ label: '0.75x', key: 0.75 },
{ label: '1.0x', key: 1.0 },
{ label: '1.25x', key: 1.25 },
{ label: '1.5x', key: 1.5 },
{ label: '2.0x', key: 2.0 }
];
const handlePlaybackRateChange = (rate: number) => {
playbackRate.value = rate;
audioService.setPlaybackRate(rate);
};
// 切换播放模式
const togglePlayMode = () => {
playerStore.togglePlayMode();
@@ -702,4 +736,24 @@ const openPlayListDrawer = () => {
color: white;
animation: spin 1s linear infinite;
}
.play-speed {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0 8px;
}
.speed-button {
font-size: 14px;
color: var(--text-color);
padding: 4px 8px;
border-radius: 4px;
background: var(--hover-color);
}
.speed-button:hover {
background: var(--hover-color-dark);
}
</style>

View File

@@ -18,6 +18,8 @@ class AudioService {
private bypass = false;
private playbackRate = 1.0; // 添加播放速度属性
// 预设的 EQ 频段
private readonly frequencies = [31, 62, 125, 250, 500, 1000, 2000, 4000, 8000, 16000];
@@ -143,7 +145,7 @@ class AudioService {
if ('setPositionState' in navigator.mediaSession) {
navigator.mediaSession.setPositionState({
duration: this.currentSound.duration(),
playbackRate: 1.0,
playbackRate: this.playbackRate,
position: this.currentSound.seek() as number
});
}
@@ -565,6 +567,7 @@ class AudioService {
volume: localStorage.getItem('volume')
? parseFloat(localStorage.getItem('volume') as string)
: 1,
rate: this.playbackRate, // 设置初始播放速度
format: ['mp3', 'aac'],
onloaderror: (_, error) => {
console.error('Audio load error:', error);
@@ -747,6 +750,35 @@ class AudioService {
public setCurrentPreset(preset: string): void {
localStorage.setItem('currentPreset', preset);
}
public setPlaybackRate(rate: number) {
if (!this.currentSound) return;
this.playbackRate = rate;
// Howler 的 rate() 在 html5 模式下不生效
this.currentSound.rate(rate);
// 取出底层 HTMLAudioElement改原生 playbackRate
const sounds = (this.currentSound as any)._sounds as any[];
sounds.forEach(({ _node }) => {
if (_node instanceof HTMLAudioElement) {
_node.playbackRate = rate;
}
});
// 同步给 Media Session UI
if ('mediaSession' in navigator && 'setPositionState' in navigator.mediaSession) {
navigator.mediaSession.setPositionState({
duration: this.currentSound.duration(),
playbackRate: rate,
position: this.currentSound.seek() as number
});
}
}
public getPlaybackRate(): number {
return this.playbackRate;
}
}
export const audioService = new AudioService();

View File

@@ -399,6 +399,9 @@ export const usePlayerStore = defineStore('player', () => {
value: 0
}));
// 添加播放速度状态
const playbackRate = ref(1.0);
// 清空播放列表
const clearPlayAll = async () => {
audioService.pause()
@@ -1042,6 +1045,23 @@ export const usePlayerStore = defineStore('player', () => {
setPlayList(newPlayList);
};
// 设置播放速度
const setPlaybackRate = (rate: number) => {
playbackRate.value = rate;
audioService.setPlaybackRate(rate);
// 保存到本地存储
localStorage.setItem('playbackRate', rate.toString());
};
// 初始化播放速度
const initializePlaybackRate = () => {
const savedRate = localStorage.getItem('playbackRate');
if (savedRate) {
playbackRate.value = parseFloat(savedRate);
audioService.setPlaybackRate(playbackRate.value);
}
};
// 初始化播放状态
const initializePlayState = async () => {
const settingStore = useSettingsStore();
@@ -1093,6 +1113,7 @@ export const usePlayerStore = defineStore('player', () => {
localStorage.removeItem('playProgress');
}
}
initializePlaybackRate();
};
const initializeFavoriteList = async () => {
@@ -1343,6 +1364,8 @@ export const usePlayerStore = defineStore('player', () => {
playAudio,
reparseCurrentSong,
setPlayListDrawerVisible,
handlePause
handlePause,
playbackRate,
setPlaybackRate
};
});