Compare commits

...

4 Commits

Author SHA1 Message Date
jlw4049
40baeb3c39 feat: update readme 2024-03-08 14:53:16 -05:00
jlw4049
f6a5d41dfe fix: need to be sure that these are both Path objects 2024-03-08 14:52:08 -05:00
jlw4049
63cbdc9663 feat: v1.2.0
refactor: removed --index-dir arg
feat: added --source-index-path and --encode-index-path, these are direct paths to the index file vs only having a directory to search
refactor: added a more descriptive help message for --subtitle-color
2024-03-08 13:46:53 -05:00
jlw4049
7118e49527 refactor: removed index_directory and replaced it with source_index_path and encode_index_path
feat: added a method to check_index_paths(), this function accurately detects the correct extension for the selected indexer
refactor: the default color is now set to a neon green color
feat: optimized code for indexing ffms2 and lsmash
feat: added the ability to accept direct paths to the index for both lsmash/ffms2
fix: fixed a potential bug when it came to creating an index that didn't exist
2024-03-08 13:45:20 -05:00
3 changed files with 166 additions and 143 deletions

@ -7,14 +7,13 @@ A CLI to generate comparison image sets with
``` ```
usage: FrameForge [-h] [-v] [--source SOURCE] [--encode ENCODE] [--frames FRAMES] usage: FrameForge [-h] [-v] [--source SOURCE] [--encode ENCODE] [--frames FRAMES]
[--image-dir IMAGE_DIR] [--indexer {lsmash,ffms2}] [--image-dir IMAGE_DIR] [--indexer {lsmash,ffms2}]
[--index-dir INDEX_DIR] [--sub-size SUB_SIZE] [--left-crop LEFT_CROP] [--source-index-path SOURCE_INDEX_PATH]
[--right-crop RIGHT_CROP] [--top-crop TOP_CROP] [--encode-index-path ENCODE_INDEX_PATH] [--sub-size SUB_SIZE]
[--left-crop LEFT_CROP] [--right-crop RIGHT_CROP] [--top-crop TOP_CROP]
[--bottom-crop BOTTOM_CROP] [--adv-resize-left ADV_RESIZE_LEFT] [--bottom-crop BOTTOM_CROP] [--adv-resize-left ADV_RESIZE_LEFT]
[--adv-resize-right ADV_RESIZE_RIGHT] [--adv-resize-right ADV_RESIZE_RIGHT] [--adv-resize-top ADV_RESIZE_TOP]
[--adv-resize-top ADV_RESIZE_TOP] [--adv-resize-bottom ADV_RESIZE_BOTTOM] [--tone-map] [--re-sync RE_SYNC]
[--adv-resize-bottom ADV_RESIZE_BOTTOM] [--tone-map] [--comparison-count COMPARISON_COUNT] [--subtitle-color SUBTITLE_COLOR]
[--re-sync RE_SYNC] [--comparison-count COMPARISON_COUNT]
[--subtitle-color SUBTITLE_COLOR]
[--release-sub-title RELEASE_SUB_TITLE] [--release-sub-title RELEASE_SUB_TITLE]
options: options:
@ -22,14 +21,16 @@ options:
-v, --version show program's version number and exit -v, --version show program's version number and exit
--source SOURCE Path to source file --source SOURCE Path to source file
--encode ENCODE Path to encode file --encode ENCODE Path to encode file
--frames FRAMES Only use this if you want to specify the frames to generate, --frames FRAMES Only use this if you want to specify the frames to generate, this
this disables sync frames disables sync frames
--image-dir IMAGE_DIR --image-dir IMAGE_DIR
Path to base image folder Path to base image folder
--indexer {lsmash,ffms2} --indexer {lsmash,ffms2}
Indexer choice Indexer choice
--index-dir INDEX_DIR --source-index-path SOURCE_INDEX_PATH
Path to look/create indexes Path to look/create indexes for source
--encode-index-path ENCODE_INDEX_PATH
Path to look/create indexes for encode
--sub-size SUB_SIZE Size of subtitles --sub-size SUB_SIZE Size of subtitles
--left-crop LEFT_CROP --left-crop LEFT_CROP
Left crop Left crop
@ -51,10 +52,9 @@ options:
--comparison-count COMPARISON_COUNT --comparison-count COMPARISON_COUNT
Amount of comparisons to generate Amount of comparisons to generate
--subtitle-color SUBTITLE_COLOR --subtitle-color SUBTITLE_COLOR
Hex color code for subtitle color Hex color code for subtitle color (i.e. --subtitle-color "#fff000")
--release-sub-title RELEASE_SUB_TITLE --release-sub-title RELEASE_SUB_TITLE
Release group subtitle name (this will show on the encode Release group subtitle name (this will show on the encode images)
images)
``` ```
## Supports ## Supports

