0.0.7 #11
| 
						 | 
				
			
			@ -7,7 +7,7 @@ import { usePlayQueueStore } from '../stores/usePlayQueueStore'
 | 
			
		|||
 | 
			
		||||
import LoadingIndicator from '../assets/icons/loadingindicator.vue'
 | 
			
		||||
import PlayIcon from '../assets/icons/play.vue'
 | 
			
		||||
import { audioVisualizer, checkAndRefreshSongResource } from '../utils'
 | 
			
		||||
import { audioVisualizer, checkAndRefreshSongResource, supportsWebAudioVisualization } from '../utils'
 | 
			
		||||
 | 
			
		||||
const playQueueStore = usePlayQueueStore()
 | 
			
		||||
const favourites = useFavourites()
 | 
			
		||||
| 
						 | 
				
			
			@ -263,21 +263,40 @@ function updateCurrentTime() {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
console.log('[Player] 初始化 audioVisualizer')
 | 
			
		||||
const { barHeights, connectAudio, isAnalyzing, error } = audioVisualizer({
 | 
			
		||||
	sensitivity: 1.5,
 | 
			
		||||
	barCount: 6,
 | 
			
		||||
	maxDecibels: -10,
 | 
			
		||||
	bassBoost: 0.8,
 | 
			
		||||
	midBoost: 1.2,
 | 
			
		||||
	trebleBoost: 1.4,
 | 
			
		||||
	threshold: 0,
 | 
			
		||||
})
 | 
			
		||||
// 检查浏览器是否支持音频可视化
 | 
			
		||||
const isAudioVisualizationSupported = supportsWebAudioVisualization()
 | 
			
		||||
console.log('[Player] 音频可视化支持状态:', isAudioVisualizationSupported)
 | 
			
		||||
 | 
			
		||||
console.log('[Player] audioVisualizer 返回值:', {
 | 
			
		||||
	barHeights: barHeights.value,
 | 
			
		||||
	isAnalyzing: isAnalyzing.value,
 | 
			
		||||
})
 | 
			
		||||
// 只在支持的浏览器上初始化音频可视化
 | 
			
		||||
let barHeights = ref<number[]>([0, 0, 0, 0, 0, 0])
 | 
			
		||||
let connectAudio = (_audio: HTMLAudioElement) => {}
 | 
			
		||||
let isAnalyzing = ref(false)
 | 
			
		||||
let error = ref<string | null>(null)
 | 
			
		||||
 | 
			
		||||
if (isAudioVisualizationSupported) {
 | 
			
		||||
	console.log('[Player] 初始化 audioVisualizer')
 | 
			
		||||
	const visualizer = audioVisualizer({
 | 
			
		||||
		sensitivity: 1.5,
 | 
			
		||||
		barCount: 6,
 | 
			
		||||
		maxDecibels: -10,
 | 
			
		||||
		bassBoost: 0.8,
 | 
			
		||||
		midBoost: 1.2,
 | 
			
		||||
		trebleBoost: 1.4,
 | 
			
		||||
		threshold: 0,
 | 
			
		||||
	})
 | 
			
		||||
	
 | 
			
		||||
	barHeights = visualizer.barHeights
 | 
			
		||||
	connectAudio = visualizer.connectAudio
 | 
			
		||||
	isAnalyzing = visualizer.isAnalyzing
 | 
			
		||||
	error = visualizer.error
 | 
			
		||||
	
 | 
			
		||||
	console.log('[Player] audioVisualizer 返回值:', {
 | 
			
		||||
		barHeights: barHeights.value,
 | 
			
		||||
		isAnalyzing: isAnalyzing.value,
 | 
			
		||||
	})
 | 
			
		||||
} else {
 | 
			
		||||
	console.log('[Player] 音频可视化被禁用(Safari 或不支持的浏览器)')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 监听播放列表变化
 | 
			
		||||
watch(
 | 
			
		||||
| 
						 | 
				
			
			@ -293,13 +312,17 @@ watch(
 | 
			
		|||
		await nextTick()
 | 
			
		||||
 | 
			
		||||
		if (player.value) {
 | 
			
		||||
			console.log('[Player] 连接音频元素到可视化器')
 | 
			
		||||
			console.log('[Player] 音频元素状态:', {
 | 
			
		||||
				src: player.value.src?.substring(0, 50) + '...',
 | 
			
		||||
				readyState: player.value.readyState,
 | 
			
		||||
				paused: player.value.paused,
 | 
			
		||||
			})
 | 
			
		||||
			connectAudio(player.value)
 | 
			
		||||
			if (isAudioVisualizationSupported) {
 | 
			
		||||
				console.log('[Player] 连接音频元素到可视化器')
 | 
			
		||||
				console.log('[Player] 音频元素状态:', {
 | 
			
		||||
					src: player.value.src?.substring(0, 50) + '...',
 | 
			
		||||
					readyState: player.value.readyState,
 | 
			
		||||
					paused: player.value.paused,
 | 
			
		||||
				})
 | 
			
		||||
				connectAudio(player.value)
 | 
			
		||||
			} else {
 | 
			
		||||
				console.log('[Player] 跳过音频可视化连接(不支持的浏览器)')
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			console.log('[Player] ❌ 音频元素不存在')
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -322,7 +345,7 @@ watch(
 | 
			
		|||
watch(
 | 
			
		||||
	() => player.value,
 | 
			
		||||
	(audioElement) => {
 | 
			
		||||
		if (audioElement && playQueueStore.list.length > 0) {
 | 
			
		||||
		if (audioElement && playQueueStore.list.length > 0 && isAudioVisualizationSupported) {
 | 
			
		||||
			connectAudio(audioElement)
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										98
									
								
								src/utils/browserDetection.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/utils/browserDetection.ts
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,98 @@
 | 
			
		|||
/**
 | 
			
		||||
 * 浏览器检测工具
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 检测是否为 Safari 浏览器
 | 
			
		||||
 * @returns {boolean} 如果是 Safari 返回 true,否则返回 false
 | 
			
		||||
 */
 | 
			
		||||
export function isSafari(): boolean {
 | 
			
		||||
	const ua = navigator.userAgent.toLowerCase()
 | 
			
		||||
	
 | 
			
		||||
	// 检测 Safari 浏览器(包括 iOS 和 macOS)
 | 
			
		||||
	// Safari 的 User Agent 包含 'safari' 但不包含 'chrome' 或 'chromium'
 | 
			
		||||
	const isSafariBrowser = ua.includes('safari') && 
 | 
			
		||||
		!ua.includes('chrome') && 
 | 
			
		||||
		!ua.includes('chromium') &&
 | 
			
		||||
		!ua.includes('android')
 | 
			
		||||
	
 | 
			
		||||
	// 额外检查:使用 Safari 特有的 API
 | 
			
		||||
	const isSafariByFeature = 'safari' in window || 
 | 
			
		||||
		/^((?!chrome|android).)*safari/i.test(navigator.userAgent)
 | 
			
		||||
	
 | 
			
		||||
	return isSafariBrowser || isSafariByFeature
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 检测是否为移动版 Safari
 | 
			
		||||
 * @returns {boolean} 如果是移动版 Safari 返回 true,否则返回 false
 | 
			
		||||
 */
 | 
			
		||||
export function isMobileSafari(): boolean {
 | 
			
		||||
	return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 检测是否支持 Web Audio API 的完整功能
 | 
			
		||||
 * @returns {boolean} 如果支持返回 true,否则返回 false
 | 
			
		||||
 */
 | 
			
		||||
export function supportsWebAudioVisualization(): boolean {
 | 
			
		||||
	// Safari 在某些情况下对 AudioContext 的支持有限制
 | 
			
		||||
	// 特别是在处理跨域音频资源时
 | 
			
		||||
	if (isSafari()) {
 | 
			
		||||
		console.log('[BrowserDetection] Safari detected, audio visualization disabled')
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// 检查基本的 Web Audio API 支持
 | 
			
		||||
	const hasAudioContext = 'AudioContext' in window || 'webkitAudioContext' in window
 | 
			
		||||
	const hasAnalyserNode = hasAudioContext && (
 | 
			
		||||
		'AnalyserNode' in window || 
 | 
			
		||||
		(window.AudioContext && 'createAnalyser' in AudioContext.prototype)
 | 
			
		||||
	)
 | 
			
		||||
	
 | 
			
		||||
	return hasAudioContext && hasAnalyserNode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 获取浏览器信息
 | 
			
		||||
 * @returns {object} 包含浏览器类型和版本信息的对象
 | 
			
		||||
 */
 | 
			
		||||
export function getBrowserInfo() {
 | 
			
		||||
	const ua = navigator.userAgent
 | 
			
		||||
	let browserName = 'Unknown'
 | 
			
		||||
	let browserVersion = 'Unknown'
 | 
			
		||||
	
 | 
			
		||||
	if (isSafari()) {
 | 
			
		||||
		browserName = 'Safari'
 | 
			
		||||
		const versionMatch = ua.match(/Version\/(\d+\.\d+)/)
 | 
			
		||||
		if (versionMatch) {
 | 
			
		||||
			browserVersion = versionMatch[1]
 | 
			
		||||
		}
 | 
			
		||||
	} else if (ua.includes('Chrome')) {
 | 
			
		||||
		browserName = 'Chrome'
 | 
			
		||||
		const versionMatch = ua.match(/Chrome\/(\d+\.\d+)/)
 | 
			
		||||
		if (versionMatch) {
 | 
			
		||||
			browserVersion = versionMatch[1]
 | 
			
		||||
		}
 | 
			
		||||
	} else if (ua.includes('Firefox')) {
 | 
			
		||||
		browserName = 'Firefox'
 | 
			
		||||
		const versionMatch = ua.match(/Firefox\/(\d+\.\d+)/)
 | 
			
		||||
		if (versionMatch) {
 | 
			
		||||
			browserVersion = versionMatch[1]
 | 
			
		||||
		}
 | 
			
		||||
	} else if (ua.includes('Edge')) {
 | 
			
		||||
		browserName = 'Edge'
 | 
			
		||||
		const versionMatch = ua.match(/Edge\/(\d+\.\d+)/)
 | 
			
		||||
		if (versionMatch) {
 | 
			
		||||
			browserVersion = versionMatch[1]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return {
 | 
			
		||||
		name: browserName,
 | 
			
		||||
		version: browserVersion,
 | 
			
		||||
		isSafari: isSafari(),
 | 
			
		||||
		isMobileSafari: isMobileSafari(),
 | 
			
		||||
		supportsAudioVisualization: supportsWebAudioVisualization()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,5 +2,16 @@ import artistsOrganize from "./artistsOrganize"
 | 
			
		|||
import { audioVisualizer } from "./audioVisualizer"
 | 
			
		||||
import cicdInfo from "./cicdInfo"
 | 
			
		||||
import { checkAndRefreshSongResource, checkAndRefreshMultipleSongs } from "./songResourceChecker"
 | 
			
		||||
import { isSafari, isMobileSafari, supportsWebAudioVisualization, getBrowserInfo } from "./browserDetection"
 | 
			
		||||
 | 
			
		||||
export { artistsOrganize, audioVisualizer, cicdInfo, checkAndRefreshSongResource, checkAndRefreshMultipleSongs }
 | 
			
		||||
export { 
 | 
			
		||||
	artistsOrganize, 
 | 
			
		||||
	audioVisualizer, 
 | 
			
		||||
	cicdInfo, 
 | 
			
		||||
	checkAndRefreshSongResource, 
 | 
			
		||||
	checkAndRefreshMultipleSongs,
 | 
			
		||||
	isSafari,
 | 
			
		||||
	isMobileSafari,
 | 
			
		||||
	supportsWebAudioVisualization,
 | 
			
		||||
	getBrowserInfo
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user