Fixed crashes

parent 89aa1260
......@@ -1998,6 +1998,22 @@ class WebPlayerWindow(QMainWindow):
def setup_web_player(self):
"""Setup web player with QWebEngineView"""
# Configure web engine settings to allow autoplay
from PyQt6.QtWebEngineCore import QWebEngineSettings
settings = self.web_player_view.settings()
settings.setAttribute(QWebEngineSettings.WebAttribute.PlaybackRequiresUserGesture, False)
settings.setAttribute(QWebEngineSettings.WebAttribute.AllowRunningInsecureContent, True)
settings.setAttribute(QWebEngineSettings.WebAttribute.AllowGeolocationOnInsecureOrigins, True)
settings.setAttribute(QWebEngineSettings.WebAttribute.LocalContentCanAccessRemoteUrls, True)
settings.setAttribute(QWebEngineSettings.WebAttribute.LocalContentCanAccessFileUrls, True)
logger.info("Configured web engine settings to allow autoplay and local content")
# Configure web engine profile for local file access
profile = self.web_player_view.page().profile()
profile.setHttpCacheType(QWebEngineProfile.HttpCacheType.NoCache)
profile.setPersistentCookiesPolicy(QWebEngineProfile.PersistentCookiesPolicy.NoPersistentCookies)
logger.info("Configured web engine profile for local file access")
# Get web player HTML path
web_player_html_path = self._get_web_player_html_path()
......
......@@ -266,7 +266,7 @@
<body>
<!-- Video container -->
<div class="video-container">
<video id="webVideoPlayer" controls autoplay playsinline>
<video id="webVideoPlayer" controls playsinline muted>
<source src="" type="video/mp4">
Your browser does not support the video tag.
</video>
......
......@@ -191,6 +191,26 @@ class WebPlayerAPI {
console.log('Video readyState:', this.videoElement.readyState);
console.log('Video networkState:', this.videoElement.networkState);
console.log('Video error:', this.videoElement.error);
// For debug mode, ensure video is visible and properly sized
if (window.location.href.includes('debug') || window.location.href.includes('debug-player')) {
console.log('DEBUG MODE: Ensuring video visibility');
this.videoElement.style.display = 'block';
this.videoElement.style.visibility = 'visible';
this.videoElement.style.opacity = '1';
this.videoElement.style.width = '100%';
this.videoElement.style.height = '100%';
this.videoElement.style.objectFit = 'contain';
// Force video element to be visible in debug mode
const videoContainer = document.querySelector('.video-container');
if (videoContainer) {
videoContainer.style.display = 'block';
videoContainer.style.visibility = 'visible';
videoContainer.style.opacity = '1';
videoContainer.style.zIndex = '100';
}
}
}
// Attempt playback with autoplay policy handling
......@@ -201,9 +221,21 @@ class WebPlayerAPI {
if (this.videoElement.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA) {
console.log('Video ready, attempting playback...');
// For debug mode, ensure video is visible before attempting playback
if (window.location.href.includes('debug') || window.location.href.includes('debug-player')) {
console.log('DEBUG MODE: Ensuring video is visible before playback');
this.videoElement.style.display = 'block';
this.videoElement.style.visibility = 'visible';
this.videoElement.style.opacity = '1';
}
// Try to play with autoplay policy handling
this.videoElement.play().then(() => {
console.log('Playback started successfully');
// Ensure video is visible after successful playback
this.videoElement.style.display = 'block';
this.videoElement.style.visibility = 'visible';
this.videoElement.style.opacity = '1';
}).catch(e => {
console.error('Playback failed (likely due to autoplay policy):', e);
......@@ -211,6 +243,14 @@ class WebPlayerAPI {
this.videoElement.controls = true;
this.videoElement.muted = true; // Muted videos can often autoplay
// For debug mode, ensure video is visible even if autoplay fails
if (window.location.href.includes('debug') || window.location.href.includes('debug-player')) {
console.log('DEBUG MODE: Forcing video visibility despite autoplay block');
this.videoElement.style.display = 'block';
this.videoElement.style.visibility = 'visible';
this.videoElement.style.opacity = '1';
}
// Try again with muted
this.videoElement.play().catch(e2 => {
console.error('Muted playback also failed:', e2);
......@@ -219,6 +259,13 @@ class WebPlayerAPI {
});
} else {
console.log('Video not ready yet, waiting for more data...');
// For debug mode, ensure video is visible even while waiting
if (window.location.href.includes('debug') || window.location.href.includes('debug-player')) {
console.log('DEBUG MODE: Ensuring video is visible while waiting for data');
this.videoElement.style.display = 'block';
this.videoElement.style.visibility = 'visible';
this.videoElement.style.opacity = '1';
}
}
}
......@@ -325,4 +372,54 @@ document.addEventListener('DOMContentLoaded', function() {
console.log('Web Player API initialized and exposed to window.webPlayer');
console.log('Global functions playVideo and updateOverlayData exposed for WebChannel');
});
\ No newline at end of file
// Initialize debug mode if detected
if (window.location.href.includes('debug') || window.location.href.includes('debug-player')) {
console.log('DEBUG MODE DETECTED: Applying debug-specific video fixes');
webPlayer._initDebugMode();
}
});
// Add debug mode initialization method to WebPlayerAPI prototype
WebPlayerAPI.prototype._initDebugMode = function() {
console.log('Initializing debug mode for web player');
// Ensure video element is visible in debug mode
if (this.videoElement) {
this.videoElement.style.display = 'block';
this.videoElement.style.visibility = 'visible';
this.videoElement.style.opacity = '1';
this.videoElement.style.width = '100%';
this.videoElement.style.height = '100%';
this.videoElement.style.objectFit = 'contain';
this.videoElement.muted = true; // Ensure muted for autoplay in debug mode
// Force video container to be visible
const videoContainer = document.querySelector('.video-container');
if (videoContainer) {
videoContainer.style.display = 'block';
videoContainer.style.visibility = 'visible';
videoContainer.style.opacity = '1';
videoContainer.style.zIndex = '100';
}
// Add debug overlay to indicate debug mode
const debugOverlay = document.createElement('div');
debugOverlay.style.position = 'absolute';
debugOverlay.style.top = '10px';
debugOverlay.style.right = '10px';
debugOverlay.style.backgroundColor = 'rgba(255, 0, 0, 0.7)';
debugOverlay.style.color = 'white';
debugOverlay.style.padding = '5px 10px';
debugOverlay.style.borderRadius = '5px';
debugOverlay.style.fontFamily = 'Arial, sans-serif';
debugOverlay.style.fontSize = '14px';
debugOverlay.style.zIndex = '1000';
debugOverlay.textContent = 'DEBUG MODE - Video Player';
document.body.appendChild(debugOverlay);
console.log('Debug mode initialization completed');
} else {
console.error('DEBUG MODE: Video element not available for debug initialization');
}
};
\ No newline at end of file
......@@ -1412,6 +1412,148 @@ def send_test_message():
return jsonify({"error": str(e)}), 500
# Video serving route for web player
@api_bp.route('/video/serve')
def serve_video_general():
"""Serve video files for web player access"""
try:
from flask import send_file
import os
from pathlib import Path
# Get video path from query parameter
video_path = request.args.get('path', '').strip()
if not video_path:
return jsonify({"error": "Video path parameter required"}), 400
# Security: Only allow access to specific directories
allowed_base_paths = [
str(Path.home() / "mbetterclient" / "videos"), # User videos
str(Path.home() / "mbetterclient" / "temp"), # Temp videos
"/tmp", # System temp
str(Path(__file__).parent.parent.parent / "assets"), # Built-in assets
]
# Check if the requested path is within allowed directories
video_path_obj = Path(video_path).resolve()
is_allowed = False
for allowed_path in allowed_base_paths:
allowed_path_obj = Path(allowed_path).resolve()
try:
video_path_obj.relative_to(allowed_path_obj)
is_allowed = True
break
except ValueError:
continue
if not is_allowed:
logger.warning(f"Access denied to video path: {video_path}")
return jsonify({"error": "Access denied"}), 403
# Check if file exists
if not video_path_obj.exists():
logger.warning(f"Video file not found: {video_path}")
return jsonify({"error": "Video file not found"}), 404
# Check if it's actually a file
if not video_path_obj.is_file():
logger.warning(f"Path is not a file: {video_path}")
return jsonify({"error": "Invalid file path"}), 400
# Get file extension to determine MIME type
file_ext = video_path_obj.suffix.lower()
mime_types = {
'.mp4': 'video/mp4',
'.avi': 'video/x-msvideo',
'.mov': 'video/quicktime',
'.mkv': 'video/x-matroska',
'.webm': 'video/webm',
'.m4v': 'video/x-m4v'
}
mime_type = mime_types.get(file_ext, 'video/mp4') # Default to mp4
logger.info(f"Serving video file: {video_path} (MIME: {mime_type})")
# Serve the file with appropriate headers for video streaming
return send_file(
str(video_path_obj),
mimetype=mime_type,
as_attachment=False,
conditional=True # Support range requests for video seeking
)
except Exception as e:
logger.error(f"Error serving video file: {e}")
return jsonify({"error": str(e)}), 500
# Video serving route for web player
@api_bp.route('/video/play/<path:filename>')
def serve_video_play(filename):
"""Serve video files for web player playback"""
try:
from pathlib import Path
from flask import send_file
logger.info(f"Serving video file: {filename}")
# Handle different video file locations
possible_paths = []
# 1. Check uploaded videos directory
from ..config.settings import get_user_data_dir
user_data_dir = get_user_data_dir()
uploaded_video_path = user_data_dir / "videos" / filename
possible_paths.append(uploaded_video_path)
# 2. Check assets directory
assets_video_path = Path(__file__).parent.parent.parent / "assets" / filename
possible_paths.append(assets_video_path)
# 3. Check temp directories for extracted match videos
import tempfile
temp_base = Path(tempfile.gettempdir())
for temp_dir in temp_base.glob("match_*"):
if temp_dir.is_dir():
temp_video_path = temp_dir / filename
possible_paths.append(temp_video_path)
# Find the first existing file
video_path = None
for path in possible_paths:
if path.exists():
video_path = path
break
if not video_path:
logger.error(f"Video file not found: {filename}")
return jsonify({"error": "Video file not found"}), 404
logger.info(f"Serving video from: {video_path}")
# Serve the video file with appropriate headers for streaming
response = send_file(
str(video_path),
mimetype='video/mp4',
as_attachment=False,
conditional=True
)
# Add CORS headers for web player
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Headers'] = 'Range'
response.headers['Accept-Ranges'] = 'bytes'
return response
except Exception as e:
logger.error(f"Error serving video {filename}: {e}")
return jsonify({"error": str(e)}), 500
# Video upload and delete routes
@api_bp.route('/video/upload', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
......@@ -1421,31 +1563,31 @@ def upload_video():
logger.info("Video upload route called")
logger.info(f"Request files: {list(request.files.keys())}")
logger.info(f"Request form: {dict(request.form)}")
if 'video' not in request.files:
logger.error("No video file in request.files")
return jsonify({"error": "No video file provided"}), 400
file = request.files['video']
logger.info(f"File received: {file.filename}, size: {file.content_length if hasattr(file, 'content_length') else 'unknown'}")
if file.filename == '':
logger.error("Empty filename")
return jsonify({"error": "No file selected"}), 400
template = request.form.get('template', 'news_template')
logger.info(f"Template: {template}")
# Check if API instance is available
if not hasattr(api_bp, 'api') or api_bp.api is None:
logger.error("API instance not available on blueprint")
return jsonify({"error": "API service unavailable"}), 500
logger.info("Calling api_bp.api.upload_video...")
result = api_bp.api.upload_video(file, template)
logger.info(f"Upload result: {result}")
return jsonify(result)
except Exception as e:
logger.error(f"API video upload error: {e}", exc_info=True)
return jsonify({"error": str(e)}), 500
......@@ -1458,18 +1600,174 @@ def delete_video():
try:
data = request.get_json() or {}
filename = data.get('filename')
if not filename:
return jsonify({"error": "Filename is required"}), 400
result = api_bp.api.delete_video(filename)
return jsonify(result)
except Exception as e:
logger.error(f"API video delete error: {e}")
return jsonify({"error": str(e)}), 500
@api_bp.route('/video/serve/<path:filename>')
def serve_video_by_filename(filename):
"""Serve video files via HTTP for web player"""
try:
from pathlib import Path
from flask import send_file
logger.info(f"Serving video file: {filename}")
# Get user data directory
from ..config.settings import get_user_data_dir
user_data_dir = Path(get_user_data_dir())
# Check multiple possible locations for the video file
possible_paths = [
user_data_dir / "videos" / filename, # Uploaded videos
user_data_dir / "zip_files" / filename, # ZIP files (not videos, but check anyway)
Path(__file__).parent.parent.parent / "assets" / filename, # Built-in assets
]
# Also check for match videos in temp directories
import tempfile
temp_base = Path(tempfile.gettempdir())
for temp_dir in temp_base.glob("match_*"):
if temp_dir.is_dir():
temp_video_path = temp_dir / filename
if temp_video_path.exists():
possible_paths.append(temp_video_path)
# Find the first existing file
video_path = None
for path in possible_paths:
if path.exists() and path.is_file():
video_path = path
break
if not video_path:
logger.warning(f"Video file not found: {filename}")
return jsonify({"error": "Video file not found"}), 404
logger.info(f"Serving video from: {video_path}")
# Determine MIME type based on file extension
mime_type = "video/mp4" # Default
if filename.lower().endswith('.avi'):
mime_type = "video/x-msvideo"
elif filename.lower().endswith('.mov'):
mime_type = "video/quicktime"
elif filename.lower().endswith('.mkv'):
mime_type = "video/x-matroska"
elif filename.lower().endswith('.webm'):
mime_type = "video/webm"
# Serve the file with appropriate headers for video streaming
response = send_file(
str(video_path),
mimetype=mime_type,
as_attachment=False,
conditional=True # Enable conditional requests for better performance
)
# Add cache control headers
response.headers['Cache-Control'] = 'public, max-age=3600' # Cache for 1 hour
response.headers['Accept-Ranges'] = 'bytes' # Enable range requests for seeking
return response
except Exception as e:
logger.error(f"Error serving video file {filename}: {e}")
return jsonify({"error": str(e)}), 500
@api_bp.route('/video/serve/<path:filename>')
def serve_video_by_filename_2(filename):
"""Serve video files for web player playback"""
try:
from flask import send_from_directory
import os
from pathlib import Path
logger.info(f"Serving video file: {filename}")
# Get project root directory
project_root = Path(__file__).parent.parent.parent
upload_dir = project_root / 'uploads'
# Security check: ensure the file is within the uploads directory
requested_path = (upload_dir / filename).resolve()
upload_dir_resolved = upload_dir.resolve()
if not str(requested_path).startswith(str(upload_dir_resolved)):
logger.warning(f"Security violation: attempted to access file outside uploads directory: {filename}")
return jsonify({"error": "Access denied"}), 403
# Check if file exists
if not requested_path.exists():
logger.warning(f"Video file not found: {requested_path}")
return jsonify({"error": "File not found"}), 404
# Check if it's actually a file
if not requested_path.is_file():
logger.warning(f"Requested path is not a file: {requested_path}")
return jsonify({"error": "Not a file"}), 400
# Get relative path from uploads directory
relative_path = requested_path.relative_to(upload_dir_resolved)
relative_dir = str(relative_path.parent) if relative_path.parent != Path('.') else ''
logger.info(f"Serving video: {relative_path} from directory: {upload_dir}")
# Serve the file with appropriate headers for video streaming
response = send_from_directory(
str(upload_dir),
str(relative_path),
mimetype='video/mp4', # Default to mp4, but Flask will detect based on file extension
as_attachment=False,
conditional=True # Support range requests for video seeking
)
# Add CORS headers for web player access
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Headers'] = 'Range'
response.headers['Accept-Ranges'] = 'bytes'
logger.info(f"Video served successfully: {filename}")
return response
except Exception as e:
logger.error(f"Error serving video file {filename}: {e}")
return jsonify({"error": str(e)}), 500
@api_bp.route('/video/<filename>')
def serve_video_by_filename_3(filename):
"""Serve video files via HTTP - no authentication required for video playback"""
try:
from ..config.settings import get_user_data_dir
from flask import send_from_directory
import os
# Get persistent storage directory
user_data_dir = get_user_data_dir()
videos_dir = user_data_dir / "videos"
# Check if file exists
if not (videos_dir / filename).exists():
return jsonify({"error": "Video file not found"}), 404
# Serve the file
return send_from_directory(str(videos_dir), filename, mimetype='video/mp4')
except Exception as e:
logger.error(f"API serve video error: {e}")
return jsonify({"error": str(e)}), 500
# Auth token endpoint for JWT creation
@auth_bp.route('/token', methods=['POST'])
def create_auth_token():
......@@ -5066,6 +5364,232 @@ def get_template_preview(template_name):
return f"Error loading template preview: {str(e)}", 500
@api_bp.route('/video/serve/<path:video_path>')
def serve_video_by_path(video_path):
"""Serve video files by path for web player"""
try:
from pathlib import Path
from flask import send_file
import mimetypes
# Security: Only allow serving video files
allowed_extensions = {'.mp4', '.avi', '.mov', '.mkv', '.webm', '.mp3', '.wav', '.flv'}
video_path_obj = Path(video_path)
if video_path_obj.suffix.lower() not in allowed_extensions:
return jsonify({"error": "Invalid file type"}), 400
# Security: Prevent directory traversal
if '..' in video_path or video_path.startswith('/'):
return jsonify({"error": "Invalid path"}), 400
# Check if file exists
if not video_path_obj.exists():
return jsonify({"error": "File not found"}), 404
# Check if it's actually a file
if not video_path_obj.is_file():
return jsonify({"error": "Not a file"}), 400
# Get MIME type
mime_type, _ = mimetypes.guess_type(str(video_path_obj))
if not mime_type:
mime_type = 'video/mp4' # Default fallback
logger.info(f"Serving video file: {video_path} (MIME: {mime_type})")
# Serve the file with appropriate headers for video streaming
return send_file(
str(video_path_obj),
mimetype=mime_type,
as_attachment=False,
conditional=True
)
except Exception as e:
logger.error(f"Error serving video file {video_path}: {e}")
return jsonify({"error": "Internal server error"}), 500
@api_bp.route('/video/<path:filepath>')
def serve_video_by_filepath(filepath):
"""Serve video files for web player playback"""
try:
from pathlib import Path
from flask import send_file
# Convert URL path to filesystem path
video_path = Path(filepath)
# Security check: only allow access to video files in specific directories
allowed_dirs = [
Path(__file__).parent.parent.parent / "assets", # Built-in assets
Path(__file__).parent.parent.parent / "mbetterclient" / "assets", # Alternative assets
]
# Get user data directory for additional video locations
try:
from ..config.settings import get_user_data_dir
user_data_dir = get_user_data_dir()
allowed_dirs.extend([
user_data_dir / "videos", # Uploaded videos
user_data_dir / "zip_files", # Match ZIP files (temporary extraction)
])
except Exception as e:
logger.warning(f"Could not get user data directory: {e}")
# Check if the requested file is in an allowed directory
file_allowed = False
for allowed_dir in allowed_dirs:
try:
# Resolve both paths to handle symlinks and relative paths
resolved_video_path = video_path.resolve()
resolved_allowed_dir = allowed_dir.resolve()
# Check if the video path is within the allowed directory
if resolved_video_path.is_relative_to(resolved_allowed_dir):
file_allowed = True
break
except Exception as e:
logger.debug(f"Path resolution error for {allowed_dir}: {e}")
continue
if not file_allowed:
logger.warning(f"Access denied to video file: {filepath}")
return jsonify({"error": "Access denied"}), 403
# Check if file exists
if not video_path.exists():
logger.warning(f"Video file not found: {filepath}")
return jsonify({"error": "File not found"}), 404
# Check if it's actually a file
if not video_path.is_file():
logger.warning(f"Path is not a file: {filepath}")
return jsonify({"error": "Not a file"}), 400
# Check file extension (basic security)
allowed_extensions = {'.mp4', '.avi', '.mov', '.mkv', '.webm', '.m4v', '.flv'}
if video_path.suffix.lower() not in allowed_extensions:
logger.warning(f"Invalid video file extension: {video_path.suffix}")
return jsonify({"error": "Invalid file type"}), 400
logger.info(f"Serving video file: {filepath}")
# Serve the file with appropriate headers for video streaming
return send_file(
str(video_path),
mimetype=f'video/{video_path.suffix[1:].lower()}',
as_attachment=False,
conditional=True # Support range requests for video seeking
)
except Exception as e:
logger.error(f"Error serving video file {filepath}: {e}")
return jsonify({"error": "Internal server error"}), 500
@api_bp.route('/video/<path:filename>')
def serve_video_by_filename_4(filename):
"""Serve video files for web player playback"""
try:
from pathlib import Path
import tempfile
import os
logger.info(f"Serving video file: {filename}")
# Define possible video locations in order of priority
video_paths = []
# 1. Check temp directories for match videos (highest priority)
temp_base = Path(tempfile.gettempdir())
for temp_dir in temp_base.glob("match_*"):
if temp_dir.is_dir():
video_file = temp_dir / filename
if video_file.exists():
logger.info(f"Found video in temp directory: {video_file}")
return send_file(str(video_file), mimetype='video/mp4')
# 2. Check assets directory for INTRO.mp4 and other built-in videos
assets_dir = Path(__file__).parent.parent.parent / "assets"
assets_video = assets_dir / filename
if assets_video.exists():
logger.info(f"Found video in assets directory: {assets_video}")
return send_file(str(assets_video), mimetype='video/mp4')
# 3. Check user data videos directory for uploaded videos
from ..config.settings import get_user_data_dir
user_data_dir = get_user_data_dir()
videos_dir = user_data_dir / "videos"
user_video = videos_dir / filename
if user_video.exists():
logger.info(f"Found video in user data directory: {user_video}")
return send_file(str(user_video), mimetype='video/mp4')
# 4. Check zip_files directory for any video files
zip_files_dir = user_data_dir / "zip_files"
zip_video = zip_files_dir / filename
if zip_video.exists():
logger.info(f"Found video in zip files directory: {zip_video}")
return send_file(str(zip_video), mimetype='video/mp4')
# Video not found
logger.warning(f"Video file not found: {filename}")
return jsonify({"error": "Video file not found"}), 404
except Exception as e:
logger.error(f"Error serving video file {filename}: {e}")
return jsonify({"error": str(e)}), 500
@api_bp.route('/video/serve/<path:filename>')
def serve_video_by_filename_5(filename):
"""Serve video files for web player playback"""
try:
from flask import send_file, Response
from pathlib import Path
import tempfile
import os
logger.info(f"Serving video file: {filename}")
# First, try to find the video in temp directories (for match videos)
temp_base = Path(tempfile.gettempdir())
temp_dir_pattern = f"match_*"
for temp_dir in temp_base.glob(temp_dir_pattern):
if temp_dir.is_dir():
video_path = temp_dir / filename
if video_path.exists():
logger.info(f"Found video in temp directory: {video_path}")
return send_file(str(video_path), mimetype='video/mp4')
# If not found in temp directories, try assets directory (for intro videos)
assets_dir = Path(__file__).parent.parent.parent / "assets"
assets_video = assets_dir / filename
if assets_video.exists():
logger.info(f"Found video in assets directory: {assets_video}")
return send_file(str(assets_video), mimetype='video/mp4')
# If not found in assets, try user data videos directory
from ..config.settings import get_user_data_dir
user_data_dir = get_user_data_dir()
videos_dir = user_data_dir / "videos"
user_video = videos_dir / filename
if user_video.exists():
logger.info(f"Found video in user videos directory: {user_video}")
return send_file(str(user_video), mimetype='video/mp4')
# Video not found
logger.warning(f"Video file not found: {filename}")
return jsonify({"error": "Video file not found"}), 404
except Exception as e:
logger.error(f"Error serving video file {filename}: {e}")
return jsonify({"error": str(e)}), 500
@api_bp.route('/upload-intro-video', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
......@@ -5125,3 +5649,51 @@ def upload_intro_video():
logger.error(f"API upload intro video error: {e}")
return jsonify({"error": str(e)}), 500
@api_bp.route('/video/<path:filename>')
def serve_video_by_filename_6(filename):
"""Serve video files via HTTP for web player"""
try:
from ..config.settings import get_user_data_dir
from flask import send_from_directory
import tempfile
from pathlib import Path
logger.info(f"Serving video file: {filename}")
# First, try to serve from persistent videos directory
user_data_dir = get_user_data_dir()
videos_dir = user_data_dir / "videos"
if videos_dir.exists():
video_path = videos_dir / filename
if video_path.exists():
logger.info(f"Serving video from persistent directory: {video_path}")
return send_from_directory(str(videos_dir), filename, mimetype='video/mp4')
# Second, try to serve from temp directories (for extracted match videos)
temp_base = Path(tempfile.gettempdir())
temp_dir_pattern = "match_*"
for temp_dir in temp_base.glob(temp_dir_pattern):
if temp_dir.is_dir():
video_path = temp_dir / filename
if video_path.exists():
logger.info(f"Serving video from temp directory: {video_path}")
return send_from_directory(str(temp_dir), filename, mimetype='video/mp4')
# Third, try to serve from assets directory (for INTRO.mp4)
assets_dir = Path(__file__).parent.parent.parent / "assets"
video_path = assets_dir / filename
if video_path.exists():
logger.info(f"Serving video from assets directory: {video_path}")
return send_from_directory(str(assets_dir), filename, mimetype='video/mp4')
# If not found in any location, return 404
logger.warning(f"Video file not found: {filename}")
return jsonify({"error": "Video file not found"}), 404
except Exception as e:
logger.error(f"Error serving video file {filename}: {e}")
return jsonify({"error": str(e)}), 500
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment