向浏览器回报歌曲元数据
This commit is contained in:
		
							parent
							
								
									d89dd55a51
								
							
						
					
					
						commit
						d63e18f0c7
					
				| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
import { usePlayQueueStore } from '../stores/usePlayQueueStore'
 | 
			
		||||
import { usePlayState } from '../stores/usePlayState'
 | 
			
		||||
import { debugPlayer } from '../utils/debug'
 | 
			
		||||
import { watch, ref, onMounted, onUnmounted } from 'vue'
 | 
			
		||||
import { watch, ref, onMounted } from 'vue'
 | 
			
		||||
import artistsOrganize from '../utils/artistsOrganize'
 | 
			
		||||
 | 
			
		||||
const playQueue = usePlayQueueStore()
 | 
			
		||||
| 
						 | 
				
			
			@ -82,11 +82,11 @@ class WebAudioPlayer {
 | 
			
		|||
		if ('mediaSession' in navigator) {
 | 
			
		||||
			navigator.mediaSession.setActionHandler('play', () => {
 | 
			
		||||
				console.log('Media session: play requested')
 | 
			
		||||
				this.play()
 | 
			
		||||
				playState.togglePlay(true)
 | 
			
		||||
			})
 | 
			
		||||
			navigator.mediaSession.setActionHandler('pause', () => {
 | 
			
		||||
				console.log('Media session: pause requested')
 | 
			
		||||
				this.pause()
 | 
			
		||||
				playState.togglePlay(false)
 | 
			
		||||
			})
 | 
			
		||||
			navigator.mediaSession.setActionHandler('stop', () => {
 | 
			
		||||
				console.log('Media session: stop requested')
 | 
			
		||||
| 
						 | 
				
			
			@ -148,6 +148,7 @@ class WebAudioPlayer {
 | 
			
		|||
		if (!playState.actualPlaying) {
 | 
			
		||||
			// 如果实际正在播放,那么跳过音轨初始化阶段
 | 
			
		||||
			debugPlayer("开始播放")
 | 
			
		||||
			navigator.mediaSession.playbackState = 'playing'
 | 
			
		||||
			if (playState.playProgress !== 0) debugPlayer(`已经有所进度!${playState.playProgress}`)
 | 
			
		||||
			this.currentSource = this.context.createBufferSource()
 | 
			
		||||
			this.currentSource.buffer = this.audioBuffer[playQueue.currentTrack.song.cid]
 | 
			
		||||
| 
						 | 
				
			
			@ -201,6 +202,19 @@ class WebAudioPlayer {
 | 
			
		|||
			const progress = this.context.currentTime - this.currentTrackStartTime
 | 
			
		||||
			playState.reportPlayProgress(progress)
 | 
			
		||||
			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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -212,6 +226,7 @@ class WebAudioPlayer {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	pause() {
 | 
			
		||||
		navigator.mediaSession.playbackState = 'paused'
 | 
			
		||||
		debugPlayer("尝试暂停播放")
 | 
			
		||||
		debugPlayer(this.currentSource)
 | 
			
		||||
		this.currentSource?.stop()
 | 
			
		||||
| 
						 | 
				
			
			@ -263,6 +278,15 @@ onMounted(() => {
 | 
			
		|||
 | 
			
		||||
watch(() => playQueue.currentTrack, () => {
 | 
			
		||||
	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()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,119 +68,6 @@ export const usePlayState = defineStore('playState', () => {
 | 
			
		|||
		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 {
 | 
			
		||||
		// 状态读取
 | 
			
		||||
		isPlaying: playingState,
 | 
			
		||||
| 
						 | 
				
			
			@ -198,13 +85,5 @@ export const usePlayState = defineStore('playState', () => {
 | 
			
		|||
		resetProgress,
 | 
			
		||||
		seekTo,
 | 
			
		||||
		reportActualPlaying,
 | 
			
		||||
 | 
			
		||||
		// 媒体会话方法
 | 
			
		||||
		setCurrentTrack,
 | 
			
		||||
		setupMediaSessionHandlers,
 | 
			
		||||
		setTrackNavigationHandlers,
 | 
			
		||||
		updateMediaSession,
 | 
			
		||||
		updateMediaSessionPlaybackState,
 | 
			
		||||
		updateMediaSessionPosition,
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user