From e70ea811c99c16f3382c08153eda573df0825536 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Thu, 18 Oct 2018 19:19:56 +0200 Subject: Implement support for .avi files, via ffmpeg - This commit introduces optional dependencies (namely ffmpeg): mat2 will spit a warning when trying to process an .avi file if ffmpeg isn't installed. - Since metadata are obtained via exiftool, this commit also refactors a bit our exfitool wrapper. --- libmat2/exiftool.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 libmat2/exiftool.py (limited to 'libmat2/exiftool.py') diff --git a/libmat2/exiftool.py b/libmat2/exiftool.py new file mode 100644 index 0000000..e17d31b --- /dev/null +++ b/libmat2/exiftool.py @@ -0,0 +1,61 @@ +import json +import os +import re +import shutil +import subprocess +import tempfile + +from typing import Dict, Union, Set + +from . import abstract + +# Make pyflakes happy +assert Set + + +class ExiftoolParser(abstract.AbstractParser): + """ Exiftool is often the easiest way to get all the metadata + from a import file, hence why several parsers are re-using its `get_meta` + method. + """ + meta_whitelist = set() # type: Set[str] + + @staticmethod + def __handle_problematic_filename(filename: str, callback) -> bytes: + """ This method takes a filename with a problematic name, + and safely applies it a `callback`.""" + tmpdirname = tempfile.mkdtemp() + fname = os.path.join(tmpdirname, "temp_file") + shutil.copy(filename, fname) + out = callback(fname) + shutil.rmtree(tmpdirname) + return out + + def get_meta(self) -> Dict[str, Union[str, dict]]: + """ There is no way to escape the leading(s) dash(es) of the current + self.filename to prevent parameter injections, so we need to take care + of this. + """ + fun = lambda f: subprocess.check_output([_get_exiftool_path(), '-json', f]) + if re.search('^[a-z0-9/]', self.filename) is None: + out = self.__handle_problematic_filename(self.filename, fun) + else: + out = fun(self.filename) + meta = json.loads(out.decode('utf-8'))[0] + for key in self.meta_whitelist: + meta.pop(key, None) + return meta + +def _get_exiftool_path() -> str: # pragma: no cover + exiftool_path = '/usr/bin/exiftool' + if os.path.isfile(exiftool_path): + if os.access(exiftool_path, os.X_OK): + return exiftool_path + + # ArchLinux + exiftool_path = '/usr/bin/vendor_perl/exiftool' + if os.path.isfile(exiftool_path): + if os.access(exiftool_path, os.X_OK): + return exiftool_path + + raise RuntimeError("Unable to find exiftool") -- cgit v1.3