I've been considering building a Python application for personal use and built a conceptual project outline to guide development. If you don't mind reviewing the outline, I'd be interested to get your perspective, starting with the conceptual approach I used?

As a bit of background, I have two PCs - one that I primarily work on and a second all in one PC for watching movies while I'm working. The catch with the second PC is that it's touchscreen only which is where the web interface comes in - it makes it easy to find and watch something if I want to multitask, without the pain of using an onscreen keyboard and Windows Explorer to navigate a large library across multiple directories. I already have a basic version of the application working, so this is a rebuild that puts the folder monitoring approach to library management and web interface more centralized to the workflow where they were bolted on as a test in the current version.


# **Media Manager**

## **User Interface**

The application will have two user interfaces: 
1. A PyQt interface for media ingestion, curation, and management
2. A web interface for content selection and playback 

### **PyQt Interface**

- A `QMenuBar` object would be present at the top of the PyQt application window with a "Settings" & "Exit" options.
- A toolbar widget should be directly below the Menu, with buttons dependent on which tab is selected
- The main window will have three tabbed sections - A "Library Management" view, a "Folder Management" view, and a "Metadata Management" view
- At the bottom of the application will be an "Activity" log as a scrollable field showing the result of operations (file syncing, database resync/clear, web server requests). Operations that fail should be highlighted to the user via red text to make them easily distinguishable. The Activity log should be for the current session only, with the user being able to review the application log file if previous session data is needed.

#### **Library Management**

- This view allows a user to manage what content is ingested
- The toolbar in this view would have "Add Directory", "Resync Database" & "Clear Database" buttons
- This main window in this view would have a single panel with a list of monitored directories with the following items:
	* Directory Path
	* Default Folder (As a dropdown selection)
	* Default Studio (as a text input field)
	* A "Remove Directory" button
	* A "Scan Now" button

#### **Folder Management**

- This view allows the user to assign media to folders as a method of organization as the preferred organization may not match the source directory structure
- The toolbar in this view would have an "Add Folder" button (to create a new root-level folder)
- This view would be split into two panels - a list of folders on the left, and a list of media in the selected folder on the right
- The left panel should show a list of folders in a tree format
	- The user can right click on a folder listed to get the following options:
		* Create Subfolder
		* Rename Folder
		* Delete Folder - this option would also delete any subfolders. If any subfolders or media are assigned when the user selects this option, a warning message should be displayed asking the user to confirm.
	- A default folder labeled "Unsorted" should be listed at the top of the folder. 
		- This folder should not be able to be renamed, deleted or have subfolders
		- All media added without a default folder set would be assigned to this folder
		- If a folder is deleted and it or any subfolders contain media, their folder association would change to the "Unsorted" folder
- The right panel should show a list of media present in the selected folder
	- This should be organized as a table widget with the following columns as a read-only view:
		* File path (including file name)
		* Title
		* Studio
		* Dimensions
		* Duration
	The user should be able to select one or more media items, then be able to right-click to open a context menu allowing them to move the selected items to a different folder

#### **Metadata Management**

- This view allows the user to edit metadata for a single media item or multiple media items
- The toolbar in this view will have a "Search" & "Clear Search" button
- Below the toolbar would be a search bar
- Below the search bar would be a row of checkboxes allowing the user to filter their search with the following options in any combination:
	* File name
	* Title
	* Studio
	* Actor
	* Tag
	* Limit search to currently selected folder (if the user has selected a folder from the left panel)
- Below the search filters will be a a list of checkboxes to aid in metadata updates that would filter items in the main window with the following options in any combination:
	* Missing Title
	* Missing Studio
	* Missing Actor(s)
	* Missing Tag(s)
- The left panel will have a list of folders in a tree view, allowing the user to select a folder to view the items in it. In this mode, the user would not be able to create or edit folders - only view the contents
- The main window will have a table of media items (either media in the selected folder or search results if a search was performed)
- The table should have the following columns as a read-only view:
	* File name
	* Title
	* Studio
	* Actor(s) - comma-separated list
	* Tag(s) - comma-separated list
