可以正常播放
This commit is contained in:
@@ -114,17 +114,20 @@ async function updateVideoSrc() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = raw.startsWith('file://') ? raw.slice(7) : raw
|
// Always use HTTP protocol for both Tauri and development
|
||||||
console.log('🎥 Converting video path:', { raw, filePath })
|
// This works reliably in both environments
|
||||||
|
const filename = raw.split('/').pop() || 'video.mp4'
|
||||||
|
|
||||||
// Use file:// protocol for local files in Tauri
|
// Use relative HTTP URL - this works in both Tauri and development
|
||||||
const absolutePath = filePath.startsWith('/') ? filePath : `/${filePath}`
|
if (filename === 'video.mp4') {
|
||||||
const fileUrl = `file://${absolutePath}`
|
videoSrc.value = '/video.mp4'
|
||||||
videoSrc.value = fileUrl
|
} else {
|
||||||
console.log('🎥 Using file:// URL:')
|
videoSrc.value = `/${filename}`
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🎥 Using HTTP URL for video:')
|
||||||
console.log(' - Original path:', raw)
|
console.log(' - Original path:', raw)
|
||||||
console.log(' - File path:', filePath)
|
console.log(' - HTTP URL:', videoSrc.value)
|
||||||
console.log(' - File URL:', fileUrl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch for changes in currentVideo and update videoSrc
|
// Watch for changes in currentVideo and update videoSrc
|
||||||
@@ -288,6 +291,8 @@ function onVideoError(event) {
|
|||||||
// Initialize fullscreen if configured
|
// Initialize fullscreen if configured
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
console.log('🔧 Component mounted, initializing...')
|
console.log('🔧 Component mounted, initializing...')
|
||||||
|
console.log('📁 Current directory:', window.location.href)
|
||||||
|
|
||||||
if (appConfig.player.autoFullscreen) {
|
if (appConfig.player.autoFullscreen) {
|
||||||
console.log('🔧 Auto fullscreen enabled')
|
console.log('🔧 Auto fullscreen enabled')
|
||||||
// Request fullscreen
|
// Request fullscreen
|
||||||
@@ -306,6 +311,18 @@ onMounted(async () => {
|
|||||||
await updatePlayerState()
|
await updatePlayerState()
|
||||||
|
|
||||||
console.log('✅ Component initialization complete')
|
console.log('✅ Component initialization complete')
|
||||||
|
|
||||||
|
// Additional debug: check if video.mp4 exists in public folder
|
||||||
|
try {
|
||||||
|
const response = await fetch('/video.mp4', { method: 'HEAD' })
|
||||||
|
if (response.ok) {
|
||||||
|
console.log('📹 Found video.mp4 in public folder via HTTP')
|
||||||
|
} else {
|
||||||
|
console.log('❌ video.mp4 not accessible via HTTP')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('🌐 Cannot check video.mp4 via HTTP (expected in Tauri)')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Setup Tauri event listeners
|
// Setup Tauri event listeners
|
||||||
@@ -373,8 +390,17 @@ async function handlePlayerCommand(command) {
|
|||||||
case 'play':
|
case 'play':
|
||||||
if (videoElement.value) {
|
if (videoElement.value) {
|
||||||
try {
|
try {
|
||||||
|
// Ensure video is ready before attempting to play
|
||||||
|
if (videoElement.value.readyState >= 2) {
|
||||||
await videoElement.value.play()
|
await videoElement.value.play()
|
||||||
isPlaying.value = true
|
isPlaying.value = true
|
||||||
|
} else {
|
||||||
|
// Wait for video to be ready
|
||||||
|
videoElement.value.addEventListener('canplay', () => {
|
||||||
|
videoElement.value.play().catch(console.error)
|
||||||
|
isPlaying.value = true
|
||||||
|
}, { once: true })
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Play error:', error)
|
console.error('Play error:', error)
|
||||||
}
|
}
|
||||||
|
@@ -38,11 +38,15 @@ pub fn run() {
|
|||||||
let player_state_for_load = player_state.clone();
|
let player_state_for_load = player_state.clone();
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
let mut candidates: Vec<std::path::PathBuf> = Vec::new();
|
let mut candidates: Vec<std::path::PathBuf> = Vec::new();
|
||||||
|
|
||||||
|
// Add current working directory
|
||||||
if let Ok(cwd) = std::env::current_dir() {
|
if let Ok(cwd) = std::env::current_dir() {
|
||||||
log::info!("🔍 Searching in current working directory: {}", cwd.display());
|
log::info!("🔍 Searching in current working directory: {}", cwd.display());
|
||||||
candidates.push(cwd.join("video.mp4"));
|
candidates.push(cwd.join("video.mp4"));
|
||||||
candidates.push(cwd.join("public").join("video.mp4"));
|
candidates.push(cwd.join("public").join("video.mp4"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add executable directory and its ancestors
|
||||||
if let Ok(exe_path) = std::env::current_exe() {
|
if let Ok(exe_path) = std::env::current_exe() {
|
||||||
log::info!("📁 Executable path: {}", exe_path.display());
|
log::info!("📁 Executable path: {}", exe_path.display());
|
||||||
let mut ancestor_opt = exe_path.parent();
|
let mut ancestor_opt = exe_path.parent();
|
||||||
@@ -63,9 +67,12 @@ pub fn run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for candidate in candidates {
|
for candidate in candidates {
|
||||||
if tokio::fs::metadata(&candidate).await.is_ok() {
|
match tokio::fs::metadata(&candidate).await {
|
||||||
|
Ok(metadata) => {
|
||||||
|
if metadata.is_file() {
|
||||||
let path_string = candidate.to_string_lossy().to_string();
|
let path_string = candidate.to_string_lossy().to_string();
|
||||||
log::info!("✅ Found video file: {}", path_string);
|
log::info!("✅ Found video file: {}", path_string);
|
||||||
|
|
||||||
// Update backend player state
|
// Update backend player state
|
||||||
{
|
{
|
||||||
let mut state = player_state_for_load.lock().await;
|
let mut state = player_state_for_load.lock().await;
|
||||||
@@ -78,44 +85,50 @@ pub fn run() {
|
|||||||
format: None,
|
format: None,
|
||||||
};
|
};
|
||||||
state.load_video(video_info);
|
state.load_video(video_info);
|
||||||
// 默认启用循环并开始播放
|
|
||||||
state.set_loop(true);
|
state.set_loop(true);
|
||||||
state.play();
|
state.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify frontend to load and play the video (use absolute path; frontend will add file:// if needed)
|
// Send commands to frontend with increasing delays for reliability
|
||||||
let _ = app_handle_load.emit("player-command", serde_json::json!({
|
|
||||||
"type": "loadVideo",
|
|
||||||
"path": path_string
|
|
||||||
}));
|
|
||||||
let _ = app_handle_load.emit("player-command", serde_json::json!({
|
|
||||||
"type": "setLoop",
|
|
||||||
"enabled": true
|
|
||||||
}));
|
|
||||||
let _ = app_handle_load.emit("player-command", serde_json::json!({
|
|
||||||
"type": "play"
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Re-emit after a short delay to ensure frontend listeners are ready in dev mode
|
|
||||||
let app_handle_clone = app_handle_load.clone();
|
let app_handle_clone = app_handle_load.clone();
|
||||||
let delayed_path = path_string.clone();
|
let path_for_load = path_string.clone();
|
||||||
|
|
||||||
|
// Immediate load
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(800)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||||
let _ = app_handle_clone.emit("player-command", serde_json::json!({
|
let _ = app_handle_clone.emit("player-command", serde_json::json!({
|
||||||
"type": "loadVideo",
|
"type": "loadVideo",
|
||||||
"path": delayed_path
|
"path": "video.mp4"
|
||||||
}));
|
}));
|
||||||
let _ = app_handle_clone.emit("player-command", serde_json::json!({
|
});
|
||||||
|
|
||||||
|
// Set loop after load
|
||||||
|
let app_handle_clone2 = app_handle_load.clone();
|
||||||
|
tauri::async_runtime::spawn(async move {
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(300)).await;
|
||||||
|
let _ = app_handle_clone2.emit("player-command", serde_json::json!({
|
||||||
"type": "setLoop",
|
"type": "setLoop",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
}));
|
}));
|
||||||
let _ = app_handle_clone.emit("player-command", serde_json::json!({
|
});
|
||||||
|
|
||||||
|
// Play after load and loop are set
|
||||||
|
let app_handle_clone3 = app_handle_load.clone();
|
||||||
|
tauri::async_runtime::spawn(async move {
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
|
||||||
|
let _ = app_handle_clone3.emit("player-command", serde_json::json!({
|
||||||
"type": "play"
|
"type": "play"
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
return; // Exit early since we found a video
|
return; // Exit early since we found a video
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::debug!("❌ File not found or inaccessible: {} - {}", candidate.display(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log::warn!("❌ No video.mp4 file found in any search location");
|
log::warn!("❌ No video.mp4 file found in any search location");
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user