"""Test extract_metadata.""" from unittest.mock import NonCallableMagicMock from pymediainfo import MediaInfo import pytest from video.connectors import s3 as s3_connector from video.constants import job_io_fields from video.logic.activities import extract_metadata from video.models import ows_video container_fields = { 'count_of_audio_streams': '1', 'count_of_video_streams': '1', 'format': 'test_format', 'format_profile': 'test_format_profile', } video_stream_fields = { 'format': 'test_format', 'format_profile': 'test_format_profile', 'width': '1234', 'height': '2345', 'bit_rate': '112233', 'duration': '223344.3', 'frame_rate': '25.2', 'pixel_aspect_ratio': '1.234', } audio_stream_fields = { 'format': 'test_format', 'format_profile': 'test_format_profile', 'format_additionalfeatures': 'test_format_additionalfeatures', 'bit_rate': '456789', 'bit_depth': '13', 'duration': '225588.9', 'channel_s': '2', 'channel_layout': 'test_channel_layout', 'sampling_rate': '65421', } expected_container_fields = { job_io_fields.NUM_VIDEO_STREAMS: 1, job_io_fields.NUM_AUDIO_STREAMS: 1, job_io_fields.CONTAINER_FORMAT: 'test_format', job_io_fields.CONTAINER_FORMAT_PROFILE: 'test_format_profile', } expected_video_stream_fields = { job_io_fields.VIDEO_STREAM_CODEC: 'test_format', job_io_fields.VIDEO_STREAM_CODEC_PROFILE: 'test_format_profile', job_io_fields.VIDEO_STREAM_WIDTH_PIXELS: 1234, job_io_fields.VIDEO_STREAM_HEIGHT_PIXELS: 2345, job_io_fields.VIDEO_STREAM_BIT_RATE_BITS_PER_SECOND: 112233, job_io_fields.VIDEO_STREAM_DURATION_SECONDS: 223.3443, job_io_fields.VIDEO_STREAM_FRAME_RATE_FRAMES_PER_SECOND: 25.2, job_io_fields.VIDEO_STREAM_PIXEL_ASPECT_RATIO: 1.234, } expected_audio_stream_fields = { job_io_fields.AUDIO_STREAM_CODEC: 'test_format', job_io_fields.AUDIO_STREAM_CODEC_PROFILE: 'test_format_profile', job_io_fields.AUDIO_STREAM_BIT_RATE_BITS_PER_SECOND: 456789, job_io_fields.AUDIO_STREAM_BIT_DEPTH_BITS: 13, job_io_fields.AUDIO_STREAM_DURATION_SECONDS: 225.5889, job_io_fields.AUDIO_STREAM_CHANNEL_COUNT: 2, job_io_fields.AUDIO_STREAM_CHANNEL_LAYOUT: 'test_channel_layout', job_io_fields.AUDIO_STREAM_SAMPLE_RATE_SAMPLES_PER_SECOND: 65421, } @pytest.mark.parametrize(( 'test_description', 'tracks', 'expected_outputs', ), [ ( 'test parsing all stream types', [ NonCallableMagicMock( track_type='Video', **video_stream_fields, ), NonCallableMagicMock( track_type='Audio', **audio_stream_fields, ), NonCallableMagicMock( track_type='General', **container_fields, ), NonCallableMagicMock( track_type='Other', applesauce='bananas', ), ], { **expected_video_stream_fields, **expected_audio_stream_fields, **expected_container_fields, }, ), ( 'test file with 1 video stream and 0 audio streams', [ NonCallableMagicMock( track_type='Video', **video_stream_fields, ), NonCallableMagicMock( track_type='General', **{ **container_fields, 'count_of_video_streams': '1', 'count_of_audio_streams': None, }, ), ], { **expected_video_stream_fields, **{ **expected_container_fields, 'num_video_streams': 1, 'num_audio_streams': 0, }, }, ), ( 'test file with 0 video streams and 1 audio stream', [ NonCallableMagicMock( track_type='Audio', **audio_stream_fields, ), NonCallableMagicMock( track_type='General', **{ **container_fields, 'count_of_video_streams': None, 'count_of_audio_streams': '1', }, ), ], { **expected_audio_stream_fields, **{ **expected_container_fields, 'num_video_streams': 0, 'num_audio_streams': 1, }, }, ), ( 'test file with 0 video streams and 0 audio streams', [ NonCallableMagicMock( track_type='General', count_of_video_streams=None, count_of_audio_streams=None, format=None, format_profile=None, ), ], { 'num_video_streams': 0, 'num_audio_streams': 0, 'container_format': None, 'container_format_profile': None, }, ), ]) def test__extract_metadata( mocker, test_description, tracks, expected_outputs, ): """Test _extract_metadata.""" mocker.patch.object( s3_connector, 'get_url_for_s3_object', return_value='test_url', autospec=True, ) mocker.patch.object( MediaInfo, 'parse', ) media_info_parse_response = MediaInfo.parse.return_value media_info_parse_response.tracks = tracks outputs = extract_metadata._extract_metadata('test_key/123.mov') assert expected_outputs == outputs def test_extract_metadata(mocker): """Test extract_metadata.""" mocker.patch.object( extract_metadata, '_extract_metadata', return_value={'cool': 'cool'}, autospec=True) inputs = { job_io_fields.EXTRACT_METADATA_JOB_ID: 123, job_io_fields.INPUT_VIDEO_S3_BUCKET: 'test_bucket', job_io_fields.INPUT_VIDEO_S3_KEY: 'test_key/123.mov', } result = extract_metadata.extract_metadata(inputs) extract_metadata._extract_metadata.assert_called_once_with( 'test_key/123.mov') assert {'cool': 'cool'} == result def test_extract_prores_mezzanine_metadata(mocker): """Test extract_prores_mezzanine_metadata.""" mocker.patch.object( extract_metadata, '_extract_metadata', return_value={'cool': 'cool'}, autospec=True) mocker.patch.object( ows_video, 'set_track_metadata', return_value={'track_id': 123}, autospec=True) inputs = { job_io_fields.EXTRACT_PRORES_MEZZANINE_METADATA_JOB_ID: 123, job_io_fields.PRORES_MEZZANINE_OUTPUT_S3_KEY: 'test_key/123.mov', job_io_fields.PRODUCT_ID: 123, } result = extract_metadata.extract_prores_mezzanine_metadata(inputs) ows_video.set_track_metadata.assert_called_once_with( {'cool': 'cool', 'product_id': 123}) extract_metadata._extract_metadata.assert_called_once_with( 'test_key/123.mov') assert { job_io_fields.PRORES_MEZZANINE_METADATA: '{"cool": "cool"}', job_io_fields.TUID: 123, } == result