暂时无法自动播放

This commit is contained in:
2025-08-17 22:07:37 +08:00
parent 196ee46a8d
commit 90e4a01e62
13 changed files with 410 additions and 21 deletions

View File

@@ -9,7 +9,7 @@ export default defineAppConfig({
defaultVolume: 50,
autoFullscreen: true,
showControls: false,
webSocketPort: 8080,
webSocketPort: 6666,
reconnectInterval: 5000
},
ui: {

View File

@@ -15,9 +15,12 @@
v-if="currentVideo"
ref="videoElement"
class="w-full h-full object-contain"
:src="currentVideo.path"
:src="videoSrc"
:volume="volume / 100"
:loop="isLooping"
playsinline
:muted="isMuted"
preload="auto"
autoplay
@loadedmetadata="onVideoLoaded"
@timeupdate="onTimeUpdate"
@@ -75,6 +78,7 @@
</template>
<script setup>
// remove direct import that breaks vite in dev; we will fallback to file:// URLs
const appConfig = useAppConfig()
const isDev = process.env.NODE_ENV === 'development'
@@ -93,10 +97,46 @@ const volume = ref(appConfig.player.defaultVolume)
const isLooping = ref(false)
const isFullscreen = ref(false)
const showControls = ref(false)
const isMuted = ref(true)
// Video element ref
const videoElement = ref(null)
// Video source URL - reactive ref that gets updated when currentVideo changes
const videoSrc = ref('')
// Convert file path to Tauri-compatible URL
async function updateVideoSrc() {
const raw = currentVideo.value?.path || ''
if (!raw) {
console.log('🎥 No video path available')
videoSrc.value = ''
return
}
const filePath = raw.startsWith('file://') ? raw.slice(7) : raw
console.log('🎥 Converting video path:', { raw, filePath })
// Use file:// protocol for local files in Tauri
const absolutePath = filePath.startsWith('/') ? filePath : `/${filePath}`
const fileUrl = `file://${absolutePath}`
videoSrc.value = fileUrl
console.log('🎥 Using file:// URL:')
console.log(' - Original path:', raw)
console.log(' - File path:', filePath)
console.log(' - File URL:', fileUrl)
}
// Watch for changes in currentVideo and update videoSrc
watch(currentVideo, updateVideoSrc, { immediate: true })
// Watch for changes in videoSrc to debug
watch(videoSrc, (newSrc, oldSrc) => {
console.log('🎥 videoSrc changed:')
console.log(' - Old:', oldSrc)
console.log(' - New:', newSrc)
})
// Computed properties
const connectionStatusClass = computed(() => {
switch (connectionStatus.value) {
@@ -167,9 +207,57 @@ function setVolume(newVolume) {
// Video event handlers
function onVideoLoaded() {
console.log('🎬 Video loaded event triggered')
if (videoElement.value) {
duration.value = videoElement.value.duration
videoElement.value.volume = volume.value / 100
console.log('🎬 Video metadata:', {
duration: duration.value,
volume: volume.value,
currentSrc: videoElement.value.currentSrc,
readyState: videoElement.value.readyState
})
// 尝试主动播放;若被策略阻止则静音后重试
console.log('🎬 Attempting to play video...')
// Always start muted to comply with autoplay policies, then unmute
isMuted.value = true
// Small delay to ensure video is ready
setTimeout(() => {
if (videoElement.value) {
const playPromise = videoElement.value.play()
if (playPromise && typeof playPromise.then === 'function') {
playPromise.then(() => {
console.log('✅ Video started playing successfully (muted)')
isPlaying.value = true
// Try to unmute after successful playback
setTimeout(() => {
if (videoElement.value) {
videoElement.value.muted = false
isMuted.value = false
console.log('🔊 Video unmuted')
}
}, 1000)
}).catch((err) => {
console.error('❌ Autoplay failed:', err)
// Show user a play button if autoplay fails
showControls.value = true
})
} else {
// Fallback for browsers without promise-based play
try {
videoElement.value.play()
console.log('✅ Video started playing (fallback)')
isPlaying.value = true
} catch (err) {
console.error('❌ Autoplay failed (fallback):', err)
showControls.value = true
}
}
}
}, 500)
}
}
@@ -186,14 +274,22 @@ function onVideoEnded() {
}
function onVideoError(event) {
console.error('Video playback error:', event)
console.error('Video playback error:', event)
console.error('❌ Video error details:', {
error: event.target?.error,
networkState: event.target?.networkState,
readyState: event.target?.readyState,
currentSrc: event.target?.currentSrc
})
currentVideo.value = null
isPlaying.value = false
}
// Initialize fullscreen if configured
onMounted(async () => {
console.log('🔧 Component mounted, initializing...')
if (appConfig.player.autoFullscreen) {
console.log('🔧 Auto fullscreen enabled')
// Request fullscreen
nextTick(() => {
document.documentElement.requestFullscreen?.() ||
@@ -202,10 +298,14 @@ onMounted(async () => {
}
// Setup Tauri event listeners
console.log('🔧 Setting up Tauri listeners...')
await setupTauriListeners()
// Get initial player state
console.log('🔧 Getting initial player state...')
await updatePlayerState()
console.log('✅ Component initialization complete')
})
// Setup Tauri event listeners
@@ -227,6 +327,7 @@ async function setupTauriListeners() {
// Listen for player commands from backend
await listen('player-command', async (event) => {
console.log('📡 Backend player command received:', event.payload)
const command = event.payload
await handlePlayerCommand(command)
})
@@ -267,6 +368,7 @@ async function updatePlayerState() {
// Handle player commands from WebSocket
async function handlePlayerCommand(command) {
console.log('🎮 Received player command:', command)
switch (command.type) {
case 'play':
if (videoElement.value) {
@@ -313,25 +415,27 @@ async function handlePlayerCommand(command) {
// Load video from file path
async function loadVideoFromPath(path) {
console.log('📥 loadVideoFromPath called with:', path)
try {
// Convert file path to URL for video element
const videoUrl = `file://${path}`
const rawPath = path.startsWith('file://') ? path.slice(7) : path
console.log('📥 Processing video path:', { originalPath: path, rawPath })
// Create video info
const title = path.split('/').pop() || path
const title = rawPath.split('/').pop() || rawPath
currentVideo.value = {
path: videoUrl,
path: rawPath,
title,
duration: null,
size: null,
format: null
}
console.log('📹 currentVideo.value set to:', currentVideo.value)
// The videoSrc will be updated automatically via the watcher
// Update backend state if invoke is available
if (invoke) {
await invoke('load_video', { path })
await invoke('load_video', { path: rawPath })
}
console.log('📹 Video loaded:', title)
console.log('📹 Video loaded successfully:', title)
} catch (error) {
console.error('❌ Failed to load video:', error)
}