- Edit Metadata Panel:
	* This would be to the right of the main window and allow the user to edit metadata for one or more items that have been selected, including the following:
		- Thumbnail (if a single item is selected)
		- If a single item is selected, an "Edit Thumbnail" button that opens a pop up menu allowing the user to select a video timestamp to use as a new thumbnail.
		- Title
		- Studio
		- Actor(s) - (as a series of "pill" style widgets - the user can press Enter after typing a tag to input another one)
		- Tag(s) - (as a series of "pill" style widgets - the user can press Enter after typing a tag to input another one)
	* To confirm changes, a "Save"/"Save All" button will be present at the bottom of the window
	* If the user closes the window with unsaved changes, the user should see a warning that unsaved changes will be discarded

#### **Settings**

- This menu allows the user to configure application settings, including:
	* Thumbnail height and width
	* Web server port
	* Folder background scan interval
	* Database location
	* Thumbnail location
	* Maximum log file size (in KB)
	* Maximum worker concurrency
- A "Save" button to confirm changes, which will update the values in a `settings.json` file in the application root folder
- A "Reset to Default" button to return settings to the default set value (stored in a `default_settings.json` file in the application root folder)

### **Web Interface**

This is the interface that would be used to select content to view in a format that's friendly for touch input devices. It would have five components:

1. A Search bar at the top - the search bar should perform a live search of the database after the user has entered at least three characters
	- Below the search bar would be a row of checkboxes allowing the user to limit their search with the following options:
	* File name
	* Title
	* Studio
	* Actor
	* Tag
	* Limit Search to Current Folder (checked by default if the user has selected a folder)
2. A folder navigation panel on the left, showing available folders in a tree view - if the user selects a folder, its content should be displayed in the main panel, including content from subfolders
3. A central selection panel - this would show the contents of a selected folder (or search if one has been performed)
	- The items should be presented as a gallery of thumbnails, with the following characteristics:
		* The title (or file name if no title is present) as a wrapped text label at the bottom
		* An Information icon at the top left, which opens a details window showing the file name, title, studio, actor(s) and tag(s) as well as media attributes including dimensions, duration, frame rate, codec, and bit rate
		* A plus icon at the top right to add the item to the queue
	- At the top of the selection panel should be an "Add All Items to Queue" button to allow the user to add all content in the selection panel based on the folder selected or search results
4. A queue panel on the right
	- This would allow the user to view the items that were added to the queue as well as manage saving/playback
	- At the top should be a "Save Queue as Playlist", "Play in Browser" & "Clear Queue" buttons
	- The list should show selected items by their title (with filename as a fallback if no title exists) and an "X" button on the right to remove an individual item
5. Media Player
	- If the user selects the "Play in Browser" option, a pop up window to stream the selected queue should be displayed with the following items:
		  * The video content
		  * A Play/Pause button
		  * A Skip Forward/Skip Backwards button to move to the next or previous item (if multiple videos were in the queue)
		  * A Maximize button to play the video in full screen mode
		  * A button to repeat a single queue item or repeat all items in the queue
		  *  A playback bar allowing the user to seek to a specific point in the media item
		

## **User Workflow**

### **PyQt Interface**

#### **Launch and Initial State**

- The application would validate that `ffmpeg` is available, and abort loading if not found.
- if `ffmpeg` is found, the application would launch to the Library Management view

#### **Library Management**

- **Add Directory**
	- This button allows the user to add a directory to the library.
	- Clicking the "Add Directory" button would open a popup dialog with the following options:
		* A folder selection dialog allowing the user to select the directory to include
		* A dropdown field to select the folder content from this directory should be assigned to by default
		* A text input field to set the default Studio associated with media in this directory
		* An "Add to List" button to confirm and add the directory and folder/Studio entries selected to the library
		* A "Cancel" button to close the dialog
