|
|
@@ -1,13 +1,14 @@
|
|
|
#!/usr/bin/env python3
|
|
|
-import sys, re, os, subprocess, pathlib, xattr, langcodes, logging
|
|
|
-import probe
|
|
|
+import sys, re, os, subprocess, pathlib, logging
|
|
|
+import langcodes
|
|
|
+import tag, probe
|
|
|
|
|
|
# Static config
|
|
|
debug = False
|
|
|
propedit_exec = 'mkvpropedit'
|
|
|
-mux_xattr = 'zib.mux'
|
|
|
+mux_tag = 'zib.mux'
|
|
|
mux_vers = 1
|
|
|
-lang_xattr = 'zib.lang'
|
|
|
+lang_tag = 'zib.lang'
|
|
|
lang_vers = 1
|
|
|
lang_default = 'eng'
|
|
|
lang_codecs = [ 'subtitle', 'audio' ]
|
|
|
@@ -32,8 +33,6 @@ meta_default = {
|
|
|
# ENV config
|
|
|
if 'DEBUG' in os.environ:
|
|
|
debug = bool(os.environ['DEBUG'])
|
|
|
-if 'PROPEDIT' in os.environ:
|
|
|
- propedit_exec = Pathlib.path(os.environ['PROPEDIT'])
|
|
|
|
|
|
# CLI config
|
|
|
if len(sys.argv) < 2:
|
|
|
@@ -42,12 +41,16 @@ if len(sys.argv) < 2:
|
|
|
root = pathlib.Path(sys.argv[1])
|
|
|
|
|
|
# Logging
|
|
|
-logger = logging.getLogger(__name__)
|
|
|
+logger = logging.getLogger('remux')
|
|
|
if debug:
|
|
|
logging.basicConfig(level=logging.DEBUG, stream=sys.stderr)
|
|
|
else:
|
|
|
logging.basicConfig(level=logging.WARN, stream=sys.stderr)
|
|
|
|
|
|
+# Tag and probe init
|
|
|
+tags = tag.tag()
|
|
|
+probes = probe.ffprobe()
|
|
|
+
|
|
|
# Build filename-metadata parsing regex
|
|
|
re_media = re.compile(
|
|
|
r'^(.*?)' +
|
|
|
@@ -57,26 +60,6 @@ re_media = re.compile(
|
|
|
re.IGNORECASE
|
|
|
)
|
|
|
|
|
|
-def read_xattr(path, attr):
|
|
|
- value = None
|
|
|
- try:
|
|
|
- if attr in xattr.listxattr(path):
|
|
|
- value = int.from_bytes(xattr.getxattr(path, attr))
|
|
|
- logger.debug(f"got xattr: {attr} => {value}")
|
|
|
- except BaseException as e:
|
|
|
- logger.error(f"xattr error ({attr}): {e}")
|
|
|
- return value
|
|
|
-
|
|
|
-def write_xattr(path, attr, value):
|
|
|
- error = True
|
|
|
- try:
|
|
|
- xattr.setxattr(path, attr, value.to_bytes())
|
|
|
- error = False
|
|
|
- logger.debug(f"set xattr: {attr} => {value}")
|
|
|
- except BaseException as e:
|
|
|
- logger.error(f"xattr error ({attr}): {e}")
|
|
|
- return not error
|
|
|
-
|
|
|
def scan(files):
|
|
|
logger.debug(f"Scanning {len(files)} files")
|
|
|
media = []
|
|
|
@@ -88,38 +71,35 @@ def scan(files):
|
|
|
info['name'] = file
|
|
|
|
|
|
# Parse media paths
|
|
|
- try:
|
|
|
- m = re_media.search(info['name'])
|
|
|
- if m and len(m.groups()) == 4:
|
|
|
- info['group'] = m.group(1)
|
|
|
+ m = re_media.search(info['name'])
|
|
|
+ if m and len(m.groups()) == 4:
|
|
|
+ info['group'] = m.group(1)
|
|
|
|
|
|
- try:
|
|
|
- lang = langcodes.Language.get(m.group(2).lower())
|
|
|
- info['lang'] = lang.to_alpha3()
|
|
|
- except:
|
|
|
- if m.group(2):
|
|
|
- logger.warning(f"Unable to match language code: {m.group(2)}")
|
|
|
+ try:
|
|
|
+ lang = langcodes.Language.get(m.group(2).lower())
|
|
|
+ info['lang'] = lang.to_alpha3()
|
|
|
+ except:
|
|
|
+ if m.group(2):
|
|
|
+ logger.warning(f"Unable to match language code: {m.group(2)}")
|
|
|
|
|
|
- if m.group(3):
|
|
|
- info['sdh'] = m.group(3).lower() in subs_sdh
|
|
|
+ if m.group(3):
|
|
|
+ info['sdh'] = m.group(3).lower() in subs_sdh
|
|
|
|
|
|
- info['ext'] = m.group(4).lower()
|
|
|
- except BaseException as e:
|
|
|
- logger.error(f"Skipping file due to name error ({info['name']}): {e}")
|
|
|
- continue
|
|
|
+ info['ext'] = m.group(4).lower()
|
|
|
+ del m
|
|
|
|
|
|
- # Skip non-media files
|
|
|
+ # Skip non-media files (and parsing errors)
|
|
|
if 'ext' not in info:
|
|
|
logger.debug(f"Skipping non-media file: {info['name']}")
|
|
|
continue
|
|
|
|
|
|
- # Read xattrs
|
|
|
- info['mux_vers'] = read_xattr(info['path'], mux_xattr)
|
|
|
- info['lang_vers'] = read_xattr(info['path'], lang_xattr)
|
|
|
+ # Read tags
|
|
|
+ info['mux_vers'] = tags.get_int(info['path'], mux_tag)
|
|
|
+ info['lang_vers'] = tags.get_int(info['path'], lang_tag)
|
|
|
|
|
|
# Loop end
|
|
|
media.append(info)
|
|
|
- logger.debug(f"Found media: {info}")
|
|
|
+ logger.debug(f"Found file: {info}")
|
|
|
|
|
|
# Return
|
|
|
return media
|
|
|
@@ -204,8 +184,8 @@ def mux(media):
|
|
|
logger.error(f"Mux error ({err}):\n{merge.stdout.decode('utf-8')}")
|
|
|
continue
|
|
|
|
|
|
- # Set xattr
|
|
|
- if not write_xattr(temp, mux_xattr, mux_vers):
|
|
|
+ # Set tag
|
|
|
+ if not tags.set_int(temp, mux_tag, mux_vers):
|
|
|
continue
|
|
|
|
|
|
# Remove sources
|
|
|
@@ -255,7 +235,7 @@ def lang(media):
|
|
|
continue
|
|
|
|
|
|
# Probe streams
|
|
|
- streams = probe.probe(file['path'])
|
|
|
+ streams = probes.probe(file['path'])
|
|
|
for stream in streams:
|
|
|
if not 'index' in stream:
|
|
|
logger.error(f"No index for stream ({file['name']}): {stream}")
|
|
|
@@ -285,8 +265,8 @@ def lang(media):
|
|
|
logger.error(f"propedit error ({propedit.returncode}): {propedit.stdout.decode('utf-8')}")
|
|
|
continue
|
|
|
|
|
|
- # Set xattr
|
|
|
- if not write_xattr(file['path'], lang_xattr, lang_vers):
|
|
|
+ # Set tag
|
|
|
+ if not tags.set_int(file['path'], lang_tag, lang_vers):
|
|
|
continue
|
|
|
file['lang_vers'] = lang_vers
|
|
|
|