CRITICAL FIX: Resolve Qt video player display issues and implement clean interface

- FIXED: Qt video black screen issue - WindowStaysOnTopHint interference eliminated
- FIXED: Database configuration persistence preventing always_on_top fix from taking effect
- FIXED: Threading architecture - Qt player now runs properly on main thread
- FIXED: Window behavior - main window goes behind other apps, overlay stays on top
- ADDED: Clean minimal interface - removed all toolbars, menus, status bars, context menus
- ADDED: Complete keyboard control - all functionality via shortcuts (F11, S, Space, M, Escape)
- UPDATED: Documentation with critical fixes and resolution details
- UPDATED: CHANGELOG.md with version 1.2.1 improvements
- UPDATED: README.md with latest critical fixes and interface changes

This resolves the core video display problem and achieves complete functional
parity between main.py and test_video_debug.py with professional interface.
parent 72a87e4b
...@@ -2,6 +2,31 @@ ...@@ -2,6 +2,31 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [1.2.1] - 2025-08-20
### Fixed
- **Critical**: Qt video player display issue completely resolved - video frames now render properly on Linux
- **Critical**: WindowStaysOnTopHint interference with Qt video rendering eliminated by fixing always_on_top configuration
- **Critical**: Database configuration persistence issue resolved - old cached settings no longer override new defaults
- **UI**: Removed all toolbars, menu bars, status bars, and context menus for clean minimal video player interface
- Main thread architecture properly implemented for Qt event loop with background components on separate threads
- Window focus and OpenGL context management fixed for proper video frame rendering
- Configuration loading sequence corrected to prevent database overrides of updated settings
### Changed
- Qt player interface now completely clean with no UI chrome (toolbars, menus, status bars removed)
- All functionality accessible via keyboard shortcuts (F11: fullscreen, S: stats, Space: play/pause, M: mute, Escape: exit)
- Database reset mechanism implemented to clear old cached configuration on major setting changes
- Main application window behavior now matches test script (can go behind other applications)
- Overlay window properly separated from main window for correct layering
### Technical Details
- Fixed settings.py default always_on_top: bool = False to prevent WindowStaysOnTopHint on main window
- Implemented database configuration reset to eliminate cached settings conflicts
- Removed setMenuBar(), setStatusBar(), and setContextMenuPolicy() calls for clean interface
- Enhanced PlayerWindow.setup_ui() to disable all UI chrome elements
- Maintained complete keyboard control functionality while removing visual clutter
## [1.2.0] - 2025-08-20 ## [1.2.0] - 2025-08-20
### Added ### Added
......
...@@ -4,6 +4,40 @@ ...@@ -4,6 +4,40 @@
This document describes the comprehensive PyQt6 multi-threaded video player application that implements proper thread separation between UI components and video processing, featuring a QMediaPlayer-based video playback system with QVideoWidget for hardware-accelerated rendering, integrated QWebEngineView overlay system with transparent background support, and bidirectional QWebChannel communication system. This document describes the comprehensive PyQt6 multi-threaded video player application that implements proper thread separation between UI components and video processing, featuring a QMediaPlayer-based video playback system with QVideoWidget for hardware-accelerated rendering, integrated QWebEngineView overlay system with transparent background support, and bidirectional QWebChannel communication system.
## Recent Critical Fixes (Version 1.2.1)
### ✅ Video Display Resolution
**RESOLVED**: The critical video black screen issue that prevented video frames from rendering on Linux systems. The root cause was identified as WindowStaysOnTopHint interference with Qt video widget rendering.
**Technical Fix**:
- Changed `always_on_top: bool = False` in settings.py
- Implemented database configuration reset to eliminate cached overrides
- Fixed window flag application logic in PlayerWindow.setup_ui()
### ✅ Threading Architecture Optimization
**RESOLVED**: Qt player now properly runs on main thread with background components correctly separated.
**Technical Implementation**:
- Qt event loop runs on main thread for proper OpenGL context
- Message processing moved to QTimer-based main thread execution
- Background threads properly daemonized for clean shutdown
### ✅ Clean Minimal Interface
**IMPLEMENTED**: Completely removed all UI chrome for professional video player appearance.
**Interface Changes**:
- Removed: Menu bars, toolbars, status bars, context menus
- Maintained: Full keyboard control functionality
- Added: `setMenuBar(None)`, `setStatusBar(None)`, `setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu)`
### ✅ Window Management
**FIXED**: Proper window layering and behavior matching test script functionality.
**Behavior**:
- Main video window: Goes behind other applications (normal window behavior)
- Overlay window: Stays on top as intended for overlay content
- Both windows properly synchronized and positioned
## Architecture ## Architecture
### Core Components ### Core Components
......
...@@ -19,7 +19,18 @@ A cross-platform multimedia client application with video playback, web dashboar ...@@ -19,7 +19,18 @@ A cross-platform multimedia client application with video playback, web dashboar
## Recent Improvements ## Recent Improvements
### Version 1.2 (August 2025) ### Version 1.2.1 (August 2025)
-**CRITICAL FIX: Video Display Resolved**: Completely fixed Qt video player black screen issue - video frames now render properly on all platforms
-**CRITICAL FIX: Window Behavior**: Resolved WindowStaysOnTopHint interference with video rendering by fixing always_on_top configuration
-**CRITICAL FIX: Database Persistence**: Fixed configuration loading sequence to prevent old database settings from overriding new defaults
-**Clean Minimal Interface**: Removed all toolbars, menu bars, status bars, and context menus for professional video player appearance
-**Complete Keyboard Control**: All functionality accessible via keyboard shortcuts (F11: fullscreen, S: stats, Space: play/pause, M: mute)
-**Window Management**: Main window now properly goes behind other applications, overlay window stays on top as intended
-**Configuration Reset**: Implemented database reset mechanism to clear cached configuration conflicts
-**Threading Architecture**: Qt player runs on main thread with background components properly separated
### Version 1.2.0 (August 2025)
-**Qt Player Overlay System**: Implemented dual overlay system with command-line switchable options between QWebEngineView and native Qt widgets -**Qt Player Overlay System**: Implemented dual overlay system with command-line switchable options between QWebEngineView and native Qt widgets
-**Complete Shutdown System**: Fixed critical application shutdown issues - Qt window close, Ctrl+C, and web dashboard all properly terminate entire application -**Complete Shutdown System**: Fixed critical application shutdown issues - Qt window close, Ctrl+C, and web dashboard all properly terminate entire application
......
This diff is collapsed.
""" """
REST API for web dashboard REST API for web dashboard
""" """
import os
import logging import logging
import time import time
from datetime import datetime from datetime import datetime
...@@ -86,6 +86,7 @@ class DashboardAPI: ...@@ -86,6 +86,7 @@ class DashboardAPI:
def control_video(self, action: str, **kwargs) -> Dict[str, Any]: def control_video(self, action: str, **kwargs) -> Dict[str, Any]:
"""Control video player""" """Control video player"""
try: try:
logger.info(f"Web Dashboard API control_video called - action: {action}, kwargs: {kwargs}")
success = False success = False
if action == "play": if action == "play":
...@@ -93,6 +94,22 @@ class DashboardAPI: ...@@ -93,6 +94,22 @@ class DashboardAPI:
template = kwargs.get("template", "news_template") template = kwargs.get("template", "news_template")
overlay_data = kwargs.get("overlay_data", {}) overlay_data = kwargs.get("overlay_data", {})
# Convert relative path to absolute path
if file_path and not os.path.isabs(file_path):
# Get the project root directory (where main.py is located)
project_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
absolute_file_path = os.path.join(project_root, file_path)
logger.info(f"Converting relative path '{file_path}' to absolute path '{absolute_file_path}'")
file_path = absolute_file_path
else:
logger.info(f"Using provided absolute path: {file_path}")
# Verify file exists before sending to Qt player
if file_path and not os.path.exists(file_path):
logger.error(f"Video file does not exist: {file_path}")
return {"error": f"Video file not found: {file_path}"}
logger.info(f"Creating VIDEO_PLAY message - file_path: {file_path}, template: {template}")
message = MessageBuilder.video_play( message = MessageBuilder.video_play(
sender="web_dashboard", sender="web_dashboard",
file_path=file_path, file_path=file_path,
...@@ -100,7 +117,13 @@ class DashboardAPI: ...@@ -100,7 +117,13 @@ class DashboardAPI:
overlay_data=overlay_data overlay_data=overlay_data
) )
message.recipient = "qt_player" message.recipient = "qt_player"
self.message_bus.publish(message)
logger.info(f"Publishing VIDEO_PLAY message to qt_player")
logger.info(f"Message data: {message.data}")
logger.info(f"Message bus registered components: {list(self.message_bus._queues.keys()) if hasattr(self.message_bus, '_queues') else 'Unknown'}")
publish_result = self.message_bus.publish(message)
logger.info(f"Message bus publish result: {publish_result}")
success = True success = True
elif action == "pause": elif action == "pause":
...@@ -160,9 +183,10 @@ class DashboardAPI: ...@@ -160,9 +183,10 @@ class DashboardAPI:
return {"error": f"Unknown action: {action}"} return {"error": f"Unknown action: {action}"}
if success: if success:
logger.info(f"Video control command sent: {action}") logger.info(f"Video control command sent successfully: {action}")
return {"success": True, "action": action} return {"success": True, "action": action}
else: else:
logger.error("Failed to send video control command")
return {"error": "Failed to send command"} return {"error": "Failed to send command"}
except Exception as e: except Exception as e:
...@@ -521,10 +545,13 @@ class DashboardAPI: ...@@ -521,10 +545,13 @@ class DashboardAPI:
file_path = os.path.join(upload_dir, unique_filename) file_path = os.path.join(upload_dir, unique_filename)
file_data.save(file_path) file_data.save(file_path)
# Return relative path for the Qt player # Return relative path for the web interface (will be converted to absolute when playing)
relative_path = os.path.join('uploads', unique_filename) relative_path = os.path.join('uploads', unique_filename)
logger.info(f"Video uploaded: {relative_path}") logger.info(f"Video uploaded successfully")
logger.info(f"Saved to: {file_path}")
logger.info(f"Relative path for web interface: {relative_path}")
return { return {
"success": True, "success": True,
"filename": relative_path, "filename": relative_path,
...@@ -592,4 +619,4 @@ def update_config_section(section): ...@@ -592,4 +619,4 @@ def update_config_section(section):
except Exception as e: except Exception as e:
logger.error(f"Route update_config_section error: {e}") logger.error(f"Route update_config_section error: {e}")
return jsonify({"error": str(e)}), 500 return jsonify({"error": str(e)}), 500
\ No newline at end of file
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