- **Monitored Directories List**
	- The user would manage added directories here
	- The user should be able to change the default folder assigned to new files found via the "Default Folder" dropdown list - if the user does not specify a folder, this should default to the "Unsorted" folder
	- The user should be able to clear or change the default Studio assigned to new files found via the "Default Studio" text input field
	- If the user wants to remove a directory and all media it contains from the library they can press the "Remove Directory" button.
		* This should present a warning dialog to the user that removing the folder will also remove all media it contains from the library, with an option to confirm or cancel the request
	- If the user wants to manually trigger a scan of the folder, they can press the "Scan Now" button
		* This would act like a targeted version of the "Resync Database" process that only processes the selected folder
		* While this process is running, the "Scan Now" button should be disabled for all directories listed until the process finishes for the selected directory
		* Any background scans should be cancelled until the next scheduled run
- **Resync Database**
	- This performs an iterative scan of all added directories, performing the following actions for each directory:
		1. Validates that the directory is accessible using a process like `os.walk()` - if not accessible, the process will abort with an error logged to the "Activity" panel as well as the application log file
		2. Checks the folder for any potentially valid media files (`.mp4` & `.m4v` extensions)
			- If no valid files are found, will skip the directory and log the result to the "Activity" panel and application log file so the user can investigate and manually remove if needed.
		3. For potentially valid media files, the application will first check to see if they're present in the library
		4. If a media file already exists, the application will validate that the file size and last modified date match the values stored in the library database, and that a thumbnail file is present with the currently set dimensions in the currently-set dimensions from the `config.json` file.
			- If the file size & last modified date match the values stored in the library database, and if a thumbnail is present and matches the currently set dimensions in the currently-set dimensions from the `config.json` file, the media file should be considered validated.
			- If the file size and last modified date do not match, the application should use `ffprobe`  to retrieve the current attributes (height, width, duration, video codec, bit rate in Kbps, frames per second) and update the database with the new values.
				* If the `ffprobe` process fails, the application should skip the file and log the error to the "Activity" panel and application log file
			- If a thumbnail does not exist, the application should generate a new thumbnail using the currently-set dimensions from the `config.json` file using the timestamp stored in the database
				* The default thumbnail timestamp would be 15 seconds into the video (or the first frame if the duration is shorter than 15 seconds)
			- To accommodate the user changing the thumbnail dimensions, if a thumbnail is present for a media file and the dimensions are different than the ones stored in the `config.json` file, the application should delete the previous thumbnail and generate a new one at the currently-set dimensions from the `config.json` file
			- If a file is found, but not present in the library, the application should use `ffprobe`  to retrieve the current attributes (height, width, duration, video codec, bit rate in Kbps, frames per second) and update the database with the new values. If the media file has a `title` metadata attribute, it should be retrieved and used as the default value for the Title metadata for that file. A thumbnail should be generated using the currently-configured values from the `config.json` file 15 seconds into the video (or the first frame if the video duration is less than 15 seconds)
			- If a file is present in the library but not found when scanning the directory, it should be removed and the associated thumbnail deleted
- **Clear Database**
	- This menu item would remove all items from the database and clear all thumbnails in the cache. 
	- When the user selects this item, they should receive an initial popup warning that has the text "Warning! This operation will clear all items from the database during which the application will not be usable. Please do not close the application while this process is running. This option is not reversible. Are you sure you want to proceed?" with "Proceed" and "Cancel" options. 
		* If the user selects "Cancel" the popup window should close with no changes made. 
		* If the user selects "Proceed" a modal dialog should appear advising the user the database is being cleared, with a "Continue" button visible to close the dialog once the process has cleared.
- **Background Scanning**
	- This process periodically scans directories that have been added to the library
	- The functionality would be identical to the **Resync Database** process, except a background scan will only add or update existing items, and would skip any library media files that are not found when scanning
	- The timing for the background scan will be configured in the **Settings** menu and stored in the `config.json` file.

#### **Folder Management**

- **Adding Folders**
	- To add a new root-level folder, the user would press the "Add Folder" button in the toolbar
	- To add a subfolder, the user would right-click a folder in the left panel and press the "Create Subfolder" button
		* This would open a pop-up dialog prompting the user to enter a name for the subfolder with "Save" & "Cancel" buttons
