Added user defined language list
All checks were successful
Publish Python Package to PyPI / deploy (push) Successful in 14s
All checks were successful
Publish Python Package to PyPI / deploy (push) Successful in 14s
This commit is contained in:
41
README.md
41
README.md
@ -2,25 +2,29 @@
|
|||||||
|
|
||||||
**A** command-line utility to intelligently find and convert 5.1 surround sound audio tracks in your video files (`.mkv`, `.mp4`) to **the E-AC3 (Dolby Digital Plus) format, while preserving other streams.**
|
**A** command-line utility to intelligently find and convert 5.1 surround sound audio tracks in your video files (`.mkv`, `.mp4`) to **the E-AC3 (Dolby Digital Plus) format, while preserving other streams.**
|
||||||
|
|
||||||
This tool is perfect for users who want to standardize their media library's audio, ensuring compatibility and high quality for 5.1 channel audio tracks, particularly for English and Japanese languages.
|
This tool is perfect for users who want to standardize their media library's audio, ensuring compatibility and high quality for 5.1 channel audio tracks while allowing you to filter by language.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
`eac3-transcode` automates the often tedious process of inspecting video files, identifying specific audio tracks, and re-encoding them. It's designed to be smart about which tracks to process:
|
`eac3-transcode` automates the often tedious process of inspecting video files, identifying specific audio tracks, and re-encoding them. It's designed to be smart about which tracks to process:
|
||||||
|
|
||||||
* **Scans Individual Files or Entire Directories:** Process a single video or batch-process an entire folder (including subfolders).
|
* **Scans Individual Files or Entire Directories:**
|
||||||
|
|
||||||
* **Targets Specific Languages:** Focuses on English (`eng`) and Japanese (`jpn`) audio streams.
|
* Process a single video or batch-process an entire folder (including subfolders).
|
||||||
|
|
||||||
|
* **Targets Specific Languages:**
|
||||||
|
|
||||||
|
* By default, it processes English (`eng`) and Japanese (`jpn`) audio streams, but this is **fully customizable** via a command-line argument.
|
||||||
|
|
||||||
* **Intelligent Transcoding:**
|
* **Intelligent Transcoding:**
|
||||||
|
|
||||||
* Converts 5.1 channel audio streams (that aren't already `ac3` or `eac3`) to `eac3`.
|
* Converts 5.1 channel audio streams (that aren't already `ac3` or `eac3`) in your target languages to `eac3`.
|
||||||
|
|
||||||
* **Smart Copying:**
|
* **Smart Copying:**
|
||||||
|
|
||||||
* Copies English or Japanese audio streams that are already in `ac3` or `eac3` format.
|
* Copies target language audio streams that are already in `ac3` or `eac3` format.
|
||||||
|
|
||||||
* Copies English or Japanese audio streams that are not 5.1 channels (e.g., stereo).
|
* Copies target language audio streams that are not 5.1 channels (e.g., stereo).
|
||||||
|
|
||||||
* **Stream Preservation:**
|
* **Stream Preservation:**
|
||||||
|
|
||||||
@ -30,9 +34,9 @@ This tool is perfect for users who want to standardize their media library's aud
|
|||||||
|
|
||||||
* **Efficient Processing:**
|
* **Efficient Processing:**
|
||||||
|
|
||||||
* Other language audio streams are dropped to save space and processing time.
|
* Audio streams not in your target languages are dropped to save space and processing time.
|
||||||
|
|
||||||
* Files are skipped entirely if no English or Japanese audio streams meet the criteria for transcoding or copying, preventing empty or unnecessary output files.
|
* Files are skipped entirely if no audio streams in the target languages meet the criteria for transcoding or copying, preventing empty or unnecessary output files.
|
||||||
|
|
||||||
* **Flexible Output:** Save processed files alongside originals or in a specified output directory, maintaining the source folder structure if applicable.
|
* **Flexible Output:** Save processed files alongside originals or in a specified output directory, maintaining the source folder structure if applicable.
|
||||||
|
|
||||||
@ -79,11 +83,15 @@ eac3-transcode --input "/path/to/your/video_folder/" --outdir "/path/to/your/pro
|
|||||||
|
|
||||||
eac3-transcode --input "video.mp4" --bitrate "640k"
|
eac3-transcode --input "video.mp4" --bitrate "640k"
|
||||||
|
|
||||||
|
4. **Process for different languages (e.g., English and Spanish):**
|
||||||
|
|
||||||
|
eac3-transcode --input "video.mkv" --langs "eng,spa"
|
||||||
|
|
||||||
## Command-Line Options
|
## Command-Line Options
|
||||||
|
|
||||||
**Usage:**
|
**Usage:**
|
||||||
|
|
||||||
eac3-transcode [-h] -i INPUT_PATH [-o OUTPUT_DIRECTORY_BASE] [-br AUDIO_BITRATE]
|
eac3-transcode [-h] -i INPUT_PATH [-o OUTPUT_DIRECTORY_BASE] [-br AUDIO_BITRATE] [-l LANGUAGES]
|
||||||
An advanced video transcoder that processes files to use E-AC3 for specific audio tracks, filters by language, and can process entire folders.
|
An advanced video transcoder that processes files to use E-AC3 for specific audio tracks, filters by language, and can process entire folders.
|
||||||
|
|
||||||
**Options:**
|
**Options:**
|
||||||
@ -100,6 +108,9 @@ An advanced video transcoder that processes files to use E-AC3 for specific audi
|
|||||||
* `-br AUDIO_BITRATE, --bitrate AUDIO_BITRATE`
|
* `-br AUDIO_BITRATE, --bitrate AUDIO_BITRATE`
|
||||||
**(Optional)** Sets the audio bitrate for the E-AC3 stream (e.g., '640k', '1536k'). Defaults to '1536k'.
|
**(Optional)** Sets the audio bitrate for the E-AC3 stream (e.g., '640k', '1536k'). Defaults to '1536k'.
|
||||||
|
|
||||||
|
* `-l LANGUAGES, --langs LANGUAGES`
|
||||||
|
**(Optional)** Comma-separated list of 3-letter audio languages to keep (e.g., 'eng,spa,fre'). Defaults to 'eng,jpn'.
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|
||||||
1. **File Discovery:** The script scans the input path for `.mkv` and `.mp4` files.
|
1. **File Discovery:** The script scans the input path for `.mkv` and `.mp4` files.
|
||||||
@ -110,21 +121,21 @@ An advanced video transcoder that processes files to use E-AC3 for specific audi
|
|||||||
|
|
||||||
3. **Decision Logic:**
|
3. **Decision Logic:**
|
||||||
|
|
||||||
* **Language Filter:** Only `eng` (English) and `jpn` (Japanese) audio streams are considered for keeping. Others are marked to be dropped.
|
* **Language Filter:** Only audio streams matching the languages provided with the `-l LANGUAGES, --langs LANGUAGES` option are considered for keeping. **This defaults to `eng,jpn`**. Others are marked to be dropped.
|
||||||
|
|
||||||
* **Transcode Criteria:** An `eng` or `jpn` stream is transcoded to E-AC3 if:
|
* **Transcode Criteria:** A target language stream is transcoded to E-AC3 if:
|
||||||
|
|
||||||
* It has 6 audio channels (5.1 surround).
|
* It has 6 audio channels (5.1 surround).
|
||||||
|
|
||||||
* Its current codec is *not* `ac3` or `eac3`.
|
* Its current codec is *not* `ac3` or `eac3`.
|
||||||
|
|
||||||
* **Copy Criteria:** An `eng` or `jpn` stream is copied directly if:
|
* **Copy Criteria:** A target language stream is copied directly if:
|
||||||
|
|
||||||
* It's already `ac3` or `eac3`.
|
* It's already `ac3` or `eac3`.
|
||||||
|
|
||||||
* It does not have 6 channels (e.g., it's stereo).
|
* It does not have 6 channels (e.g., it's stereo).
|
||||||
|
|
||||||
* **File Skipping:** If no audio streams are marked for either 'transcode' or 'copy' (e.g., a file only contains French audio, or all English/Japanese audio is already in the desired format and channel layout for copying), the entire file is skipped to avoid creating redundant or empty output files.
|
* **File Skipping:** If no audio streams are marked for 'transcode' (e.g., a file only contains French audio, and French is not a target language, or all target languages' audio are already in the desired format and channel layout for copying), the entire file is skipped to avoid creating redundant or empty output files.
|
||||||
|
|
||||||
4. **Processing (using `ffmpeg`):**
|
4. **Processing (using `ffmpeg`):**
|
||||||
|
|
||||||
@ -144,9 +155,9 @@ An advanced video transcoder that processes files to use E-AC3 for specific audi
|
|||||||
|
|
||||||
* Ensure FFmpeg is installed correctly and its `bin` directory is in your system's PATH environment variable. See the [Prerequisites](#prerequisites) section.
|
* Ensure FFmpeg is installed correctly and its `bin` directory is in your system's PATH environment variable. See the [Prerequisites](#prerequisites) section.
|
||||||
|
|
||||||
* **No files processed / "Skipping 'filename': No English/Japanese audio streams meet criteria..."**:
|
* **No files processed / "Skipping 'filename': No audio streams in the desired languages... meet criteria..."**:
|
||||||
|
|
||||||
* This is expected behavior if the files scanned do not contain any English or Japanese audio tracks that require transcoding to E-AC3 or qualify for copying based on the tool's logic. For example, if a file only has a stereo English AAC track, it will be copied (not transcoded to 5.1 E-AC3). If it only has a French 5.1 DTS track, it will be skipped.
|
* This is expected behavior if the files scanned do not contain any audio tracks in the target languages that require transcoding to E-AC3 or qualify for copying. This message reflects the default languages (`eng,jpn`) or the ones you specified with `--langs`.
|
||||||
|
|
||||||
* **Permission Errors:**
|
* **Permission Errors:**
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = surround-to-eac3
|
name = surround-to-eac3
|
||||||
version = 0.1.4
|
version = 0.2.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.
|
||||||
|
@ -177,8 +177,15 @@ def main():
|
|||||||
dest="audio_bitrate",
|
dest="audio_bitrate",
|
||||||
default="1536k"
|
default="1536k"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-l", "--langs",
|
||||||
|
help="Comma-separated list of 3-letter audio languages to keep (e.g., 'eng,jpn').\nDefaults to 'eng,jpn'.",
|
||||||
|
dest="languages",
|
||||||
|
default="eng,jpn"
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
target_languages = [lang.strip().lower() for lang in args.languages.split(',') if lang.strip()]
|
||||||
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 = []
|
||||||
|
|
||||||
@ -227,7 +234,7 @@ def main():
|
|||||||
lang = stream['language']
|
lang = stream['language']
|
||||||
op_to_perform = None # Will be 'transcode', 'copy', or None (for drop)
|
op_to_perform = None # Will be 'transcode', 'copy', or None (for drop)
|
||||||
|
|
||||||
if lang in ['eng', 'jpn']:
|
if lang in target_languages:
|
||||||
is_5_1 = stream.get('channels') == 6
|
is_5_1 = stream.get('channels') == 6
|
||||||
is_not_ac3_eac3 = stream.get('codec_name') not in ['ac3', 'eac3']
|
is_not_ac3_eac3 = stream.get('codec_name') not in ['ac3', 'eac3']
|
||||||
|
|
||||||
@ -242,7 +249,7 @@ def main():
|
|||||||
reason = ", ".join(reason_parts) if reason_parts else "meets other criteria for copying"
|
reason = ", ".join(reason_parts) if reason_parts else "meets other criteria for copying"
|
||||||
print(f" 🔈 Will copy: Audio stream #{stream['index']} ({lang}, {stream.get('channels')}ch, {stream.get('codec_name')}) - Reason: {reason}")
|
print(f" 🔈 Will copy: Audio stream #{stream['index']} ({lang}, {stream.get('channels')}ch, {stream.get('codec_name')}) - Reason: {reason}")
|
||||||
else:
|
else:
|
||||||
# Language is not English or Japanese, so it will be dropped (no op_to_perform)
|
# Language is not in the target list, so it will be dropped (no op_to_perform)
|
||||||
print(f" 🔈 Will drop: Audio stream #{stream['index']} ({lang}, {stream.get('channels')}ch, {stream.get('codec_name')}) - Other language.")
|
print(f" 🔈 Will drop: Audio stream #{stream['index']} ({lang}, {stream.get('channels')}ch, {stream.get('codec_name')}) - Other language.")
|
||||||
|
|
||||||
if op_to_perform:
|
if op_to_perform:
|
||||||
@ -252,17 +259,12 @@ def main():
|
|||||||
'lang': lang # Store for potential metadata setting during transcode
|
'lang': lang # Store for potential metadata setting during transcode
|
||||||
})
|
})
|
||||||
|
|
||||||
# --- Apply the new skipping logic ---
|
|
||||||
# If no English/Japanese audio streams meet criteria for processing (transcode/copy),
|
|
||||||
# skip creating a new file for this input file entirely.
|
|
||||||
if not audio_ops_for_ffmpeg:
|
if not audio_ops_for_ffmpeg:
|
||||||
print(f" ⏭️ Skipping '{display_name}': No English/Japanese audio streams meet criteria for processing (transcode/copy). File will not be created.")
|
print(f" ⏭️ Skipping '{display_name}': No audio streams in the desired languages ({args.languages}) meet criteria for processing. File will not be created.")
|
||||||
stats["skipped_rules"] += 1
|
stats["skipped_rules"] += 1
|
||||||
continue # Move to the next file in files_to_process_paths
|
continue # Move to the next file in files_to_process_paths
|
||||||
|
|
||||||
# If we reach here, audio_ops_for_ffmpeg is NOT empty,
|
# If we reach here, audio_ops_for_ffmpeg is NOT empty
|
||||||
# meaning at least one English or Japanese audio stream will be processed.
|
|
||||||
|
|
||||||
# Determine the output directory for this specific file
|
# Determine the output directory for this specific file
|
||||||
output_dir_for_this_file = None
|
output_dir_for_this_file = None
|
||||||
if args.output_directory_base:
|
if args.output_directory_base:
|
||||||
@ -298,3 +300,7 @@ def main():
|
|||||||
print(f"Skipped (no qualifying audio ops): {stats['skipped_rules']}")
|
print(f"Skipped (no qualifying audio ops): {stats['skipped_rules']}")
|
||||||
print(f"Failed to process: {stats['failed']}")
|
print(f"Failed to process: {stats['failed']}")
|
||||||
print("--------------------------")
|
print("--------------------------")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user