Changelog¶
All notable changes to this project are documented here.
Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased¶
Fixed¶
Scan Command Permission Error Handling (#220, #221)¶
- Scan command continues after PermissionError - Previously stopped on first protected directory
- Scans all accessible directories even when some are protected
- Reports count of inaccessible items after scan completes
- OSError handling - Gracefully handles broken symlinks and I/O errors
- Counts and reports broken symlinks separately from permission errors
- Prevents scan from crashing on filesystem edge cases
- Comprehensive test coverage - 9 tests covering error handling scenarios
- Permission error continuation, count reporting, and mixed errors
- Broken symlink handling and OS error count reporting
- Path filtering, size filtering, and keyboard interrupt handling
Scan Command Display Improvements (#228)¶
- Symlink and firmlink deduplication - Prevents duplicate entries in scan output
- Same file accessed via different paths appears only once
- Handles macOS firmlinks (
/System/Volumes/Dataprefix normalization) - Accurate file count and storage totals (no double-counting)
- Full path display - Shows complete directory paths in scan output
- Removed 60-character path truncation
- Rich Table automatically wraps long paths for readability
Changed¶
CI/CD Configuration Improvements (#219)¶
- Unified release workflow - Consolidated
release.ymlandrelease-macos.ymlinto single workflow - Prevents race conditions from duplicate v* tag triggers
- Includes code signing and notarization from macOS workflow
- Adds Homebrew Cask update automation
- Pre-release test gate - Tests run before building release artifacts
- Linting, type checking, and unit tests must pass before build
- Prevents releasing buggy code to production
- Standardized macOS versions - All workflows now use
macos-14 - Consistent behavior across CI, E2E, build, and release workflows
- Improved reproducibility and debugging
- Type checking now enforced - mypy type errors fail the build (#226)
- Fixed all 45 mypy type errors across 17 files
- Added proper type annotations to functions missing return types
- Corrected variable type declarations to match actual usage patterns
- Replaced
callablewithCallablefrom typing module - Pinned tool versions - ruff (>=0.1.9,<0.2.0) and mypy (>=1.8.0,<2.0.0)
- Matches pre-commit hook versions for consistency
- Prevents version drift between local and CI environments
Added¶
CI/CD Enhancements (#219)¶
- GUI tests in CI - Headless GUI tests with
QT_QPA_PLATFORM=offscreen - Dedicated
gui-testjob in CI workflow - Tests run without requiring display server
- Homebrew package caching - Faster CI builds with cached dependencies
- Caches ffmpeg, exiftool, and create-dmg installations
- Reduces macOS job runtime significantly
- CodeQL security scanning - Static code analysis for vulnerabilities
- Weekly security scans plus on every PR
- Extended security and quality queries enabled
- Compatibility test workflow - macOS version matrix testing
- Tests on macos-13, macos-14, and macos-15
- Runs weekly and on demand with
[compat]commits - Verifies CLI commands and app bundle builds
0.3.0.0 - 2025-12-24¶
Changed¶
Extract Magic Numbers to Constants Module (#176)¶
- Centralized constants module (
utils/constants.py) with all magic numbers and default values - Size units:
BYTES_PER_KB,BYTES_PER_MB,BYTES_PER_GB - Timeouts:
ICLOUD_DOWNLOAD_TIMEOUT,VMAF_ANALYSIS_TIMEOUT - Quality settings:
DEFAULT_QUALITY,DEFAULT_CRF, VMAF thresholds - Encoding presets:
ENCODING_PRESETS,SUPPORTED_BIT_DEPTHS - File extensions:
VIDEO_EXTENSIONSas immutable frozenset - Processing:
MIN_FREE_DISK_SPACE, concurrent conversion limits - Helper functions for consistent formatting across codebase
bytes_to_human(): Convert bytes to human-readable formatformat_duration(): Format seconds as "X hr Y min" or "X min Y sec"- Eliminated code duplication across 8 modules
__main__.py,core/config.py,core/orchestrator.pyconverters/hardware.py,converters/software.pyextractors/icloud_handler.py,processors/vmaf_analyzer.py- Comprehensive test coverage with 34 tests in
test_constants.py
Fixed¶
osxphotos API Compatibility (#195)¶
- Fix TypeError with osxphotos when running
video-converter run --source photos - Replace unsupported
media_typeparameter withmovies/imagesparameters - Affects
get_library_info(),get_video_count(), andget_videos()methods - osxphotos has never supported
media_typeparameter; correct API uses:movies=True, images=Falsefor video queriesimages=True, movies=Falsefor photo queries
- Compatible with osxphotos 0.70.0+ (all supported versions)
CI Build Fixes (#181)¶
- Make osxphotos dependency macOS-only with platform marker
sys_platform == 'darwin' - Fixes CI build failure on ubuntu-latest runners for documentation builds
- osxphotos is only needed on macOS for Photos library integration
- Fix mkdocstrings cross-reference warnings in
command_runner.py - Convert docstring examples to fenced code blocks
- Prevents bracket notation from being interpreted as cross-references
Changed¶
Extended Config Schema for VMAF, HDR, and Processing Settings (#173)¶
- VmafConfig model added for VMAF quality analysis settings
enabled: Enable/disable VMAF measurementthreshold: Minimum acceptable VMAF score (default: 93.0 for visually lossless)sample_interval: Frame sampling interval (default: 30 for faster analysis)fail_action: Action when below threshold ("warn", "retry", "fail")- EncodingConfig extended with
bit_depth(8/10) andhdr(bool) fields - Supports HDR10 encoding with 10-bit depth
- ProcessingConfig extended with disk space and file management options
move_processed: Move processed originals topaths.processedmove_failed: Move failed files topaths.failedcheck_disk_space: Enable disk space monitoringmin_free_space_gb: Minimum free space threshold (default: 1.0 GB)- CLI VMAF options now use config defaults when not explicitly specified
- All OrchestratorConfig instantiations updated to read from Config
convert, batch,photos convert, and resume commands- GUI ConversionService integration
paths.processedandpaths.failednow connected to processing workflow
Version Unification (#172)¶
- Unified version source to use
pyproject.tomlas single source of truth viaimportlib.metadata __init__.pynow loads version from package metadataconfig.pyimports__version__instead of hardcoding versionbuild_app.shreads version dynamically via Python- Removed version field from
config/default.json(determined at runtime) - Version updated from scattered values (0.1.0, 0.2.0.0, 0.3.0, 1.0.0) to unified
0.2.1.0 - Added version consistency tests to ensure all version references remain synchronized
Photos Convert Orchestrator Integration (#171)¶
- Refactored Photos batch conversion to use
orchestrator.run()instead of directconverter.convert()calls - Enables concurrent processing via
--max-concurrentoption (1-8 workers) - Session persistence for recovery after interruption
- Disk space monitoring with automatic pause when disk is full
- VMAF quality measurement support for Photos conversions
- Automatic retry logic on encoder failures
- 3-phase workflow implementation:
- Phase 1: Export all videos from Photos library (sequential)
- Phase 2: Convert using orchestrator.run() (concurrent)
- Phase 3: Re-import successful conversions (with original handling)
- Added
--max-concurrentoption for Photos mode to control parallel conversion workers
CLI Convert Command Orchestrator Integration (#170)¶
- Refactored
convertcommand to useorchestrator.convert_single()instead of directconverter.convert()call - Enables full Orchestrator pipeline features for single file conversions
- VMAF analysis is now properly triggered when
--vmafflag is used - Output validation is performed when
--validateflag is used - Automatic retry logic on encoder failures through RetryManager
- Timestamp synchronization preserves original file dates
- iCloud file handling with automatic download before conversion
- Added
on_progress_infoparameter toOrchestrator.convert_single() - Allows detailed FFmpeg progress tracking (percentage, speed, ETA, current size)
- Maintains existing progress bar display functionality in CLI
Added¶
macOS App Packaging (#145)¶
- PyInstaller Configuration:
video_converter.specfor building standalone macOS .app bundle - All dependencies bundled including PySide6, osxphotos, and core modules
- High DPI support with Retina display optimization
- File associations for common video formats
- URL scheme handler for
videoconverter://links - Code Signing Support: Entitlements and build scripts for proper macOS distribution
entitlements.plistfor hardened runtime and Photos library accessInfo.plistwith privacy descriptions and app metadata- Support for Developer ID signing and notarization
- DMG Installer:
create_dmg.shscript for creating drag-to-install disk images - Styled DMG with Applications folder shortcut
- Optional integration with
create-dmgtool for enhanced appearance - SHA256 checksum generation for verification
- Homebrew Cask Formula:
video-converter.rbfor installation via Homebrew - Automatic dependency management (ffmpeg)
- Zap support for complete uninstallation
- Caveats with setup instructions
- Auto-Update Service:
UpdateServicefor checking GitHub releases - Async update checking with Qt threading
- Version comparison and release notes parsing
- Download URL extraction from release assets
check_for_updates_sync()for CLI usage
GUI Application¶
- Photos Library Browser (#143): Full Photos library integration for the GUI:
PhotosServicefor async Photos library access in separate thread- Album tree view with video counts loaded from Photos database
- Video grid with selectable thumbnails generated via ffmpeg
- H.264/iCloud/favorites filtering options
- Multi-select with total size calculation
- iCloud status display with warning for cloud-only videos
- Permission handling with link to System Settings
- Batch conversion integration (selected videos go to queue)
- Loading indicators for async operations
- Menubar App Integration (#142): macOS system tray application for background monitoring:
- Real-time conversion progress display in menubar menu
- Text-based progress bar visualization (▓░)
- Pause/resume/cancel controls accessible from menubar
- System notifications for task completion and errors
- Main window toggle with single/double click on tray icon
- Background execution support (app keeps running when window closed)
- Integration with
ConversionServicefor live status updates - Drag and Drop Support (#141): Comprehensive drag and drop functionality:
- Folder drag support to extract video files automatically
- Visual feedback showing file count during drag operations
- Blue border for valid files, red border for invalid files
- Multiple file drop support with batch queue integration
- Automatic batch addition to conversion queue with saved settings
- Settings Persistence (#140):
SettingsManagerservice for persistent settings: - JSON-based settings storage in
~/Library/Application Support/VideoConverter/ - Automatic load on app startup and save on shutdown
- Settings categories: encoding, paths, automation, notifications
- Integration with
MainWindowfor seamless settings management apply_to_conversion_settings()for applying saved settings to conversions- Main Window UI (#138): PySide6-based main window with tab navigation:
MainWindowwith 5 tabs: Home, Convert, Photos, Queue, SettingsHomeViewwith welcome section, drag & drop zone, and statistics barDropZonewidget with visual feedback for drag & drop video filesRecentConversionsListfor displaying conversion history- macOS-native theming with dark mode support
- Keyboard shortcuts for tab navigation (Cmd+1-5)
- Menu bar with File, Edit, View, Help menus
Testing¶
- GUI Integration Tests (#160): Comprehensive integration tests for complete user workflows in
tests/gui/test_gui_integration.py: - File drop to conversion flow (single/multiple files)
- Photos library to conversion flow
- Settings persistence across sessions
- Menubar and main window synchronization
- Queue management operations (pause/resume/cancel)
- Tab navigation state preservation
- Error handling propagation between components
- 23 test cases covering all main user workflows
- Tests run in < 1 second with no flaky tests
- CLI Test Coverage (#128): Comprehensive test suite for CLI commands in
tests/unit/cli/: test_convert_cmd.py- Convert command tests (VMAF, metadata, encoding modes)test_run_cmd.py- Batch conversion tests (folder/Photos modes, filters)test_status_cmd.py- Status command tests for all service statestest_config_cmd.py- Configuration command tests (view, set, setup wizard)test_service_cmd.py- Service management tests (install, uninstall, control)test_stats_cmd.py- Statistics command tests (view, export, periods)test_error_handling.py- Error handling and edge case teststest_helpers.py- Helper function tests (parse_time, format_duration, format_size)- CLI-specific fixtures in
conftest.py(mock converters, handlers, managers) - 141 test cases covering 17 CLI commands
- UpdateService Test Coverage (#159): Comprehensive test suite for
UpdateServiceintests/gui/test_update_service.py: ReleaseInfodataclass creation andfrom_github_response()parsing- Version comparison logic (
parse_version,is_newer_version) UpdateCheckWorkerthread signal emissionsUpdateServiceasync update checking and error handlingcheck_for_updates_sync()blocking method for CLI- Browser integration tests (open download page)
- Mock GitHub API responses (no network calls during tests)
- 36 test cases covering all UpdateService functionality
- PhotosView Test Coverage (#157): Comprehensive unit tests for
PhotosViewintests/gui/test_views.py: - View creation and initialization tests
- Album tree population and selection
- Video grid display and filtering (H.264, iCloud, favorites)
- Multi-selection with selection count and total size
- iCloud status display with warnings
- Permission error handling
- Loading indicator visibility
- Signal emission tests (
videos_selected) - 29 test cases achieving 96% code coverage
- VideoGrid and ResultDialog Test Coverage (#158): Unit tests for
VideoGridandConversionResultDialog: test_video_grid.py:VideoItemdataclass,VideoThumbnailwidget,VideoGridcontainer- Thumbnail click/double-click signals, selection state, iCloud/favorite badges
- Grid operations: add, clear, multi-select, selection tracking
test_result_dialog.py: Success/failure dialog states, statistics display- Format helpers (
_format_size,_format_duration), action buttons - 64 test cases covering widget functionality
- Accessibility Tests (#161): Comprehensive accessibility tests in
tests/gui/test_accessibility.py: - Keyboard navigation through all tabs (Tab key, Ctrl+1-5 shortcuts)
- Accessible names for widgets (buttons, sliders, combo boxes, checkboxes)
- Accessible descriptions for complex widgets (quality slider, error states)
- Focus indicators visibility on interactive elements
- Color contrast compliance (WCAG 2.1 relative luminance formula)
- Comprehensive accessibility audit (focus traps, form labels, status bar)
- 33 test cases covering accessibility requirements
Fixed¶
PySide6 6.10 Compatibility and Test Fixes (#169)¶
- E2E test compatibility: Removed
qtbot.addWidget()calls forConversionService(QObject, not QWidget) - PySide6 6.10 compatibility: Replaced
Q_ARG(object, ...)with signal-based approach inConversionServicefor thread-safe worker communication - VideoValidator API fix: Fixed
validate()call inOrchestratorto use keyword argumentstrictness=instead of positional argument
0.2.0.0 - 2025-12-23¶
Fixed¶
- Session State Deadlock (#116): Resolved deadlock in
SessionStateManagerby usingthreading.RLock()instead ofthreading.Lock(). The nested lock acquisition whencreate_session()calledsave()was causing test hangs.
Changed¶
- Version scheme changed from 1.x.x to 0.x.x.x (project is in active development)
- Coverage Configuration: Exclude
__main__.py(CLI entrypoint) andapplescript.py(macOS-specific) from coverage measurement. Focus coverage on testable business logic modules.
Added¶
Core Features¶
- VMAF Quality Measurement (#26):
VmafAnalyzerclass for perceptual video quality measurement with VMAF score calculation,VmafScoresdataclass (min, mean, max, percentiles),VmafQualityLevelenum (visually lossless >= 93), frame sampling,quick_analyze()for fast estimation, and async support. 46 comprehensive unit tests. - Concurrent Processing (#31):
ConcurrentProcessorfor parallel video processing with configurable max concurrent jobs,ResourceMonitorfor system resource tracking,AggregatedProgressfor combined progress, semaphore-based concurrency limiting, and thread-safe job management. 32 test cases. - Error Recovery (#32):
ErrorRecoveryManagerwithErrorCategoryandRecoveryActionenums, automatic error classification, disk space monitoring,FailureRecordtracking, manual retry API, and partial output cleanup. - Retry Logic (#27):
RetryManagerwith four-stage retry (same settings → switch encoder → adjust quality → final attempt), automatic encoder fallback (HW ↔ SW), CRF adjustment,RetryConfig,RetryAttempttracking, andRetryResult. 35 unit tests.
Photos Integration¶
- Photos Re-Import (#101):
PhotosImporterclass for importing converted videos back to Photos library via AppleScript,import_video(),verify_import(),get_video_info()methods, configurable timeout, and comprehensive exception hierarchy (PhotosImportError,PhotosNotRunningError,ImportTimeoutError,DuplicateVideoError,ImportFailedError). - Metadata Preservation (#103):
MetadataPreserverclass withVideoMetadataSnapshot,capture_metadata(),embed_metadata_in_file()via ExifTool,apply_photos_metadata()via AppleScript,verify_metadata()withMetadataTolerancepresets, andVerificationResult. - Original Handling (#102):
OriginalHandlingenum (DELETE, ARCHIVE, KEEP),handle_original()method, CLI options (--reimport,--delete-originals,--keep-originals,--archive-album,--confirm-delete), and AppleScript integration. - Permission Guidance (#96):
--check-permissionsflag, rich panel display for permission errors,display_photos_permission_error(),display_photos_permission_success(),display_photos_library_info(), and quick access to System Settings. - Progress Display (#97):
PhotosProgressDisplaywith library info panel, two-phase progress tracking (Export/Convert), metadata display, styled summary panel, and_NullPhotosProgressfor quiet mode.
Folder Support¶
- iCloud Drive Support (#88): Automatic iCloud stub file detection (
.filename.icloudformat) inFolderExtractor,_is_icloud_stub(),_get_original_path_from_stub(),in_cloudandstub_pathproperties,FolderConfigwith iCloud settings, and_ensure_file_available()in Orchestrator. 15 unit tests. - Folder Extractor:
FolderExtractorclass for direct video conversion from filesystem folders, recursive scanning with include/exclude patterns, video codec detection,FolderVideoInfoandFolderStatsdataclasses. 62 test cases.
Automation¶
- Service Management (#35): Public
load(),unload(),restart()methods inServiceManager, permission checking, CLI commands (service-start,service-stop,service-load,service-unload,service-restart,service-logs),--followand--stderroptions. - Status Query (#36):
calculate_next_run(),get_last_run_info(),get_detailed_status()methods,LastRunInfoandDetailedServiceStatusdataclasses, enhanced CLIstatuscommand with next run time and statistics. 26 tests.
UI/UX¶
- Rich Progress Display (#38):
ui/progress.pymodule withSingleFileProgressDisplay,BatchProgressDisplay,IndeterminateSpinner,ProgressDisplayManager, custom Rich columns (SizeProgressColumn,SpeedColumn,ETAColumn), and null object pattern for quiet mode. 35 unit tests. - Statistics Reporter:
StatisticsReporterclass withStatsPeriodenum, time-based filtering (today, week, month, all), enhancedstatsCLI command,stats-exportfor JSON/CSV,--detailedand--periodoptions. - macOS Notifications:
NotificationManagerclass with automatic batch completion notifications, success/partial/failure types, summary statistics,NotificationConfig, and Orchestrator integration.
Quality & Validation¶
- Metadata Verification (#22):
MetadataVerifierclass for comprehensive metadata comparison,ToleranceSettings(date: 1s, GPS: 0.000001°, duration: 0.1s),CheckResultandVerificationResultdataclasses, category-based verification, and tolerance profiles. 43 test cases. - Timestamp Sync (#21):
TimestampSynchronizerfor copying timestamps,FileTimestampsdataclass, birth time support on macOS via SetFile,TimestampVerificationResult,preserve_timestampsconfig option. 23 test cases. - Conversion History (#18):
ConversionHistoryclass for duplicate prevention,ConversionRecorddataclass,HistoryStatistics, UUID and file hash identification, JSON persistence, export functionality. 41 test cases.
Other¶
- iCloud Download (#16):
iCloudHandlerfor detecting and downloading iCloud videos,CloudStatusenum, stub file analysis, brctl download triggering,DownloadProgresstracking,icloud_timeoutandskip_cloud_onlyoptions. - Real-time Progress (#11):
ProgressInfodataclass with ETA calculation,ProgressParserfor FFmpeg output,ProgressMonitorwith throttling,create_simple_callbackhelper. - 10-bit HDR Encoding:
bit_depthoption for 8/10-bit,hdroption for HDR10 (BT.2020 PQ), libx265 10-bit support with yuv420p10le.
Test Infrastructure¶
- Integration Tests (#115):
test_vmaf_integration.py(29 tests),test_concurrent_integration.py(24 tests),test_error_recovery_integration.py(34 tests),test_icloud_folder_integration.py(31 tests),test_statistics_integration.py(47 tests),test_notification_integration.py(49 tests). - Test Coverage (#116): Verified 81.62% unit test coverage, exceeding 80% target. Added
mock_osxphotosfixture, updatedtest_config_version, refactoredtest_photos_extractor.py. - Photos CLI Tests (#98):
test_photos_handler.py,test_photos_permissions.py,test_photos_progress.py,test_photos_cli.py. - Photos Re-Import Tests (#104):
test_photos_metadata_preservation.py,test_photos_original_handling.py,test_photos_reimport.py.
0.1.0.0 - 2025-12-22¶
Added¶
Core Conversion¶
- H.264 to H.265 (HEVC) video conversion with hardware acceleration (VideoToolbox)
- Software encoder fallback with x265 for maximum compatibility
- Configurable quality settings (1-100 for hardware, CRF 0-51 for software)
- Real-time progress tracking with speed and ETA estimation
- Automatic codec detection using FFprobe
Photos Library Integration¶
- macOS Photos library access via osxphotos
- H.264 video filtering from Photos library
- Album-based video selection
- Video export from Photos library
Metadata Preservation¶
- GPS coordinate preservation across conversions
- ExifTool integration for comprehensive metadata handling
- File timestamp synchronization (creation date, modification date)
- Critical metadata verification after conversion
Quality Validation¶
- Video integrity validation using FFprobe
- Compression ratio validation
- Video property comparison (resolution, duration, audio)
- GPS coordinate verification
Orchestration¶
- Batch conversion workflow with priority ordering
- Session state management for resumable conversions
- Pause/resume functionality
- Failure isolation and error recovery
Automation¶
- macOS launchd integration for scheduled conversions
- Service install/uninstall commands
- Daily/weekly scheduling support
- Watch path monitoring
CLI Interface¶
- Complete command-line interface with Rich formatting
convertcommand for single file or directory conversionphotoscommand for Photos library conversionscancommand to preview conversion candidatesconfigcommand for configuration managementservicecommand for automation managementstatuscommand for service status
Configuration¶
- JSON-based configuration system
- Environment variable overrides
- Configurable paths, encoding settings, and automation options
Logging¶
- Structured logging with file and console output
- Log rotation support
- Configurable log levels
Documentation¶
- Comprehensive README with installation and usage instructions
- Software Requirements Specification (SRS)
- Software Design Specification (SDS)
- Product Requirements Document (PRD)
- Architecture documentation