- **Renaming/Deleting Folders**
	- To rename a folder, the user would right-click a folder in the left panel and press the "Rename Folder" button
		* This would open a pop-up dialog prompting the user to enter a new name for the subfolder with "Save" & "Cancel" buttons
	- To delete a folder, the user would right-click a folder in the left panel and press the "Delete Folder" button.
		* If there are no media files or subfolders associated with the folder being deleted, the deletion would be done silently
		* If there are media files in the folder or any subfolders associated, the user should receive a warning message that all subfolders will be deleted and any files in the folder or subfolder will be moved to the "Unsorted" folder, with an option to confirm or cancel the action
- **"Unsorted" Folder**
	- This is the default folder that all media would be assigned to if another folder has not been specified
	- The user should not be able to delete, rename, or add subfolders to the "Unsorted" folder as it's intended to be a temporary location only
- **Folder Contents & Reassigning Folders**
	- The right panel of the "Folder Management" view will show a list of any media files associated with the selected folder
		* The user should be able to select one or more media files, then right-click to open a context menu allowing the user to select a new folder of subfolder to reassign the media to the selected folder.

#### **Metadata Management:**

- **Folder Panel**
	- The left panel will have a read only list of folders that the user can select. Selecting a folder would display the associated media items in the main panel, with items in subfolders being excluded to allow for more granularity when editing metadata
- **Searching**
	- The user can enter a search term in the search bar to look for specific items
	- There are two sets of filters the user can use to further narrow search results:
		* Search Filters: The user can limit the search to any combination of file name, title, studio, actor or tag metadata. The user can also limit the search to the currently selected folder. If no folder was selected, this option would have no effect
		* Metadata Filters: The user can also limit the search to show items missing metadata. The user can limit the search to filter to items missing a title, studio, actor(s) or tag(s) - if multiple options are chosen the filtering should be treated as an OR operation, showing any items that match the search criteria and any combination of missing metadata
- **Main Panel**
	- This panel would show the contents of either the selected folder or search results as a table with the following columns:
		* File Name
		* Title
		* Studio
		* Actors
		* Tags
**Edit Metadata Panel**
	- This panel would be to the right of the Main Panel and allow the user to edit metadata for one or more files
	- To begin the process, the user would select one or more files in the main panel
	- If one item is selected, the user should see the thumbnail for the media item at the top of the Edit Metadata Panel, with an "Edit Thumbnail" button
		* Pressing the "Edit Thumbnail" button would open a dialog allowing the user to input a new timestamp to use for the media item with a "Confirm" and "Cancel" button. The timestamp selected should be validated against the video duration to prevent the user from inputting an invalid timestamp.
		* Once the user confirms the change, a new thumbnail should be requested and the library database updated with the new thumbnail timestamp
		* The thumbnail should be blank and the "Edit Thumbnail" button disabled if multiple items are selected in the Main Panel
	- If one item is selected, the user should be able to edit or input a new title for the media item
		* This input should be disabled if multiple items are selected
	- If any number of items are selected, the user should be able to input a new Studio for the selected items
	- If any number of items are selected, the user should be able to input new Actors for the selected items
		* This input would use "pill"-style widgets
		* To input multiple actors quickly, the user should be able to input an actor, press Enter, then input another - adding as many as needed
	- If any number of items are selected, the user should be able to input new Tags for the selected items
		* This input would use "pill"-style widgets
		* To input multiple tags quickly, the user should be able to input an actor, press Enter, then input another - adding as many as needed
	- To save changes, the user would press the "Save"/"Save All" button at the bottom of the panel
		* The button should be context sensitive, with "Save" being the label if only one item is selected, and "Save All" if multiple items are selected
		* This button should be disabled unless an item of metadata has been updated (with the exception of thumbnails as they are handled separately.)
		* When saving, Actor/Studio/Tag names should be trimmed and normalized with proper title casing

#### **Settings**

- This would be selectable from the application menu
- Settings would be a pop-out window showing currently configurable items, with text inputs to allow the user to save settings.
- Settings should include the following items:
	* Thumbnail height and width
	* Web server port
	* Folder background scan interval
	* Database location
	* Thumbnail location
	* Maximum log file size (in KB)
	* Maximum worker concurrency
