向浏览器回报歌曲元数据
This commit is contained in:
parent
d89dd55a51
commit
d63e18f0c7
|
@ -2,7 +2,7 @@
|
||||||
import { usePlayQueueStore } from '../stores/usePlayQueueStore'
|
import { usePlayQueueStore } from '../stores/usePlayQueueStore'
|
||||||
import { usePlayState } from '../stores/usePlayState'
|
import { usePlayState } from '../stores/usePlayState'
|
||||||
import { debugPlayer } from '../utils/debug'
|
import { debugPlayer } from '../utils/debug'
|
||||||
import { watch, ref, onMounted, onUnmounted } from 'vue'
|
import { watch, ref, onMounted } from 'vue'
|
||||||
import artistsOrganize from '../utils/artistsOrganize'
|
import artistsOrganize from '../utils/artistsOrganize'
|
||||||
|
|
||||||
const playQueue = usePlayQueueStore()
|
const playQueue = usePlayQueueStore()
|
||||||
|
@ -82,11 +82,11 @@ class WebAudioPlayer {
|
||||||
if ('mediaSession' in navigator) {
|
if ('mediaSession' in navigator) {
|
||||||
navigator.mediaSession.setActionHandler('play', () => {
|
navigator.mediaSession.setActionHandler('play', () => {
|
||||||
console.log('Media session: play requested')
|
console.log('Media session: play requested')
|
||||||
this.play()
|
playState.togglePlay(true)
|
||||||
})
|
})
|
||||||
navigator.mediaSession.setActionHandler('pause', () => {
|
navigator.mediaSession.setActionHandler('pause', () => {
|
||||||
console.log('Media session: pause requested')
|
console.log('Media session: pause requested')
|
||||||
this.pause()
|
playState.togglePlay(false)
|
||||||
})
|
})
|
||||||
navigator.mediaSession.setActionHandler('stop', () => {
|
navigator.mediaSession.setActionHandler('stop', () => {
|
||||||
console.log('Media session: stop requested')
|
console.log('Media session: stop requested')
|
||||||
|
@ -148,6 +148,7 @@ class WebAudioPlayer {
|
||||||
if (!playState.actualPlaying) {
|
if (!playState.actualPlaying) {
|
||||||
// 如果实际正在播放,那么跳过音轨初始化阶段
|
// 如果实际正在播放,那么跳过音轨初始化阶段
|
||||||
debugPlayer("开始播放")
|
debugPlayer("开始播放")
|
||||||
|
navigator.mediaSession.playbackState = 'playing'
|
||||||
if (playState.playProgress !== 0) debugPlayer(`已经有所进度!${playState.playProgress}`)
|
if (playState.playProgress !== 0) debugPlayer(`已经有所进度!${playState.playProgress}`)
|
||||||
this.currentSource = this.context.createBufferSource()
|
this.currentSource = this.context.createBufferSource()
|
||||||
this.currentSource.buffer = this.audioBuffer[playQueue.currentTrack.song.cid]
|
this.currentSource.buffer = this.audioBuffer[playQueue.currentTrack.song.cid]
|
||||||
|
@ -201,6 +202,19 @@ class WebAudioPlayer {
|
||||||
const progress = this.context.currentTime - this.currentTrackStartTime
|
const progress = this.context.currentTime - this.currentTrackStartTime
|
||||||
playState.reportPlayProgress(progress)
|
playState.reportPlayProgress(progress)
|
||||||
playState.reportCurrentTrackDuration(this.audioBuffer[playQueue.currentTrack.song.cid].duration)
|
playState.reportCurrentTrackDuration(this.audioBuffer[playQueue.currentTrack.song.cid].duration)
|
||||||
|
|
||||||
|
// 向浏览器回报
|
||||||
|
if (('mediaSession' in navigator) && ('setPositionState' in navigator.mediaSession)) {
|
||||||
|
try {
|
||||||
|
navigator.mediaSession.setPositionState({
|
||||||
|
duration: this.audioBuffer[playQueue.currentTrack.song.cid].duration || 0,
|
||||||
|
playbackRate: 1.0,
|
||||||
|
position: progress,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
debugPlayer('媒体会话位置更新失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,6 +226,7 @@ class WebAudioPlayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pause() {
|
pause() {
|
||||||
|
navigator.mediaSession.playbackState = 'paused'
|
||||||
debugPlayer("尝试暂停播放")
|
debugPlayer("尝试暂停播放")
|
||||||
debugPlayer(this.currentSource)
|
debugPlayer(this.currentSource)
|
||||||
this.currentSource?.stop()
|
this.currentSource?.stop()
|
||||||
|
@ -263,6 +278,15 @@ onMounted(() => {
|
||||||
|
|
||||||
watch(() => playQueue.currentTrack, () => {
|
watch(() => playQueue.currentTrack, () => {
|
||||||
debugPlayer(`检测到当前播放曲目更新`)
|
debugPlayer(`检测到当前播放曲目更新`)
|
||||||
|
navigator.mediaSession.playbackState = playState.isPlaying ? 'playing' : 'paused'
|
||||||
|
navigator.mediaSession.metadata = new MediaMetadata({
|
||||||
|
title: playQueue.currentTrack.song.name,
|
||||||
|
artist: artistsOrganize(playQueue.currentTrack.song.artistes ?? []),
|
||||||
|
album: playQueue.currentTrack.album?.name,
|
||||||
|
artwork: [
|
||||||
|
{ src: playQueue.currentTrack.album?.coverUrl ?? "", sizes: '500x500', type: 'image/png' },
|
||||||
|
]
|
||||||
|
})
|
||||||
playerInstance.value?.loadResourceAndPlay()
|
playerInstance.value?.loadResourceAndPlay()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -68,119 +68,6 @@ export const usePlayState = defineStore('playState', () => {
|
||||||
actualPlaying.value = playing
|
actualPlaying.value = playing
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********
|
|
||||||
* 媒体会话管理
|
|
||||||
**********/
|
|
||||||
// 设置当前播放曲目
|
|
||||||
const setCurrentTrack = (track: QueueItem | null) => {
|
|
||||||
debugStore('设置当前曲目:', track?.song.name || 'null')
|
|
||||||
currentTrack.value = track
|
|
||||||
if (track) {
|
|
||||||
updateMediaSession(track)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化媒体会话处理器
|
|
||||||
const setupMediaSessionHandlers = () => {
|
|
||||||
if (!('mediaSession' in navigator) || mediaSessionInitialized.value) return
|
|
||||||
|
|
||||||
debugStore('设置媒体会话处理器')
|
|
||||||
|
|
||||||
navigator.mediaSession.setActionHandler('play', () => {
|
|
||||||
debugStore('媒体会话: 播放')
|
|
||||||
togglePlay(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
navigator.mediaSession.setActionHandler('pause', () => {
|
|
||||||
debugStore('媒体会话: 暂停')
|
|
||||||
togglePlay(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 上一首和下一首需要从外部传入回调
|
|
||||||
mediaSessionInitialized.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置上一首/下一首处理器
|
|
||||||
const setTrackNavigationHandlers = (
|
|
||||||
previousHandler: () => void,
|
|
||||||
nextHandler: () => void,
|
|
||||||
) => {
|
|
||||||
if (!('mediaSession' in navigator)) return
|
|
||||||
|
|
||||||
navigator.mediaSession.setActionHandler('previoustrack', () => {
|
|
||||||
debugStore('媒体会话: 上一首')
|
|
||||||
previousHandler()
|
|
||||||
})
|
|
||||||
|
|
||||||
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
|
||||||
debugStore('媒体会话: 下一首')
|
|
||||||
nextHandler()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新媒体会话信息
|
|
||||||
const updateMediaSession = (track: QueueItem) => {
|
|
||||||
if (!('mediaSession' in navigator)) return
|
|
||||||
|
|
||||||
debugStore('更新媒体会话:', track.song.name)
|
|
||||||
|
|
||||||
try {
|
|
||||||
navigator.mediaSession.metadata = new MediaMetadata({
|
|
||||||
title: track.song.name,
|
|
||||||
artist: artistsOrganize(track.song.artists ?? []),
|
|
||||||
album: track.album?.name,
|
|
||||||
artwork: [
|
|
||||||
{
|
|
||||||
src: track.album?.coverUrl ?? '',
|
|
||||||
sizes: '500x500',
|
|
||||||
type: 'image/png',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('更新媒体会话元数据失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新媒体会话播放状态
|
|
||||||
const updateMediaSessionPlaybackState = () => {
|
|
||||||
if (!('mediaSession' in navigator)) return
|
|
||||||
|
|
||||||
navigator.mediaSession.playbackState = isPlaying.value
|
|
||||||
? 'playing'
|
|
||||||
: 'paused'
|
|
||||||
debugStore('媒体会话状态更新:', navigator.mediaSession.playbackState)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新媒体会话位置信息
|
|
||||||
const updateMediaSessionPosition = () => {
|
|
||||||
if (
|
|
||||||
!('mediaSession' in navigator) ||
|
|
||||||
!('setPositionState' in navigator.mediaSession)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
try {
|
|
||||||
navigator.mediaSession.setPositionState({
|
|
||||||
duration: currentTrackDuration.value || 0,
|
|
||||||
playbackRate: 1.0,
|
|
||||||
position: playProgress.value,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
debugStore('媒体会话位置更新失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听播放状态变化,自动更新媒体会话
|
|
||||||
watch(isPlaying, () => {
|
|
||||||
updateMediaSessionPlaybackState()
|
|
||||||
})
|
|
||||||
|
|
||||||
// 监听播放进度变化,定期更新位置信息
|
|
||||||
watch(playProgress, () => {
|
|
||||||
updateMediaSessionPosition()
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// 状态读取
|
// 状态读取
|
||||||
isPlaying: playingState,
|
isPlaying: playingState,
|
||||||
|
@ -198,13 +85,5 @@ export const usePlayState = defineStore('playState', () => {
|
||||||
resetProgress,
|
resetProgress,
|
||||||
seekTo,
|
seekTo,
|
||||||
reportActualPlaying,
|
reportActualPlaying,
|
||||||
|
|
||||||
// 媒体会话方法
|
|
||||||
setCurrentTrack,
|
|
||||||
setupMediaSessionHandlers,
|
|
||||||
setTrackNavigationHandlers,
|
|
||||||
updateMediaSession,
|
|
||||||
updateMediaSessionPlaybackState,
|
|
||||||
updateMediaSessionPosition,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user