"""Custom methods for validation of audio metadata.""" from src.constants import audio_standards from src.common.constants import transcoding_types import trafaret as t INVALID_INPUT_VALUE_ERROR_MESSAGE = 'Invalid input value {value} for {name}.' \ ' Expected value(s): {expected}' def sample_rate_validation(audio_meta): """Validate sample_rate value for default schema. Args: audio_meta (dict): input audio metadata. { 'sample_rate': 44100, 'bits_per_sample': 16 } Returns: dict: sample_rate value or trafaret.DataError exception. """ bits_per_sample = audio_meta['bits_per_sample'] sample_rate = audio_meta['sample_rate'] if bits_per_sample not in audio_standards.ALLOWED_SAMPLE_RATES: error_message = INVALID_INPUT_VALUE_ERROR_MESSAGE.format( name='bits_per_sample', expected=list(audio_standards.ALLOWED_SAMPLE_RATES.keys()), value=audio_meta['bits_per_sample'] ) return {'sample_rate': t.DataError(error_message)} available_sample_rates = ( audio_standards.ALLOWED_SAMPLE_RATES[bits_per_sample]) if sample_rate not in available_sample_rates: error_message = INVALID_INPUT_VALUE_ERROR_MESSAGE.format( name='sample_rate', expected=available_sample_rates, value=audio_meta['sample_rate'] ) return {'sample_rate': t.DataError(error_message)} return {'sample_rate': sample_rate} def wav_bit_rate_validation(audio_meta): """Validate bitrate value for wav schema. Args: audio_meta (dict): input audio metadata. { 'bitrate': 1411318, 'bits_per_sample': 16, 'channels': 2, 'sample_rate': 44100, 'container': 'wave' } Returns: dict: bit_rate value or trafaret.DataError exception. """ expected_bit_rate = ( audio_meta['channels'] * audio_meta['sample_rate'] * audio_meta['bits_per_sample'] ) is_wave = (audio_meta['container'] == transcoding_types.CONTAINER_WAVE) if is_wave and audio_meta['bit_rate'] != expected_bit_rate: error_message = INVALID_INPUT_VALUE_ERROR_MESSAGE.format( name='bit_rate', expected=expected_bit_rate, value=audio_meta['bit_rate'] ) return {'bit_rate': t.DataError(error_message)} return {'bit_rate': audio_meta['bit_rate']} def wav_file_size_validation(audio_meta): """Validate file_size value for wav schema. Args: audio_meta (dict): input audio metadata. { 'file_size': 2560000, 'playtime_seconds': 12000, # ms 'container': 'wave' } Returns: dict: file_size value or trafaret.DataError exception. """ file_size_minimum = ( audio_standards.FILE_SIZE_PER_SECOND * (audio_meta['playtime_seconds'] / 1000) ) is_wave = (audio_meta['container'] == transcoding_types.CONTAINER_WAVE) if is_wave and (file_size_minimum > audio_meta['file_size']): expected_file_size_msg = 'greater than {}'.format(file_size_minimum) error_message = INVALID_INPUT_VALUE_ERROR_MESSAGE.format( name='file_size', expected=expected_file_size_msg, value=audio_meta['file_size'] ) return {'file_size': t.DataError(error_message)} return {'file_size': audio_meta['file_size']} def bits_per_sample_validation(audio_meta): """Validate bits_per_sample value for all schema. Args: audio_meta (dict): input audio metadata. { 'bits_per_sample': 16, 'container': 'wave' } Returns: dict: bits_per_sample value or trafaret.DataError exception. """ is_aac = (audio_meta['container'] in [transcoding_types.CONTAINER_MPEG4, transcoding_types.CONTAINER_MPEG3]) if is_aac: return {'bits_per_sample': 16} bits_per_sample = audio_meta['bits_per_sample'] if bits_per_sample not in [16, 24]: expected_bits_per_sample_msg = 'not equal to 16 or 24 bits per sample' error_message = INVALID_INPUT_VALUE_ERROR_MESSAGE.format( name='bits_per_sample', expected=expected_bits_per_sample_msg, value=audio_meta['bits_per_sample'] ) return {'bits_per_sample': t.DataError(error_message)} return {'bits_per_sample': audio_meta['bits_per_sample']}