- When the user is satisfied with their changes, they can press the "Save" button at the bottom of the window, which would save the new settings to the `config.json` file
- If the user wants to reset settings to the original defaults, they can press the "Reset to Default" button
	* This would present a warning message to the user advising them that resetting to defaults will clear any user-defined settings and restore the application to original defaults, with an option to confirm or cancel

### **Web Interface**

The web interface should use Flask/Waitress to host a lightweight web server allowing the user to find media and play it via a web browser via a touch-friendly interface

#### **Web Search**

- The search bar should be at the top of the web page presented to the user
	- The search bar should perform a live search of the database after the user has entered at least three characters
	- Below the search bar, the user should see a row of checkboxes allowing them to filter the search, including
		* File name
		* Title
		* Studio
		* Actor
		* Tag
		* Limit Search to Current Folder
	- The "Limit Search to Current Folder" item will be enabled by default if the user selects a folder, although they should be able to manually deselect it as needed
	- Search results would display in the Central Selection Panel, overwriting any items from a currently selected folder unless the user clears the search

#### **Folder Selection**

- The Folder Selection panel should be on the left side of the web page presented to the user
	- It should contain a scrollable tree view of folders that the user can select
	- If the user selects a folder, the media items associated with it should be displayed in the central selection panel
		* If a user selects a parent folder, the contents of any subfolders should be included along with any items in the parent folder itself

#### **Central Selection Panel**

- This is where search results or items in a selected folder will appear
- It should present a grid of thumbnails to the user
	* Each thumbnail should have the title for the media item as wrappable text, with the file name being treated as the title if a title is not present
	* At the top right should be a `+` icon, allowing the user to add a single item to the queue
	* At the top left should be an `i` icon, allowing the user to see media attributes (file name, dimensions, codec, frames per second, duration, bit rate) as well as user-assigned metadata (title, studio, actors, tags)
- The items in the Central Selection Panel should be sorted alphabetically by file name
- At the top of the Central Selection Panel should be an "Add All Items to Queue" button, allowing for an easy method for the user to add all folder contents or search results to the Queue

#### **Queue Panel**

- The Queue Panel should be to the right of the Central Selection Panel, and would allow the user to add one or more media items to a queue
- At the top of the Queue Panel should be "Save Queue as Playlist", "Play In Browser" & "Clear Queue" buttons
- Save Queue as Playlist - This would create a `.xspf` playlist with all items in the queue, including title information, and offer it as a download to the user if they wish to use another media player to watch the items in the queue
- Play in Browser - This would allow the user to stream the playlist items via the server to a popup window, allowing the user to view one or more items seamlessly. This process should be robust and not disrupt playback if the user clears the queue while playing content in the browser
- Clear Queue - this would remove all items in the queue

#### **Media Player**

- If the user selects the "Play in Browser" option, a pop up window to stream the selected queue should be displayed with the following items:
	* The video content
	* A Play/Pause button
	* A Skip Forward/Skip Backwards button to move to the next or previous item (if multiple videos were in the queue)
	* A Maximize button to play the video in full screen mode
	* A button to repeat a single queue item or repeat all items in the queue
	* A playback bar allowing the user to seek to a specific point in the media item
- Transcoding support is currently out of scope - the server would just stream the file in chunks for the client browser to render. If a file format does not play back, the user is responsible for troubleshooting browser issues

## **Data Storage**

- Video Metadata: Preference is to use SQLite & SQLAlchemy (with SQLite FTS5 enabled for searching) to manage database entries for video items. Ideally the database structure should be similar to the outline below, use association tables to map linking between the different base tables, and index key columns for faster searches:
- Video Table:
	* id (UUID, Primary Key)
	* filepath (The full, absolute path to the video file)
	* filename
	* title (User-editable)
	* date_added (timestamp)
	* date_modified (timestamp)
	* file_size
	* last_modified_date
	* thumbnail_path (The path to the thumbnail for the item - if blank a default gray placeholder would be used)
	* thumbnail_dimensions
	* thumbnail_timestamp (the number of seconds into a video to use when generating a thumbnail if manually changed by the user)
	* codec
	* bitrate
	* dimensions
	* duration
	* frame_rate
