From e51a271a38673b7e23782a54728530a21152245c Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Fri, 16 Jun 2023 15:56:39 +0300 Subject: [PATCH 01/10] RenPy-Android-Unpack: .obb files support --- RenPy-Android-Unpack/unpack.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/RenPy-Android-Unpack/unpack.py b/RenPy-Android-Unpack/unpack.py index 6d826a8..bc7047e 100755 --- a/RenPy-Android-Unpack/unpack.py +++ b/RenPy-Android-Unpack/unpack.py @@ -9,10 +9,11 @@ def extract_assets(file): for content in zip_ref.namelist(): if content.split('/')[0] == 'assets': zip_ref.extract(content) - zip_ref.extract('res/mipmap-xxxhdpi-v4/icon_background.png', 'assets') - zip_ref.extract('res/mipmap-xxxhdpi-v4/icon_foreground.png', 'assets') - os.rename('assets/res/mipmap-xxxhdpi-v4/icon_background.png', 'assets/android-icon_background.png') - os.rename('assets/res/mipmap-xxxhdpi-v4/icon_foreground.png', 'assets/android-icon_foreground.png') + if os.path.splitext(file)[1] == '.apk': + zip_ref.extract('res/mipmap-xxxhdpi-v4/icon_background.png', 'assets') + zip_ref.extract('res/mipmap-xxxhdpi-v4/icon_foreground.png', 'assets') + os.rename('assets/res/mipmap-xxxhdpi-v4/icon_background.png', 'assets/android-icon_background.png') + os.rename('assets/res/mipmap-xxxhdpi-v4/icon_foreground.png', 'assets/android-icon_foreground.png') def rename_files(directory): @@ -38,7 +39,7 @@ def rename_dirs(directory): if __name__ == '__main__': for filename in os.listdir(os.getcwd()): - if os.path.splitext(filename)[1] == '.apk': + if os.path.splitext(filename)[1] == '.apk' or os.path.splitext(filename)[1] == '.obb': print(f'[INFO] Extracting assets from {filename}... ', end='') extract_assets(filename) print('Done') @@ -48,7 +49,8 @@ if __name__ == '__main__': print('Done') print('[INFO] Removing unneeded files... ', end='') shutil.rmtree('assets/renpy') - shutil.rmtree('assets/res') + if os.path.splitext(filename)[1] == '.apk': + shutil.rmtree('assets/res') print('Done') print('[INFO] Renaming directory... ', end='') os.rename('assets', f'{os.path.splitext(filename)[0]}') From b2335509e38db7f3fa535cde0c9c99a23b0cd470 Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Thu, 6 Jul 2023 14:14:07 +0300 Subject: [PATCH 02/10] RenPy-Unpacker: Initial commit --- FFMpeg-Compressor/config.toml | 4 ++-- README.md | 3 ++- RenPy-Unpacker/README.md | 8 ++++++++ RenPy-Unpacker/unpack.rpy | 12 ++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 RenPy-Unpacker/README.md create mode 100644 RenPy-Unpacker/unpack.rpy diff --git a/FFMpeg-Compressor/config.toml b/FFMpeg-Compressor/config.toml index 2600227..e927951 100644 --- a/FFMpeg-Compressor/config.toml +++ b/FFMpeg-Compressor/config.toml @@ -2,8 +2,8 @@ AudioBitRate = "320k" AudioExt = "mp3" CompLevel = 20 -ImageExt = "png" +ImageExt = "jpg" JpegComp = 3 FFmpegParams = "-hide_banner -loglevel error" VideoCodec = "libvpx-vp9" -VideoExt = "webm" \ No newline at end of file +VideoExt = "webm" diff --git a/README.md b/README.md index 5982f00..127caae 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,5 @@ Collection of tools used by administrators from VN Telegram Channel ### Tools * `FFMpeg-Compressor` - Python utility uses ffmpeg to compress Visual Novel Resources -* `A simple Python script` for unpacking Ren'Py based .apk files for later rebuilding in the Ren'Py SDK +* `RenPy-Android-Unpack` - Simple Python script for unpacking Ren'Py based .apk files for later rebuilding in the Ren'Py SDK +* `RenPy-Unpacker` - Simple .rpy script that will make any RenPy game unpack itself diff --git a/RenPy-Unpacker/README.md b/RenPy-Unpacker/README.md new file mode 100644 index 0000000..41a3c75 --- /dev/null +++ b/RenPy-Unpacker/README.md @@ -0,0 +1,8 @@ +## RenPy-Unpacker +Simple .rpy script that will make any RenPy game unpack itself + +### How to use +* Put .rpyc from releases page to game's `game` folder +* Open your game and wait until it not be launched +* Unpacked assets will be in `unpack` folder near with game's executable +* Enjoy! diff --git a/RenPy-Unpacker/unpack.rpy b/RenPy-Unpacker/unpack.rpy new file mode 100644 index 0000000..07d6180 --- /dev/null +++ b/RenPy-Unpacker/unpack.rpy @@ -0,0 +1,12 @@ +init 4 python: + import os + + for asset in renpy.list_files(): + if os.path.splitext(asset)[1] != ".rpa": + output = "unpack/game/" + asset + if not os.path.exists(os.path.dirname(output)): + os.makedirs(os.path.dirname(output)) + + out_bytes = open(output, "wb") + out_bytes.write(renpy.file(asset).read()) + out_bytes.close() From 39aa70c5386ca6965a2f5cfad3e9ace83d4339de Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Thu, 6 Jul 2023 14:40:31 +0300 Subject: [PATCH 03/10] RenPy-Unpacker: Ignore itself --- RenPy-Unpacker/unpack.rpy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RenPy-Unpacker/unpack.rpy b/RenPy-Unpacker/unpack.rpy index 07d6180..005e855 100644 --- a/RenPy-Unpacker/unpack.rpy +++ b/RenPy-Unpacker/unpack.rpy @@ -2,7 +2,7 @@ init 4 python: import os for asset in renpy.list_files(): - if os.path.splitext(asset)[1] != ".rpa": + if os.path.splitext(asset)[1] != ".rpa" and asset != "unpack.rpyc": output = "unpack/game/" + asset if not os.path.exists(os.path.dirname(output)): os.makedirs(os.path.dirname(output)) From 250c4f789aec2c6259558a90f14d7f20ece136c3 Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Thu, 27 Jul 2023 16:57:08 +0300 Subject: [PATCH 04/10] RenPy-Android-Unpack: Support old RenPy versions --- RenPy-Android-Unpack/unpack.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/RenPy-Android-Unpack/unpack.py b/RenPy-Android-Unpack/unpack.py index bc7047e..1a89253 100755 --- a/RenPy-Android-Unpack/unpack.py +++ b/RenPy-Android-Unpack/unpack.py @@ -10,10 +10,15 @@ def extract_assets(file): if content.split('/')[0] == 'assets': zip_ref.extract(content) if os.path.splitext(file)[1] == '.apk': - zip_ref.extract('res/mipmap-xxxhdpi-v4/icon_background.png', 'assets') - zip_ref.extract('res/mipmap-xxxhdpi-v4/icon_foreground.png', 'assets') - os.rename('assets/res/mipmap-xxxhdpi-v4/icon_background.png', 'assets/android-icon_background.png') - os.rename('assets/res/mipmap-xxxhdpi-v4/icon_foreground.png', 'assets/android-icon_foreground.png') + try: + zip_ref.extract('res/mipmap-xxxhdpi-v4/icon_background.png', 'assets') + zip_ref.extract('res/mipmap-xxxhdpi-v4/icon_foreground.png', 'assets') + os.rename('assets/res/mipmap-xxxhdpi-v4/icon_background.png', 'assets/android-icon_background.png') + os.rename('assets/res/mipmap-xxxhdpi-v4/icon_foreground.png', 'assets/android-icon_foreground.png') + except KeyError: + zip_ref.extract('res/drawable/icon.png', 'assets') + os.rename('assets/res/drawable/icon.png', 'assets/icon.png') + def rename_files(directory): @@ -39,6 +44,7 @@ def rename_dirs(directory): if __name__ == '__main__': for filename in os.listdir(os.getcwd()): + renpy_warn = 0 if os.path.splitext(filename)[1] == '.apk' or os.path.splitext(filename)[1] == '.obb': print(f'[INFO] Extracting assets from {filename}... ', end='') extract_assets(filename) @@ -48,10 +54,15 @@ if __name__ == '__main__': rename_dirs('assets') print('Done') print('[INFO] Removing unneeded files... ', end='') - shutil.rmtree('assets/renpy') + try: + shutil.rmtree('assets/renpy') + except FileNotFoundError: + renpy_warn = 1 if os.path.splitext(filename)[1] == '.apk': shutil.rmtree('assets/res') print('Done') + if renpy_warn: + print("[WARN] File does not contain renpy folder!") print('[INFO] Renaming directory... ', end='') os.rename('assets', f'{os.path.splitext(filename)[0]}') print('Done') From 1caebeb15889440f495498eef12d6bc7cf8f24ed Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Tue, 1 Aug 2023 17:20:57 +0300 Subject: [PATCH 05/10] FFMpeg-Compressor: Compress subfolders & Add progressbar --- FFMpeg-Compressor/main.py | 20 ++++++++------ FFMpeg-Compressor/modules/compressor.py | 26 +++++++++--------- FFMpeg-Compressor/modules/printer.py | 35 ++++++++++++++++++------- FFMpeg-Compressor/modules/utils.py | 24 ++++++++--------- FFMpeg-Compressor/requirements.txt | 2 ++ RenPy-Android-Unpack/unpack.py | 1 - 6 files changed, 63 insertions(+), 45 deletions(-) create mode 100644 FFMpeg-Compressor/requirements.txt diff --git a/FFMpeg-Compressor/main.py b/FFMpeg-Compressor/main.py index c789839..fba5cff 100755 --- a/FFMpeg-Compressor/main.py +++ b/FFMpeg-Compressor/main.py @@ -3,22 +3,26 @@ from modules import compressor from modules import printer from modules import utils +import shutil import sys import os try: orig_folder = sys.argv[1] + printer.orig_folder = sys.argv[1] except IndexError: print(utils.help_message()) exit() -try: - os.mkdir(f"{orig_folder}_compressed") - printer.info(f"Created {orig_folder}_compressed folder") -except OSError: - printer.warning(f"{orig_folder}_compressed already exist!") - pass +printer.bar_init(orig_folder) -printer.info("Compression started!") -compressor.compress(orig_folder) +if os.path.exists(f"{orig_folder}_compressed"): + shutil.rmtree(f"{orig_folder}_compressed") +printer.info("Creating folders...") +for folder, folders, files in os.walk(orig_folder): + if not os.path.exists(folder.replace(orig_folder, f"{orig_folder}_compressed")): + os.mkdir(folder.replace(orig_folder, f"{orig_folder}_compressed")) + + printer.info(f"Compressing \"{folder.replace(orig_folder, orig_folder.split('/').pop())}\" folder...") + compressor.compress(orig_folder, folder) utils.get_compression_status(orig_folder) diff --git a/FFMpeg-Compressor/modules/compressor.py b/FFMpeg-Compressor/modules/compressor.py index 0e83fee..72760cf 100644 --- a/FFMpeg-Compressor/modules/compressor.py +++ b/FFMpeg-Compressor/modules/compressor.py @@ -32,16 +32,16 @@ def has_transparency(img): return False -def compress(folder): +def compress(root_folder, folder): + target_folder = folder.replace(root_folder, f"{root_folder}_compressed") files = len(os.listdir(folder)) - progress = 0 for file in os.listdir(folder): if os.path.isfile(f'{folder}/{file}'): if os.path.splitext(file)[1] in audio_exts: bitrate = config['FFMPEG']['AudioBitRate'] - printer.files(int((progress / files) * 100), file, os.path.splitext(file)[0], req_audio_ext, f"{bitrate}bit/s") - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} '{folder}_compressed/{os.path.splitext(file)[0]}.{req_audio_ext}'") + printer.files(file, os.path.splitext(file)[0], req_audio_ext, f"{bitrate}bit/s") + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} '{target_folder}/{os.path.splitext(file)[0]}.{req_audio_ext}'") elif os.path.splitext(file)[1] in image_exts: @@ -49,25 +49,23 @@ def compress(folder): if not has_transparency(Image.open(f'{folder}/{file}')): jpg_comp = config['FFMPEG']['JpegComp'] - printer.files(int((progress / files) * 100), file, os.path.splitext(file)[0], req_image_ext, f"level {jpg_comp}") - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -q {jpg_comp} '{folder}_compressed/{os.path.splitext(file)[0]}.{req_image_ext}'") + printer.files(file, os.path.splitext(file)[0], req_image_ext, f"level {jpg_comp}") + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -q {jpg_comp} '{target_folder}/{os.path.splitext(file)[0]}.{req_image_ext}'") else: printer.warning(f"{file} has transparency (.jpg not support it). Skipping...") else: comp_level = config['FFMPEG']['CompLevel'] - printer.files(int((progress / files) * 100), file, os.path.splitext(file)[0], req_image_ext, f"{comp_level}%") - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -compression_level {comp_level} '{folder}_compressed/{os.path.splitext(file)[0]}.{req_image_ext}'") + printer.files(file, os.path.splitext(file)[0], req_image_ext, f"{comp_level}%") + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -compression_level {comp_level} '{target_folder}/{os.path.splitext(file)[0]}.{req_image_ext}'") elif os.path.splitext(file)[1] in video_exts: codec = config['FFMPEG']['VideoCodec'] - printer.files(int((progress / files) * 100), file, os.path.splitext(file)[0], req_video_ext, codec) - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -vcodec {codec} '{folder}_compressed/{os.path.splitext(file)[0]}.{req_video_ext}'") + printer.files(file, os.path.splitext(file)[0], req_video_ext, codec) + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -vcodec {codec} '{target_folder}/{os.path.splitext(file)[0]}.{req_video_ext}'") else: printer.warning("File extension not recognized. This may affect the quality of the compression.") - print(f"\r[{int((progress/files) * 100)}%] \033[0;33m{file}\033[0m") - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} '{folder}_compressed/{file}'") - - progress += 1 + printer.unknown_file(file) + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} '{target_folder}/{file}'") diff --git a/FFMpeg-Compressor/modules/printer.py b/FFMpeg-Compressor/modules/printer.py index 209f813..cd9f2b6 100644 --- a/FFMpeg-Compressor/modules/printer.py +++ b/FFMpeg-Compressor/modules/printer.py @@ -1,21 +1,38 @@ import os +from progress.bar import IncrementalBar + + +# Fill whole string with spaces for cleaning progress bar +def clean_str(string): + return string + " " * (os.get_terminal_size().columns - len(string)) + + +def bar_init(folder): + file_count = 0 + for folder, folders, file in os.walk(folder): + file_count += len(file) + global bar + bar = IncrementalBar('Compressing', max=file_count, suffix='[%(index)d/%(max)d] (%(percent).1f%%) - ETA: %(eta)ds') def info(string): - print(f"[INFO] \033[0;32m{string}\033[0m") + print(clean_str(f"\r\033[0;32m[INFO] \033[0m {string}" + " ")) -def files(progress, source, dest, dest_ext, comment): +def files(source, dest, dest_ext, comment): + source_ext = os.path.splitext(source)[1] - source_name= os.path.splitext(source)[0] + source_name = os.path.splitext(source)[0] - if progress < 10: - progress = f" {progress}" - elif progress < 100: - progress = f" {progress}" + print(clean_str(f"\r[COMP] \033[0;32m{source_name}\033[0m{source_ext}\033[0;32m -> {dest}\033[0m.{dest_ext}\033[0;32m ({comment})\033[0m")) + bar.next() - print(f"[{progress}%] \033[0;32m{source_name}\033[0m{source_ext}\033[0;32m -> {dest}\033[0m.{dest_ext}\033[0;32m ({comment})\033[0m") + +def unknown_file(file): + + print(clean_str(f"\r[COMP] \033[0;33m{file}\033[0m")) + bar.next() def warning(string): - print(f"\033[0;33m[WARNING] {string}\033[0m") \ No newline at end of file + print(clean_str(f"\r\033[0;33m[WARNING] {string}\033[0m")) diff --git a/FFMpeg-Compressor/modules/utils.py b/FFMpeg-Compressor/modules/utils.py index 8cc41e2..567348f 100644 --- a/FFMpeg-Compressor/modules/utils.py +++ b/FFMpeg-Compressor/modules/utils.py @@ -1,21 +1,21 @@ from modules import printer -import glob import os def get_dir_size(directory, files): total_size = 0 - for f in files: - fp = glob.glob(f'{directory}/{f}*')[0] - if not os.path.islink(fp): - total_size += os.path.getsize(fp) + for folder, folders, files in os.walk(directory): + for file in files: + if not os.path.islink(f"{folder}/{file}"): + total_size += os.path.getsize(f"{folder}/{file}") return total_size def get_compression(orig, comp): processed_files = [] - for file in os.listdir(comp): - processed_files.append(os.path.splitext(file)[0]) + for folder, folders, files in os.walk(comp): + for file in files: + processed_files.append(file) try: comp = 100 - int((get_dir_size(comp, processed_files) / get_dir_size(orig, processed_files)) * 100) @@ -32,13 +32,11 @@ def get_compression_status(orig_folder): orig_folder_len = 0 comp_folder_len = 0 - for file in os.listdir(orig_folder): - if os.path.isfile(f'{orig_folder}/{file}'): - orig_folder_len += 1 + for folder, folders, file in os.walk(orig_folder): + orig_folder_len += len(file) - for file in os.listdir(f'{orig_folder}_compressed'): - if os.path.isfile(f'{orig_folder}_compressed/{file}'): - comp_folder_len += 1 + for folder, folders, file in os.walk(f'{orig_folder}_compressed'): + comp_folder_len += len(file) if orig_folder_len == comp_folder_len: printer.info("Success!") diff --git a/FFMpeg-Compressor/requirements.txt b/FFMpeg-Compressor/requirements.txt new file mode 100644 index 0000000..290af37 --- /dev/null +++ b/FFMpeg-Compressor/requirements.txt @@ -0,0 +1,2 @@ +Pillow==9.5.0 +progress==1.6 diff --git a/RenPy-Android-Unpack/unpack.py b/RenPy-Android-Unpack/unpack.py index 1a89253..07cc074 100755 --- a/RenPy-Android-Unpack/unpack.py +++ b/RenPy-Android-Unpack/unpack.py @@ -20,7 +20,6 @@ def extract_assets(file): os.rename('assets/res/drawable/icon.png', 'assets/icon.png') - def rename_files(directory): for dir_ in os.walk(directory): for file in dir_[2]: From d74464a031a96233e1fff48aee14fc3910bbed3b Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Tue, 8 Aug 2023 16:33:25 +0300 Subject: [PATCH 06/10] FFMpeg-Compressor: UNIX binary --- .../{config.toml => ffmpeg-comp.toml} | 0 FFMpeg-Compressor/modules/compressor.py | 23 +++++++++++++------ FFMpeg-Compressor/modules/printer.py | 20 +++++++++------- FFMpeg-Compressor/modules/utils.py | 2 +- 4 files changed, 29 insertions(+), 16 deletions(-) rename FFMpeg-Compressor/{config.toml => ffmpeg-comp.toml} (100%) diff --git a/FFMpeg-Compressor/config.toml b/FFMpeg-Compressor/ffmpeg-comp.toml similarity index 100% rename from FFMpeg-Compressor/config.toml rename to FFMpeg-Compressor/ffmpeg-comp.toml diff --git a/FFMpeg-Compressor/modules/compressor.py b/FFMpeg-Compressor/modules/compressor.py index 72760cf..4d72056 100644 --- a/FFMpeg-Compressor/modules/compressor.py +++ b/FFMpeg-Compressor/modules/compressor.py @@ -7,8 +7,14 @@ audio_exts = ['.aac', '.flac', '.m4a', '.mp3', '.ogg', '.opus', '.raw', '.wav', image_exts = ['.apng', '.avif', '.jfif', '.pjpeg', '.pjp', '.svg', '.webp', '.jpg', '.jpeg', '.png', '.raw'] video_exts = ['.3gp' '.amv', '.avi', '.gif', '.m4v', '.mkv', '.mov', '.mp4', '.m4v', '.mpeg', '.mpv', '.webm', '.ogv'] -with open("config.toml", "rb") as f: - config = tomllib.load(f) +try: + config = tomllib.load(open("ffmpeg-comp.toml", "rb")) +except FileNotFoundError: + try: + config = tomllib.load(open("/etc/ffmpeg-comp.toml", "rb")) + except FileNotFoundError: + printer.error("Config file not found. Please put it next to binary or in to /etc folder.") + exit() ffmpeg_params = config['FFMPEG']['FFmpegParams'] req_audio_ext = config['FFMPEG']['AudioExt'] @@ -34,14 +40,14 @@ def has_transparency(img): def compress(root_folder, folder): target_folder = folder.replace(root_folder, f"{root_folder}_compressed") - files = len(os.listdir(folder)) for file in os.listdir(folder): if os.path.isfile(f'{folder}/{file}'): if os.path.splitext(file)[1] in audio_exts: bitrate = config['FFMPEG']['AudioBitRate'] printer.files(file, os.path.splitext(file)[0], req_audio_ext, f"{bitrate}bit/s") - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} '{target_folder}/{os.path.splitext(file)[0]}.{req_audio_ext}'") + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} " + f"'{target_folder}/{os.path.splitext(file)[0]}.{req_audio_ext}'") elif os.path.splitext(file)[1] in image_exts: @@ -50,7 +56,8 @@ def compress(root_folder, folder): if not has_transparency(Image.open(f'{folder}/{file}')): jpg_comp = config['FFMPEG']['JpegComp'] printer.files(file, os.path.splitext(file)[0], req_image_ext, f"level {jpg_comp}") - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -q {jpg_comp} '{target_folder}/{os.path.splitext(file)[0]}.{req_image_ext}'") + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -q {jpg_comp} " + f"'{target_folder}/{os.path.splitext(file)[0]}.{req_image_ext}'") else: printer.warning(f"{file} has transparency (.jpg not support it). Skipping...") @@ -58,12 +65,14 @@ def compress(root_folder, folder): else: comp_level = config['FFMPEG']['CompLevel'] printer.files(file, os.path.splitext(file)[0], req_image_ext, f"{comp_level}%") - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -compression_level {comp_level} '{target_folder}/{os.path.splitext(file)[0]}.{req_image_ext}'") + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -compression_level {comp_level} " + f"'{target_folder}/{os.path.splitext(file)[0]}.{req_image_ext}'") elif os.path.splitext(file)[1] in video_exts: codec = config['FFMPEG']['VideoCodec'] printer.files(file, os.path.splitext(file)[0], req_video_ext, codec) - os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -vcodec {codec} '{target_folder}/{os.path.splitext(file)[0]}.{req_video_ext}'") + os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -vcodec {codec} " + f"'{target_folder}/{os.path.splitext(file)[0]}.{req_video_ext}'") else: printer.warning("File extension not recognized. This may affect the quality of the compression.") diff --git a/FFMpeg-Compressor/modules/printer.py b/FFMpeg-Compressor/modules/printer.py index cd9f2b6..f735b01 100644 --- a/FFMpeg-Compressor/modules/printer.py +++ b/FFMpeg-Compressor/modules/printer.py @@ -7,6 +7,18 @@ def clean_str(string): return string + " " * (os.get_terminal_size().columns - len(string)) +def info(string): + print(clean_str(f"\r\033[0;32m[INFO]\033[0m {string}")) + + +def warning(string): + print(clean_str(f"\r\033[0;33m[WARNING]\033[0m {string}")) + + +def error(string): + print(clean_str(f"\r\033[0;31m[ERROR]\033[0m {string}")) + + def bar_init(folder): file_count = 0 for folder, folders, file in os.walk(folder): @@ -15,10 +27,6 @@ def bar_init(folder): bar = IncrementalBar('Compressing', max=file_count, suffix='[%(index)d/%(max)d] (%(percent).1f%%) - ETA: %(eta)ds') -def info(string): - print(clean_str(f"\r\033[0;32m[INFO] \033[0m {string}" + " ")) - - def files(source, dest, dest_ext, comment): source_ext = os.path.splitext(source)[1] @@ -32,7 +40,3 @@ def unknown_file(file): print(clean_str(f"\r[COMP] \033[0;33m{file}\033[0m")) bar.next() - - -def warning(string): - print(clean_str(f"\r\033[0;33m[WARNING] {string}\033[0m")) diff --git a/FFMpeg-Compressor/modules/utils.py b/FFMpeg-Compressor/modules/utils.py index 567348f..66f3b80 100644 --- a/FFMpeg-Compressor/modules/utils.py +++ b/FFMpeg-Compressor/modules/utils.py @@ -47,5 +47,5 @@ def get_compression_status(orig_folder): def help_message(): - text = "Usage: main.py {folder}" + text = "Usage: ffmpeg-comp {folder}" return text From 258619a1004d398a029d0f96434feb80c48c4afa Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Tue, 8 Aug 2023 16:46:52 +0300 Subject: [PATCH 07/10] Compilation script --- build.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..3eec12d --- /dev/null +++ b/build.sh @@ -0,0 +1,6 @@ +#!/bin/bash +mkdir output +mkdir output/bin +nuitka3 --jobs=$(nproc) --output-dir=output --follow-imports --output-filename=output/bin/ffmpeg-comp FFMpeg-Compressor/main.py +cp FFMpeg-Compressor/ffmpeg-comp.toml output/bin/ +nuitka3 --jobs=$(nproc) --output-dir=output --follow-imports --output-filename=output/bin/rendroid-unpack RenPy-Android-Unpack/unpack.py \ No newline at end of file From 3297a3720a4e09ba01a465240359c3cd5639fd46 Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Tue, 8 Aug 2023 17:02:11 +0300 Subject: [PATCH 08/10] FFMpeg-Compressor: Update README.md --- FFMpeg-Compressor/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/FFMpeg-Compressor/README.md b/FFMpeg-Compressor/README.md index 2704f0b..f30ceed 100644 --- a/FFMpeg-Compressor/README.md +++ b/FFMpeg-Compressor/README.md @@ -2,6 +2,7 @@ Python utility uses ffmpeg to compress Visual Novel Resources ### How to use -* Configure utitlity in `config.toml` -* `python main.py {folder}` +* Download `ffmpeg-comp.toml` and put in next to binary or in to `/etc` folder +* Change the configuration of the utility in `ffmpeg-comp.toml` for yourself +* `ffmpeg-comp {folder}` * In result you get `{folder-compressed}` near with original `{folder}` From 9e83954d1a75cfb4f325dcf1dfd1a015b5b4b053 Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Sat, 30 Sep 2023 19:41:29 +0300 Subject: [PATCH 09/10] FFMpeg-Compressor: Ignoring the slash at the end of the folder path --- FFMpeg-Compressor/main.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/FFMpeg-Compressor/main.py b/FFMpeg-Compressor/main.py index fba5cff..3a14022 100755 --- a/FFMpeg-Compressor/main.py +++ b/FFMpeg-Compressor/main.py @@ -8,12 +8,17 @@ import sys import os try: - orig_folder = sys.argv[1] - printer.orig_folder = sys.argv[1] + if sys.argv[1][len(sys.argv[1])-1] == "/": + arg_path = sys.argv[1][:len(sys.argv[1])-1] + else: + arg_path = sys.argv[1] except IndexError: print(utils.help_message()) exit() +orig_folder = arg_path +printer.orig_folder = arg_path + printer.bar_init(orig_folder) if os.path.exists(f"{orig_folder}_compressed"): From a7ed37d58cfc32b730362eeda2bbe44532965145 Mon Sep 17 00:00:00 2001 From: OleSTEEP Date: Sat, 30 Sep 2023 21:56:47 +0300 Subject: [PATCH 10/10] FFMpeg-Compressor: Restructure config file --- FFMpeg-Compressor/ffmpeg-comp.toml | 20 +++++++++++++------- FFMpeg-Compressor/modules/compressor.py | 14 +++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/FFMpeg-Compressor/ffmpeg-comp.toml b/FFMpeg-Compressor/ffmpeg-comp.toml index e927951..9f117bb 100644 --- a/FFMpeg-Compressor/ffmpeg-comp.toml +++ b/FFMpeg-Compressor/ffmpeg-comp.toml @@ -1,9 +1,15 @@ [FFMPEG] -AudioBitRate = "320k" -AudioExt = "mp3" -CompLevel = 20 -ImageExt = "jpg" -JpegComp = 3 FFmpegParams = "-hide_banner -loglevel error" -VideoCodec = "libvpx-vp9" -VideoExt = "webm" + +[AUDIO] +Extension = "mp3" +BitRate = "320k" + +[IMAGE] +Extension = "jpg" +CompLevel = 100 +JpegComp = 3 + +[VIDEO] +Extension = "webm" +Codec = "libvpx-vp9" diff --git a/FFMpeg-Compressor/modules/compressor.py b/FFMpeg-Compressor/modules/compressor.py index 4d72056..5f3d959 100644 --- a/FFMpeg-Compressor/modules/compressor.py +++ b/FFMpeg-Compressor/modules/compressor.py @@ -17,9 +17,9 @@ except FileNotFoundError: exit() ffmpeg_params = config['FFMPEG']['FFmpegParams'] -req_audio_ext = config['FFMPEG']['AudioExt'] -req_image_ext = config['FFMPEG']['ImageExt'] -req_video_ext = config['FFMPEG']['VideoExt'] +req_audio_ext = config['AUDIO']['Extension'] +req_image_ext = config['IMAGE']['Extension'] +req_video_ext = config['VIDEO']['Extension'] def has_transparency(img): @@ -44,7 +44,7 @@ def compress(root_folder, folder): if os.path.isfile(f'{folder}/{file}'): if os.path.splitext(file)[1] in audio_exts: - bitrate = config['FFMPEG']['AudioBitRate'] + bitrate = config['AUDIO']['BitRate'] printer.files(file, os.path.splitext(file)[0], req_audio_ext, f"{bitrate}bit/s") os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} " f"'{target_folder}/{os.path.splitext(file)[0]}.{req_audio_ext}'") @@ -54,7 +54,7 @@ def compress(root_folder, folder): if req_image_ext == "jpg" or req_image_ext == "jpeg": if not has_transparency(Image.open(f'{folder}/{file}')): - jpg_comp = config['FFMPEG']['JpegComp'] + jpg_comp = config['IMAGE']['JpegComp'] printer.files(file, os.path.splitext(file)[0], req_image_ext, f"level {jpg_comp}") os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -q {jpg_comp} " f"'{target_folder}/{os.path.splitext(file)[0]}.{req_image_ext}'") @@ -63,13 +63,13 @@ def compress(root_folder, folder): printer.warning(f"{file} has transparency (.jpg not support it). Skipping...") else: - comp_level = config['FFMPEG']['CompLevel'] + comp_level = config['IMAGE']['CompLevel'] printer.files(file, os.path.splitext(file)[0], req_image_ext, f"{comp_level}%") os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -compression_level {comp_level} " f"'{target_folder}/{os.path.splitext(file)[0]}.{req_image_ext}'") elif os.path.splitext(file)[1] in video_exts: - codec = config['FFMPEG']['VideoCodec'] + codec = config['VIDEO']['Codec'] printer.files(file, os.path.splitext(file)[0], req_video_ext, codec) os.system(f"ffmpeg -i '{folder}/{file}' {ffmpeg_params} -vcodec {codec} " f"'{target_folder}/{os.path.splitext(file)[0]}.{req_video_ext}'")