fix: 解决 Safari 浏览器音频播放问题
- 创建浏览器检测工具,专门检测 Safari 和音频可视化支持 - 在 Safari 浏览器上禁用 AudioContext 连接,避免播放问题 - 保持其他浏览器的音频可视化功能正常工作 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5be5b4812f
commit
8ee2b928f9
|
@ -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,8 +263,19 @@ function updateCurrentTime() {
|
|||
}
|
||||
}
|
||||
|
||||
console.log('[Player] 初始化 audioVisualizer')
|
||||
const { barHeights, connectAudio, isAnalyzing, error } = audioVisualizer({
|
||||
// 检查浏览器是否支持音频可视化
|
||||
const isAudioVisualizationSupported = supportsWebAudioVisualization()
|
||||
console.log('[Player] 音频可视化支持状态:', isAudioVisualizationSupported)
|
||||
|
||||
// 只在支持的浏览器上初始化音频可视化
|
||||
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,
|
||||
|
@ -272,12 +283,20 @@ const { barHeights, connectAudio, isAnalyzing, error } = audioVisualizer({
|
|||
midBoost: 1.2,
|
||||
trebleBoost: 1.4,
|
||||
threshold: 0,
|
||||
})
|
||||
})
|
||||
|
||||
console.log('[Player] audioVisualizer 返回值:', {
|
||||
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,6 +312,7 @@ watch(
|
|||
await nextTick()
|
||||
|
||||
if (player.value) {
|
||||
if (isAudioVisualizationSupported) {
|
||||
console.log('[Player] 连接音频元素到可视化器')
|
||||
console.log('[Player] 音频元素状态:', {
|
||||
src: player.value.src?.substring(0, 50) + '...',
|
||||
|
@ -300,6 +320,9 @@ watch(
|
|||
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