@ -7,7 +7,7 @@ from frame_forge.cli_utils import frame_list
program_name = "FrameForge" program_name = "FrameForge"
__version__ = "1.1.0" __version__ = "1.2.0"
if __name__ == "__main__": if __name__ == "__main__":
@ -30,9 +30,15 @@ if __name__ == "__main__":
"--indexer", "--indexer",
type=str, type=str,
choices=["lsmash", "ffms2"], choices=["lsmash", "ffms2"],
default="lsmash",
help="Indexer choice", help="Indexer choice",
) )
parser.add_argument("--index-dir", type=str, help="Path to look/create indexes") parser.add_argument(
"--source-index-path", type=str, help="Path to look/create indexes for source"
)
parser.add_argument(
"--encode-index-path", type=str, help="Path to look/create indexes for encode"
)
parser.add_argument("--sub-size", type=int, default=20, help="Size of subtitles") parser.add_argument("--sub-size", type=int, default=20, help="Size of subtitles")
parser.add_argument("--left-crop", type=int, help="Left crop") parser.add_argument("--left-crop", type=int, help="Left crop")
parser.add_argument("--right-crop", type=int, help="Right crop") parser.add_argument("--right-crop", type=int, help="Right crop")
@ -54,7 +60,9 @@ if __name__ == "__main__":
"--comparison-count", type=int, help="Amount of comparisons to generate" "--comparison-count", type=int, help="Amount of comparisons to generate"
) )
parser.add_argument( parser.add_argument(
"--subtitle-color", type=str, help="Hex color code for subtitle color" "--subtitle-color",
type=str,
help='Hex color code for subtitle color (i.e. --subtitle-color "#fff000")',
) )
parser.add_argument( parser.add_argument(
"--release-sub-title", "--release-sub-title",
@ -80,6 +88,16 @@ if __name__ == "__main__":
1, 1,
) )
index_suffix = ".lwi" if args.indexer == "lsmash" else ".ffindex"
for index_input in [args.source_index_path, args.encode_index_path]:
if index_input:
if Path(index_input).suffix != index_suffix:
exit_application(
f"When using {args.indexer} indexer you must use '{index_suffix}' "
"for your source/encode index path suffix",
1,
)
if args.image_dir: if args.image_dir:
image_dir = Path(args.image_dir) image_dir = Path(args.image_dir)
else: else:
@ -93,7 +111,8 @@ if __name__ == "__main__":
frames=args.frames, frames=args.frames,
image_dir=image_dir, image_dir=image_dir,
indexer=args.indexer, indexer=args.indexer,
index_directory=args.index_dir, source_index_path=args.source_index_path,
encode_index_path=args.encode_index_path,
sub_size=args.sub_size, sub_size=args.sub_size,
left_crop=args.left_crop, left_crop=args.left_crop,
right_crop=args.right_crop, right_crop=args.right_crop,

