"""Media metadata extraction module.""" from functools import reduce import subprocess from . import common_config from .common_config import logger from .constants import errors from .constants import mediainfo_const def get_audio_asset_media_info(file_path): """Collect all information about audio media file using mediainfo. Args: file_path (str): path to file or url. Returns: dict: dictionary with full mediainfo output. """ info = [] for cli_filter in mediainfo_const.CLI_FILTERS: mediainfo_result_by_flag = get_media_info(file_path, cli_filter) info.append(mediainfo_result_by_flag) # extract all dictionaries key/values pairs to one dictionary result_dict = reduce((lambda x, y: dict(x, **y)), info) return result_dict def get_media_info(file_path, filter_pattern): """Get mediainfo output for file by filter pattern. Args: file_path (str): File path or url. filter_pattern (str): String pattern for grabbing mediainfo results. Returns: dict: Mediainfo output parsed by filter_pattern. Raises: RuntimeError: Unable to read asset file technical and tag data. OSError: Any error occurred during meadiainfo work. """ try: media_info_binary_data = subprocess.check_output( [common_config.MEDIAINFO_PATH, filter_pattern, file_path]) except OSError as e: logger.exception(str(e)) raise if not media_info_binary_data: raise RuntimeError(errors.ERROR_MEDIAINFO_EMPTY_OUTPUT_MESSAGE) media_info = ( media_info_binary_data.decode('utf-8').replace('\n', '')) # split info unit by key and value split_data = map(lambda s: s.split(' ', 1), media_info.split(' * ')) # type casting unready_res = {ld[0].lower(): ld[1].lower() if len(ld) > 1 else None for ld in split_data} result_dict = {k: type_cast(k, v) for k, v in unready_res.items()} return result_dict def type_cast(key, value): """Cast type of output value from mediainfo. Args: key (str): result key for mediainfo cli output value (str): result value Returns: str or int: return casted value """ if key in mediainfo_const.NUMERIC_FIELDS: if '/' in value: value = value.split('/')[0] if value == '': value = 0 return int(value) return value