- Actor Table:
	* id (UUID, Primary Key)
	* name (Unique)
- Tag Table:
	* id (UUID, Primary Key)
	* name (Unique)
- Studio Table:
	* id (UUID, Primary Key)
	* name (Unique)
- Folder Table:
	* id (Primary Key)
	* name
	* parent_folder_id (foreign key to the parent folder's id, blank for root folders)
- Watched Directory Table:
	* id (UUID, Primary Key)
	* directory_path (TEXT)
	* default_studio_id
	* default_folder_id
	* last_scan_time (DATETIME)

- Thumbnails: Thumbnails should be cached on disk to the application folder as the database will likely have 10000+ items in different locations on a network share.
- Database Operations: These should be handled by a single dedicated worker thread with database requests being added to a queue to prevent database locking issues.
- Thumbnails and the database should be stored in dedicated subfolders to keep the main application folder tidy

## **System Specifications:**

- OS: Windows 11 Pro
- CPU: Intel i9-13900K
- RAM: 64GB (~42GB available under normal circumstances)
- GPU: NVIDIA RTX 4080 with 16GB of VRAM (~13GB available under normal circumstances)
- Storage: ~2TB available.
- Python: 3.11.1
- Primary Monitor Resolution: 2560x1440

## **Additional Requirements/Preferences**

1. **Modularity:** The project should be structured with smaller Python files, each implementing a single class. Large files (such as the main interface controls) should be abstracted into smaller files to avoid monolithic files that become difficult to maintain.
2. **Simplicity:** Coding approaches should favor simpler approaches that accomplish the goal over more complex approaches that may offer little benefit for the amount of complexity they add.
3. **Development Approach:** A "walking skeleton" approach is preferred, following the order of the user workflow for easy testing.
4. **UI Framework:** PyQt6 is the required library for the user interface, with Flask/Waitress used for the web interface
5. **Code Quality:** Code must be well-commented. Type hints should be used for clarity and maintainability.
6. **Testing:** After each component is implemented, it should be tested to ensure it functions correctly before moving on.
7. **Error Handling & Logging:**
	- Use the Python `logging` module to capture errors and informational messages to a file in a `logs` subfolder. Use `logging.handlers.RotatingFileHandler` with a max size of 1MB.
	- User-facing errors (e.g., "Video file not found") should be logged to the "Activity" panel allowing the user to review later.
8. **Responsiveness:** 
	- All long-running tasks **must** be executed in background worker threads (using `QThreadPool`) to keep the UI responsive. Use Qt's signal and slot mechanism for thread-safe communication.
	- When a worker (either when adding media or resyncing the database) runs, it should do the following:
		* If the file path is associated with a folder on a network share (UNC path structure) it should initially perform a check to see if the path is accessible with a timeout to prevent the process from hanging indefinitely. If the operation times out, the user should be notified and the folder skipped. For an operation like "Resync Database" a subsequent failure should result in the operation being aborted.

9 **Configuration Management:**
	- A JSON file should be saved in the root folder of the application to store items like background scan interval, database location, thumbnail location, maximum worker concurrency, and log file settings. Any other values that would be hardcoded should be instead moved to the JSON file to allow for easy editing if needed.

## **Video/Library Specifications**

- **Input Videos:** Standard video containers like (.mp4, .m4v) Input videos will likely have a maximum resolution of 1920x1080
- **Video Codec:** H.264, H.265
- **Database Size:** The database should be able to handle 10000+ video sources
- **Video Sources:** Most videos will be stored on a network share, so the application will need to ensure it supports UNC path formatting and increased latency when accessing files/file data.

## **Future Considerations (Currently Out of Scope)**

- Filtering Activity log to include the option to show all items or only errors.
- Implement dashboard view to see usage
- Keyboard shortcuts to Management view
- Transcoding support for browser streaming using GPU acceleration
- Toggle between AND/OR for missing metadata filters