@ -4,6 +4,7 @@ from random import choice
from pathlib import Path from pathlib import Path
from numpy import linspace from numpy import linspace
from unidecode import unidecode from unidecode import unidecode
import awsmfunc import awsmfunc
import vapoursynth as vs import vapoursynth as vs
from frame_forge.exceptions import FrameForgeError from frame_forge.exceptions import FrameForgeError
@ -18,7 +19,8 @@ class GenerateImages:
frames: str, frames: str,
image_dir: Path, image_dir: Path,
indexer: str, indexer: str,
index_directory: None | str, source_index_path: None | str,
encode_index_path: None | str,
sub_size: int, sub_size: int,
left_crop: int, left_crop: int,
right_crop: int, right_crop: int,
@ -42,7 +44,8 @@ class GenerateImages:
self.encode_node = None self.encode_node = None
self.image_dir = image_dir self.image_dir = image_dir
self.indexer = indexer self.indexer = indexer
self.index_dir = index_directory self.source_index_path = source_index_path
self.encode_index_path = encode_index_path
self.sub_size = sub_size self.sub_size = sub_size
self.left_crop = left_crop self.left_crop = left_crop
self.right_crop = right_crop self.right_crop = right_crop
@ -62,6 +65,8 @@ class GenerateImages:
self.load_plugins() self.load_plugins()
def process_images(self): def process_images(self):
self.check_index_paths()
if self.indexer == "lsmash": if self.indexer == "lsmash":
self.index_lsmash() self.index_lsmash()
@ -77,7 +82,7 @@ class GenerateImages:
# Shadow Depth, Alignment, Left Margin, Right Margin, Vertical Margin, Encoding # Shadow Depth, Alignment, Left Margin, Right Margin, Vertical Margin, Encoding
# bgr color # bgr color
color = "&H000ac7f5" color = "&H14FF39"
if self.subtitle_color: if self.subtitle_color:
color = hex_to_bgr(self.subtitle_color) color = hex_to_bgr(self.subtitle_color)
@ -478,10 +483,9 @@ class GenerateImages:
flush=True, flush=True,
) )
def index_lsmash(self): def _index_source_lsmash(self):
print("Indexing source", flush=True) print("Indexing source", flush=True)
# index source file
# if index is found in the StaxRip temp working directory, attempt to use it # if index is found in the StaxRip temp working directory, attempt to use it
if ( if (
Path(str(Path(self.source_file).with_suffix("")) + "_temp/").is_dir() Path(str(Path(self.source_file).with_suffix("")) + "_temp/").is_dir()
@ -491,152 +495,134 @@ class GenerateImages:
): ):
print("Index found in StaxRip temp, attempting to use", flush=True) print("Index found in StaxRip temp, attempting to use", flush=True)
# define cache path
lwi_cache_path = Path( lwi_cache_path = Path(
str(Path(self.source_file).with_suffix("")) + "_temp/temp.lwi" str(Path(self.source_file).with_suffix("")) + "_temp/temp.lwi"
) )
# try to use index on source file with the cache path elif self.source_index_path.exists():
try: print("Index found, attempting to use", flush=True)
self.source_node = self.core.lsmas.LWLibavSource( lwi_cache_path = self.source_index_path
source=self.source_file, cachefile=lwi_cache_path
)
self.reference_source_file = self.core.lsmas.LWLibavSource(
source=self.source_file, cachefile=lwi_cache_path
)
print("Using existing index", flush=True)
# if index cannot be used
except vs.Error:
print("L-Smash version miss-match, indexing source again", flush=True)
# index source file
self.source_node = self.core.lsmas.LWLibavSource(self.source_file)
self.reference_source_file = self.core.lsmas.LWLibavSource(
self.source_file
)
# if no existing index is found index source file # if no existing index is found index source file
else: else:
cache_path = Path(Path(self.source_file).with_suffix(".lwi")) lwi_cache_path = Path(Path(self.source_file).with_suffix(".lwi"))
try:
# create index
self.source_node = self.core.lsmas.LWLibavSource(
self.source_file, cachefile=cache_path
)
self.reference_source_file = self.core.lsmas.LWLibavSource(
self.source_file, cachefile=cache_path
)
except vs.Error:
# delete index
Path(self.source_file).with_suffix(".lwi").unlink(missing_ok=True)
# create index
self.source_node = self.core.lsmas.LWLibavSource(
self.source_file, cachefile=cache_path
)
self.reference_source_file = self.core.lsmas.LWLibavSource(
self.source_file, cachefile=cache_path
)
print("Source index completed\n\nIndexing encode", flush=True) try:
self.source_node = self.core.lsmas.LWLibavSource(
source=self.source_file, cachefile=lwi_cache_path
)
self.reference_source_file = self.core.lsmas.LWLibavSource(
source=self.source_file, cachefile=lwi_cache_path
)
print("Using existing index", flush=True)
except vs.Error:
print("L-Smash version miss-match, indexing source again", flush=True)
self.source_node = self.core.lsmas.LWLibavSource(self.source_file)
self.reference_source_file = self.core.lsmas.LWLibavSource(self.source_file)
# define a path for encode index to go print("Source index completed", flush=True)
if self.index_dir:
index_base_path = Path(self.index_dir) / Path(self.encode_file).name def _index_encode_lsmash(self):
cache_path_enc = index_base_path.with_suffix(".lwi") print("\nIndexing encode", flush=True)
if self.encode_index_path:
cache_path_enc = self.encode_index_path
else: else:
cache_path_enc = Path(Path(self.encode_file).with_suffix(".lwi")) cache_path_enc = Path(Path(self.encode_file).with_suffix(".lwi"))
try: try:
# create index
self.encode_node = self.core.lsmas.LWLibavSource( self.encode_node = self.core.lsmas.LWLibavSource(
self.encode_file, cachefile=cache_path_enc self.encode_file, cachefile=cache_path_enc
) )
except vs.Error: except vs.Error:
# delete index
cache_path_enc.unlink(missing_ok=True) cache_path_enc.unlink(missing_ok=True)
# create index
self.encode_node = self.core.lsmas.LWLibavSource( self.encode_node = self.core.lsmas.LWLibavSource(
self.encode_file, cachefile=cache_path_enc self.encode_file, cachefile=cache_path_enc
) )
print("Encode index completed", flush=True) print("Encode index completed", flush=True)
def index_lsmash(self):
"""Index source/encode with lsmash"""
self._index_source_lsmash()
self._index_encode_lsmash()
def _index_source_ffms2(self):
print("Indexing source", flush=True)
# if index is found in the StaxRip temp working directory, attempt to use it
if (
Path(str(Path(self.source_file).with_suffix("")) + "_temp/").is_dir()
and Path(
str(Path(self.source_file).with_suffix("")) + "_temp/temp.ffindex"
).is_file()
):
print("Index found in StaxRip temp, attempting to use", flush=True)
ffindex_cache_path = Path(
str(Path(self.source_file).with_suffix("")) + "_temp/temp.ffindex"
)
elif self.source_index_path.exists():
print("Index found, attempting to use", flush=True)
ffindex_cache_path = self.source_index_path
# if no existing index is found index source file
else:
ffindex_cache_path = Path(Path(self.source_file).with_suffix(".ffindex"))
print(
"FFMS2 library doesn't allow progress, please wait while the index is completed",
flush=True,
)
try:
self.source_node = self.core.ffms2.Source(
self.source_file, cachefile=ffindex_cache_path
)
self.reference_source_file = self.core.ffms2.Source(
self.source_file, cachefile=ffindex_cache_path
)
except vs.Error:
Path(self.source_file).with_suffix(".ffindex").unlink(missing_ok=True)
print(
"FFMS2 library doesn't allow progress, please wait while the index is completed",
flush=True,
)
self.source_node = self.core.ffms2.Source(
self.source_file, cachefile=ffindex_cache_path
)
self.reference_source_file = self.core.ffms2.Source(
self.source_file, cachefile=ffindex_cache_path
)
print("Source index completed", flush=True)
def _index_encode_ffms2(self):
print("\nIndexing encode", flush=True)
if self.encode_index_path:
cache_path_enc = self.encode_index_path
else:
cache_path_enc = Path(str(self.encode_file) + ".ffindex")
try:
self.encode_node = self.core.ffms2.Source(
self.encode_file, cachefile=cache_path_enc
)
except vs.Error:
cache_path_enc.unlink(missing_ok=True)
self.encode_node = self.core.ffms2.Source(
self.encode_file, cachefile=cache_path_enc
)
print("Encode index completed", flush=True)
def index_ffms2(self): def index_ffms2(self):
print("Indexing source", flush=True) """Index source/encode with ffms2"""
# index source file self._index_source_ffms2()
# if index is found in the StaxRip temp working directory, attempt to use it self._index_encode_ffms2()
if (
Path(str(Path(self.source_file).with_suffix("")) + "_temp/").is_dir()
and Path(
str(Path(self.source_file).with_suffix("")) + "_temp/temp.ffindex"
).is_file()
):
print("Index found in StaxRip temp, attempting to use", flush=True)
# define cache path
ffindex_cache_path = Path(
str(Path(self.source_file).with_suffix("")) + "_temp/temp.ffindex"
)
# try to use index on source file with the cache path
try:
self.source_node = self.core.ffms2.Source(
source=self.source_file, cachefile=ffindex_cache_path
)
self.reference_source_file = self.core.ffms2.Source(
source=self.source_file, cachefile=ffindex_cache_path
)
print("Using existing index", flush=True)
# if index cannot be used
except vs.Error:
print("FFMS2 version miss-match, indexing source again", flush=True)
# index source file
self.source_node = self.core.ffms2.Source(self.source_file)
self.reference_source_file = self.core.ffms2.Source(self.source_file)
# if no existing index is found index source file
else:
try:
# create index
print(
"FFMS2 library doesn't allow progress, please wait while the index is completed",
flush=True,
)
self.source_node = self.core.ffms2.Source(self.source_file)
self.reference_source_file = self.core.ffms2.Source(self.source_file)
except vs.Error:
# delete index
Path(self.source_file).with_suffix(".ffindex").unlink(missing_ok=True)
# create index
print(
"FFMS2 library doesn't allow progress, please wait while the index is completed",
flush=True,
)
self.source_node = self.core.ffms2.Source(self.source_file)
self.reference_source_file = self.core.ffms2.Source(self.source_file)
print("Source index completed\n\nIndexing encode", flush=True)
# define a path for encode index to go
if self.index_dir:
index_base_path = Path(self.index_dir) / Path(self.encode_file).name
cache_path_enc = Path(str(index_base_path) + ".ffindex")
else:
cache_path_enc = Path(self.encode_file + ".ffindex")
try:
self.encode_node = self.core.ffms2.Source(
self.encode_file, cachefile=cache_path_enc
)
except vs.Error:
cache_path_enc.unlink(missing_ok=True)
self.encode_node = self.core.ffms2.Source(
self.encode_file, cachefile=cache_path_enc
)
print("Encode index completed", flush=True)
def load_plugins(self): def load_plugins(self):
plugin_path = get_working_dir() / "img_plugins" plugin_path = get_working_dir() / "img_plugins"
@ -645,3 +631,21 @@ class GenerateImages:
else: else:
for plugin in plugin_path.glob("*.dll"): for plugin in plugin_path.glob("*.dll"):
self.core.std.LoadPlugin(Path(plugin).resolve()) self.core.std.LoadPlugin(Path(plugin).resolve())
def check_index_paths(self):
indexer_ext = ".lwi" if self.indexer == "lsmash" else ".ffindex"
if not self.source_index_path or not Path(self.source_index_path).exists():
source_path_obj = Path(self.source_file)
self.source_index_path = source_path_obj.parent / Path(
f"{source_path_obj.stem}{indexer_ext}"
)
else:
self.source_index_path = Path(self.source_index_path)
if not self.encode_index_path or not Path(self.encode_index_path).exists():
encode_path_obj = Path(self.source_file)
self.encode_index_path = encode_path_obj.parent / Path(
f"{encode_path_obj.stem}{indexer_ext}"
)
else:
self.encode_index_path = Path(self.encode_index_path)