[+] formatting
This commit is contained in:
+38
-15
@@ -1,9 +1,10 @@
|
|||||||
import glob
|
import glob
|
||||||
import traceback
|
import traceback
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import check_call
|
from subprocess import check_call, DEVNULL
|
||||||
|
|
||||||
from hypy_utils import printc
|
from hypy_utils import printc
|
||||||
|
from rich.progress import track
|
||||||
|
|
||||||
defaults = {
|
defaults = {
|
||||||
'av1': {
|
'av1': {
|
||||||
@@ -34,6 +35,9 @@ defaults = {
|
|||||||
'-c:a': 'flac',
|
'-c:a': 'flac',
|
||||||
'-compression_level': '7',
|
'-compression_level': '7',
|
||||||
},
|
},
|
||||||
|
'wav': {
|
||||||
|
'-c:a': 'pcm_s16le',
|
||||||
|
}
|
||||||
}
|
}
|
||||||
suffixes = {
|
suffixes = {
|
||||||
'av1': '.av1-{-crf}.mp4',
|
'av1': '.av1-{-crf}.mp4',
|
||||||
@@ -41,10 +45,13 @@ suffixes = {
|
|||||||
'mp3': '.v{-q:a}.mp3',
|
'mp3': '.v{-q:a}.mp3',
|
||||||
'opus': '.v{-b:a}.opus',
|
'opus': '.v{-b:a}.opus',
|
||||||
'flac': '.flac',
|
'flac': '.flac',
|
||||||
|
'wav': '.wav',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def main(fmt: str, files: list[str], keep: bool, passthrough: list[str]):
|
def main(fmt: str, files: list[str], keep: bool, passthrough: list[str], quiet: bool = False, silent: bool = False):
|
||||||
|
printq = printc if not silent else lambda *a, **k: None
|
||||||
|
quiet = quiet or silent
|
||||||
# Process each file provided on the command line
|
# Process each file provided on the command line
|
||||||
files = [
|
files = [
|
||||||
Path(p)
|
Path(p)
|
||||||
@@ -52,16 +59,19 @@ def main(fmt: str, files: list[str], keep: bool, passthrough: list[str]):
|
|||||||
for p in glob.glob(str(Path(pattern).expanduser()))
|
for p in glob.glob(str(Path(pattern).expanduser()))
|
||||||
if Path(p).is_file()
|
if Path(p).is_file()
|
||||||
]
|
]
|
||||||
|
total_orig_size, total_new_size = 0, 0
|
||||||
printc(f"&e> Using format: {fmt}")
|
printc(f"&e> Using format: {fmt}")
|
||||||
printc(f"&e> Found {len(files)} files to process.")
|
printc(f"&e> Found {len(files)} files to process.")
|
||||||
printc(f"&e> Keep original files: {'Yes' if keep else 'No'}")
|
printc(f"&e> Keep original files: {'Yes' if keep else 'No'}")
|
||||||
printc(f"&e> Passthrough parameters: {passthrough if passthrough else 'None'}")
|
printc(f"&e> Passthrough parameters: {passthrough if passthrough else 'None'}")
|
||||||
print()
|
print()
|
||||||
for inf in files:
|
for inf in track(files):
|
||||||
printc("&e-----------------------------------------")
|
printq("&e-----------------------------------------")
|
||||||
try:
|
try:
|
||||||
params: dict[str, str | None] = defaults[fmt].copy()
|
params: dict[str, str | None] = defaults[fmt].copy()
|
||||||
old_size = inf.stat().st_size
|
old_size = inf.stat().st_size
|
||||||
|
if quiet:
|
||||||
|
params['-y'] = None # Overwrite output files without asking
|
||||||
|
|
||||||
# Check for any passthrough arguments and add them to params (overrides defaults)
|
# Check for any passthrough arguments and add them to params (overrides defaults)
|
||||||
i = 0
|
i = 0
|
||||||
@@ -70,11 +80,11 @@ def main(fmt: str, files: list[str], keep: bool, passthrough: list[str]):
|
|||||||
# Check if next item exists and is not a flag (i.e., it's a value)
|
# Check if next item exists and is not a flag (i.e., it's a value)
|
||||||
if i + 1 < len(passthrough) and not passthrough[i+1].startswith('-'):
|
if i + 1 < len(passthrough) and not passthrough[i+1].startswith('-'):
|
||||||
v = passthrough[i+1]
|
v = passthrough[i+1]
|
||||||
printc(f"&a> Overriding parameter: {k} {v} (was {params.get(k, 'not set')})")
|
printq(f"&a> Overriding parameter: {k} {v} (was {params.get(k, 'not set')})")
|
||||||
params[k] = v
|
params[k] = v
|
||||||
i += 2
|
i += 2
|
||||||
else: # It's a standalone flag
|
else: # It's a standalone flag
|
||||||
printc(f"&a> Overriding parameter: {k} (was {params.get(k, 'not set')})")
|
printq(f"&a> Overriding parameter: {k} (was {params.get(k, 'not set')})")
|
||||||
params[k] = None # Use None to signify a flag without a value
|
params[k] = None # Use None to signify a flag without a value
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
@@ -84,35 +94,48 @@ def main(fmt: str, files: list[str], keep: bool, passthrough: list[str]):
|
|||||||
end = ''.join(c for c in end if c.isalnum() or c in ' ._-+').rstrip()
|
end = ''.join(c for c in end if c.isalnum() or c in ' ._-+').rstrip()
|
||||||
|
|
||||||
if inf.name.endswith(end):
|
if inf.name.endswith(end):
|
||||||
printc(f"&c> Error: File already has target suffix '{end}', skipping: {inf.name}")
|
printq(f"&c> Error: File already has target suffix '{end}', skipping: {inf.name}")
|
||||||
continue
|
continue
|
||||||
ouf = inf.with_name(f'{inf.stem}{end}')
|
ouf = inf.with_name(f'{inf.stem}{end}')
|
||||||
printc(f"&e+ Compressing '{inf.name}' > '{ouf.name}'")
|
printq(f"&e+ Compressing '{inf.name}' > '{ouf.name}'")
|
||||||
|
|
||||||
# Construct and run the ffmpeg command
|
# Construct and run the ffmpeg command
|
||||||
cmd = ['ffmpeg', '-hide_banner', '-i',
|
cmd = ['ffmpeg', '-hide_banner', '-i',
|
||||||
str(inf),
|
str(inf),
|
||||||
*sum(([k] if v is None else [k, str(v)] for k, v in params.items()), []),
|
*sum(([k] if v is None else [k, str(v)] for k, v in params.items()), []),
|
||||||
str(ouf)]
|
str(ouf)]
|
||||||
printc(f"&e> Running command: {' '.join(cmd)}")
|
printq(f"&e> Running command: {' '.join(cmd)}")
|
||||||
|
|
||||||
check_call(cmd)
|
check_call(cmd) if not quiet else check_call(cmd, stdout=DEVNULL, stderr=DEVNULL)
|
||||||
printc(f"&a> Compression successful :)")
|
printq(f"&a> Compression successful :)")
|
||||||
new_size = ouf.stat().st_size
|
new_size = ouf.stat().st_size
|
||||||
ratio = new_size / old_size
|
ratio = new_size / old_size
|
||||||
printc(f"&a> Size: {old_size / 1_000_000:.2f} MB -> {new_size / 1_000_000:.2f} MB ({ratio:.2%})")
|
printq(f"&a> Size: {old_size / 1_000_000:.2f} MB -> {new_size / 1_000_000:.2f} MB ({ratio:.2%})")
|
||||||
|
|
||||||
|
total_orig_size += old_size
|
||||||
|
total_new_size += new_size
|
||||||
|
|
||||||
if not keep:
|
if not keep:
|
||||||
if new_size >= old_size:
|
if new_size >= old_size:
|
||||||
printc(f"&c! Warning: Compressed file is not smaller than original. Keeping original file :(")
|
printc(f"&c! Warning: Compressed file is not smaller than original. Keeping original file :(")
|
||||||
else:
|
else:
|
||||||
printc(f"&e- Removing original file: '{inf.name}'")
|
printq(f"&e- Removing original file: '{inf.name}'")
|
||||||
inf.unlink()
|
inf.unlink()
|
||||||
printc(f"&a> Original file removed.")
|
printq(f"&a> Original file removed.")
|
||||||
|
|
||||||
print()
|
printq('')
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
printc(f"&c! An error occurred while processing {inf.name}: {e}")
|
printc(f"&c! An error occurred while processing {inf.name}: {e}")
|
||||||
printc("&c! Leaving original file intact.\n")
|
printc("&c! Leaving original file intact.\n")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# Print summary
|
||||||
|
if total_orig_size > 0:
|
||||||
|
total_ratio = total_new_size / total_orig_size
|
||||||
|
printc("&a=========================================")
|
||||||
|
printc(f"&a> Processed {len(files)} files.")
|
||||||
|
printc(f"&a> Total size: {total_orig_size / 1_000_000:.2f} MB -> {total_new_size / 1_000_000:.2f} MB ({total_ratio:.2%})")
|
||||||
|
printc("&a=========================================")
|
||||||
|
else:
|
||||||
|
printc("&c! Nothing to do")
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ def cli(fmt: str | None = None):
|
|||||||
agupa.add_argument('format', choices=defaults.keys(), help="Compression format to use.")
|
agupa.add_argument('format', choices=defaults.keys(), help="Compression format to use.")
|
||||||
agupa.add_argument('files', nargs='+', help="One or more files to compress.")
|
agupa.add_argument('files', nargs='+', help="One or more files to compress.")
|
||||||
agupa.add_argument('--keep', action='store_true', help="Keep original files after compression.")
|
agupa.add_argument('--keep', action='store_true', help="Keep original files after compression.")
|
||||||
|
agupa.add_argument('--quiet', action='store_true', help="Suppress ffmpeg output.")
|
||||||
|
agupa.add_argument('--silent', action='store_true', help="Suppress all output except errors.")
|
||||||
args, passthrough = agupa.parse_known_args()
|
args, passthrough = agupa.parse_known_args()
|
||||||
|
|
||||||
main(fmt or args.format, args.files, args.keep, passthrough)
|
main(fmt or args.format, args.files, args.keep, passthrough, args.quiet, args.silent)
|
||||||
|
|
||||||
|
|
||||||
def av1():
|
def av1():
|
||||||
@@ -34,5 +36,9 @@ def flac():
|
|||||||
cli('flac')
|
cli('flac')
|
||||||
|
|
||||||
|
|
||||||
|
def wav():
|
||||||
|
cli('wav')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
cli()
|
cli()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ readme = "README.md"
|
|||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hypy-utils>=1.0.29",
|
"hypy-utils>=1.0.29",
|
||||||
|
"rich>=14.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
@@ -15,3 +16,4 @@ fx264 = "formtool.__main__:x264"
|
|||||||
fmp3 = "formtool.__main__:mp3"
|
fmp3 = "formtool.__main__:mp3"
|
||||||
fopus = "formtool.__main__:opus"
|
fopus = "formtool.__main__:opus"
|
||||||
fflac = "formtool.__main__:flac"
|
fflac = "formtool.__main__:flac"
|
||||||
|
fwav = "formtool.__main__:wav"
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ version = "0.1.0"
|
|||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "hypy-utils" },
|
{ name = "hypy-utils" },
|
||||||
|
{ name = "rich" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [{ name = "hypy-utils", specifier = ">=1.0.29" }]
|
requires-dist = [
|
||||||
|
{ name = "hypy-utils", specifier = ">=1.0.29" },
|
||||||
|
{ name = "rich", specifier = ">=14.1.0" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hypy-utils"
|
name = "hypy-utils"
|
||||||
@@ -21,3 +25,46 @@ sdist = { url = "https://files.pythonhosted.org/packages/e1/02/6c93a5f7be972d55b
|
|||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e8/34/7e4f6c09da586d317a74958e6b853da8a4c220898c5a8adf98030abb1492/hypy_utils-1.0.29-py3-none-any.whl", hash = "sha256:146a5aa85d3b4bc175e64d3f9e26befd0d87d221c4366eb70e137e46933eb65d", size = 18099, upload-time = "2024-12-10T11:51:12.019Z" },
|
{ url = "https://files.pythonhosted.org/packages/e8/34/7e4f6c09da586d317a74958e6b853da8a4c220898c5a8adf98030abb1492/hypy_utils-1.0.29-py3-none-any.whl", hash = "sha256:146a5aa85d3b4bc175e64d3f9e26befd0d87d221c4366eb70e137e46933eb65d", size = 18099, upload-time = "2024-12-10T11:51:12.019Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markdown-it-py"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "mdurl" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mdurl"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pygments"
|
||||||
|
version = "2.19.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rich"
|
||||||
|
version = "14.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markdown-it-py" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa6a9d089ca6c07ff4453d86c65c145d0a300bb073b9b/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8", size = 224441, upload-time = "2025-07-25T07:32:58.125Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" },
|
||||||
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user