FEATURE: Added support for configuration files, documentation updated
All checks were successful
Publish Python Package to PyPI / deploy (push) Successful in 18s
All checks were successful
Publish Python Package to PyPI / deploy (push) Successful in 18s
This commit is contained in:
44
README.md
44
README.md
@ -16,6 +16,9 @@ This tool is perfect for users who want to standardize their media library's aud
|
|||||||
|
|
||||||
* Processes multiple files simultaneously to dramatically speed up batch jobs, automatically using the optimal number of CPU cores.
|
* Processes multiple files simultaneously to dramatically speed up batch jobs, automatically using the optimal number of CPU cores.
|
||||||
|
|
||||||
|
* **User-Friendly Configuration:**
|
||||||
|
* Automatically creates a default `options.json` file on the first run for easy customization. Command-line options always override the config file.
|
||||||
|
|
||||||
* **Interactive Progress Bar:**
|
* **Interactive Progress Bar:**
|
||||||
|
|
||||||
* A clean `tqdm` progress bar shows you the overall progress, ETA, and processing speed.
|
* A clean `tqdm` progress bar shows you the overall progress, ETA, and processing speed.
|
||||||
@ -88,7 +91,7 @@ The primary command is `eac3-transcode`.
|
|||||||
`eac3-transcode --input "/path/to/your/video_folder/" --dry-run `
|
`eac3-transcode --input "/path/to/your/video_folder/" --dry-run `
|
||||||
__*This is the safest way to start, to confirm the script's logic matches your expectations.*__
|
__*This is the safest way to start, to confirm the script's logic matches your expectations.*__
|
||||||
|
|
||||||
2. **Process** all videos in a folder (output saved in the same directory as **originals):**
|
2. **Process** all videos in a folder (using defaults or your config file):**
|
||||||
|
|
||||||
`eac3-transcode --input "/path/to/your/video_folder/"`
|
`eac3-transcode --input "/path/to/your/video_folder/"`
|
||||||
__*This will use all available CPU cores for maximum speed.*__
|
__*This will use all available CPU cores for maximum speed.*__
|
||||||
@ -107,6 +110,45 @@ __*This will use all available CPU cores for maximum speed.*__
|
|||||||
|
|
||||||
`eac3-transcode --input "/path/to/your/video_folder/" --force-reprocess`
|
`eac3-transcode --input "/path/to/your/video_folder/" --force-reprocess`
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
For convenience, the script supports a `options.json` file to set your preferred defaults.
|
||||||
|
|
||||||
|
### How it Works
|
||||||
|
|
||||||
|
1. **Automatic Creation:** The **first time** you run the script, it will automatically create a default `options.json` file in your user's configuration directory. It will print a message showing you where the file was created.
|
||||||
|
|
||||||
|
2. **Search Order:** When you run the command, it looks for a `options.json` file in this order:
|
||||||
|
|
||||||
|
* **1. Current Directory:** A `options.json` in the folder you are running the command from (for project-specific settings).
|
||||||
|
|
||||||
|
* **2. User Config Directory:** The global config file it created on the first run.
|
||||||
|
|
||||||
|
3. **Overrides:** Any option you provide on the command line (e.g., `--bitrate 640k`) will always take precedence over the setting in the config file for that specific run.
|
||||||
|
|
||||||
|
### Config File Location
|
||||||
|
|
||||||
|
The global config file is located in the standard directory for your operating system:
|
||||||
|
|
||||||
|
* Windows: `C:\Users\<YourUser>\AppData\Roaming\eac3-transcode\options.json`
|
||||||
|
|
||||||
|
* macOS: `/Users/<YourUser>/Library/Application Support/eac3-transcode/options.json`
|
||||||
|
|
||||||
|
* Linux: `/home/<YourUser>/.config/eac3-transcode/options.json`
|
||||||
|
|
||||||
|
**Example `options.json`**
|
||||||
|
You can edit this JSON file ot change your default settings.
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"output_directory_base": null,
|
||||||
|
"audio_bitrate": "640k",
|
||||||
|
"languages": "eng,jpn",
|
||||||
|
"jobs": 8,
|
||||||
|
"dry_run": false,
|
||||||
|
"force_reprocess": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Command-Line Options
|
## Command-Line Options
|
||||||
|
|
||||||
**Usage:**
|
**Usage:**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = surround-to-eac3
|
name = surround-to-eac3
|
||||||
version = 0.3.4
|
version = 0.4.0
|
||||||
author = Jonathan Rampersad
|
author = Jonathan Rampersad
|
||||||
author_email = jonathan@jono-rams.work
|
author_email = jonathan@jono-rams.work
|
||||||
description = A CLI tool to transcode 5.1 audio in video files to E-AC3.
|
description = A CLI tool to transcode 5.1 audio in video files to E-AC3.
|
||||||
@ -19,6 +19,7 @@ packages = find:
|
|||||||
python_requires = >=3.10
|
python_requires = >=3.10
|
||||||
install_requires =
|
install_requires =
|
||||||
tqdm
|
tqdm
|
||||||
|
platformdirs
|
||||||
|
|
||||||
[options.packages.find]
|
[options.packages.find]
|
||||||
where=src
|
where=src
|
||||||
|
@ -6,8 +6,13 @@ import argparse
|
|||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
import queue
|
import queue
|
||||||
from functools import partial
|
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
from platformdirs import user_config_dir
|
||||||
|
|
||||||
|
# --- Constants for Configuration ---
|
||||||
|
APP_NAME = "eac3-transcode"
|
||||||
|
APP_AUTHOR = "eac3-transcode"
|
||||||
|
CONFIG_FILENAME = "options.json"
|
||||||
|
|
||||||
# Global lock for TQDM writes to prevent interleaving from multiple threads
|
# Global lock for TQDM writes to prevent interleaving from multiple threads
|
||||||
tqdm_lock = threading.Lock()
|
tqdm_lock = threading.Lock()
|
||||||
@ -380,15 +385,47 @@ def main():
|
|||||||
help="Force reprocessing of all files, even if an output file with the target name already exists."
|
help="Force reprocessing of all files, even if an output file with the target name already exists."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# --- Configuration File Logic ---
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
user_config_dir_path = user_config_dir(APP_NAME, APP_AUTHOR)
|
||||||
|
user_config_file_path = os.path.join(user_config_dir_path, CONFIG_FILENAME)
|
||||||
|
|
||||||
|
if not os.path.exists(user_config_file_path):
|
||||||
|
try:
|
||||||
|
defaults = {action.dest: action.default for action in parser._actions if action.dest != "help" and not action.required}
|
||||||
|
os.makedirs(user_config_dir_path, exist_ok=True)
|
||||||
|
with open(user_config_file_path, 'w') as f:
|
||||||
|
json.dump(defaults, f, indent=4)
|
||||||
|
print(f"✅ Created default configuration at: {user_config_file_path}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Warning: Could not create default config at '{user_config_file_path}': {e}")
|
||||||
|
|
||||||
|
potential_paths = [os.path.join(os.getcwd(), CONFIG_FILENAME), user_config_file_path]
|
||||||
|
loaded_config_path = None
|
||||||
|
for path in potential_paths:
|
||||||
|
if os.path.exists(path):
|
||||||
|
try:
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
loaded_config_path = path
|
||||||
|
break
|
||||||
|
except (json.JSONDecodeError, IOError) as e:
|
||||||
|
print(f"⚠️ Warning: Could not read or parse config at '{path}': {e}")
|
||||||
|
break
|
||||||
|
|
||||||
|
parser.set_defaults(**config)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if loaded_config_path:
|
||||||
|
print(f"✅ Loaded configuration from: {loaded_config_path}")
|
||||||
|
|
||||||
if args.dry_run:
|
if args.dry_run:
|
||||||
print("--- DRY RUN MODE ENABLED: No files will be modified. ---")
|
print("--- DRY RUN MODE ENABLED: No files will be modified. ---")
|
||||||
|
|
||||||
|
# --- File Discovery ---
|
||||||
input_path_abs = os.path.abspath(args.input_path)
|
input_path_abs = os.path.abspath(args.input_path)
|
||||||
files_to_process_paths = []
|
files_to_process_paths = []
|
||||||
|
|
||||||
# Collect all files to process
|
|
||||||
if os.path.isdir(input_path_abs):
|
if os.path.isdir(input_path_abs):
|
||||||
print(f"📁 Scanning folder: {input_path_abs}")
|
print(f"📁 Scanning folder: {input_path_abs}")
|
||||||
for root, _, filenames in os.walk(input_path_abs):
|
for root, _, filenames in os.walk(input_path_abs):
|
||||||
|
Reference in New Issue
Block a user