def test(
        self,
        transcode_job_factory,
        transcode_profile_name,
        source_file_path,
        exp_metadata,
        mocker,
    ):
        transcode_job = transcode_job_factory(profile=transcode_profile_name)
        video_rendition, thumbnails = ffmpeg.transcode(
            transcode_job=transcode_job, source_file_path=source_file_path)

        # Check video transcoded & persisted
        assert isinstance(video_rendition, models.VideoRendition)
        assert video_rendition.file
        assert video_rendition.name == transcode_profile_name
        assert video_rendition.width == exp_metadata['width']
        assert video_rendition.height == exp_metadata['height']
        assert video_rendition.duration == exp_metadata['duration']
        assert video_rendition.framerate == exp_metadata['framerate']
        assert video_rendition.audio_codec == exp_metadata['audio_codec']
        assert video_rendition.video_codec == exp_metadata['video_codec']
        assert video_rendition.codecs_string == exp_metadata['codecs_string']
        assert video_rendition.ext == 'webm'
        assert video_rendition.container == 'webm'
        assert video_rendition.file_size == exp_metadata['file_size']
        assert video_rendition.metadata
        assert sorted(video_rendition.metadata.keys()) == sorted(
            ('summary', 'video_stream', 'audio_stream', 'format'))

        # Check video is also updated
        video = video_rendition.video
        assert video.duration == video_rendition.duration
        assert video.framerate == video_rendition.framerate
        assert video.is_viewable is True
        assert video.default_thumbnail_image

        assert thumbnails
        assert all(
            isinstance(t, models.VideoRenditionThumbnail) for t in thumbnails)
        # Check thumbnails created
        assert thumbnails
        for thumbnail_record in thumbnails:
            assert isinstance(thumbnail_record, models.VideoRenditionThumbnail)
            assert thumbnail_record.time_offset_secs > 0
            assert thumbnail_record.file
            assert thumbnail_record.file.name.endswith('.jpg')
            assert thumbnail_record.ext == 'jpg'
            assert thumbnail_record.width == exp_metadata['width']
            assert thumbnail_record.height == exp_metadata['height']

        assert transcode_job.status == 'completed'
        assert transcode_job.ended_on

        # Check Segments were created
        assert video_rendition.videorenditionsegment_set.count() > 0
        for segment in video_rendition.videorenditionsegment_set.all():
            assert segment.segment_number is not None
            assert segment.file
    def test_raises_if_source_file_path_does_not_exist(self, transcode_job):
        result_path = ffmpeg.transcode(transcode_job=transcode_job,
                                       source_file_path=Path('not_found'))

        assert result_path is None
        assert transcode_job.status == 'failed'
        assert transcode_job.ended_on
        assert transcode_job.failure_context is None
        assert not models.VideoRendition.objects.filter(
            video=transcode_job.video).count()
    def test_transcode_job_failed_when_video_file_is_not_valid(
            self, transcode_job):
        result_path = ffmpeg.transcode(
            transcode_job=transcode_job,
            source_file_path=constants.INVALID_VIDEO_PATH,
        )

        assert result_path is None
        assert transcode_job.status == 'failed'
        assert transcode_job.ended_on
        assert not models.VideoRendition.objects.filter(
            video=transcode_job.video).count()
    def test_cannot_transcode_into_different_framerate(self, source_file_path,
                                                       transcode_profile_name,
                                                       transcode_job_factory):
        transcode_job = transcode_job_factory(profile=transcode_profile_name)
        result_path = ffmpeg.transcode(transcode_job=transcode_job,
                                       source_file_path=source_file_path)

        assert result_path is None
        assert transcode_job.status == 'completed'
        assert transcode_job.ended_on
        assert not models.VideoRendition.objects.filter(
            video=transcode_job.video).count()
    def test_transcode_job_failed_when_ffmpeg_returns_an_error(
            self, transcode_job_factory, mocker):
        mocker.patch(
            f'{MODULE}._ffmpeg_transcode_video',
            side_effect=[
                ffmpeg.TranscodeException('msg', stderr='command error output')
            ],
        )
        transcode_job = transcode_job_factory(profile='webm_240p')

        result_path = ffmpeg.transcode(
            transcode_job=transcode_job,
            source_file_path=constants.VIDEO_PATH_1080_30FPS_VERT,
        )

        assert result_path is None
        assert transcode_job.status == 'failed'
        assert transcode_job.ended_on
        assert transcode_job.failure_context == 'command error output'
        assert not models.VideoRendition.objects.filter(
            video=transcode_job.video).count()