def _test_for_extension(self, extension: str, mock_datetime):
        from flamenco.job_compilers import blender_video_chunks, commands

        job_doc = JobDocForTesting({
            '_id': ObjectId(24 * 'f'),
            '_created': self.created,
            'settings': {
                'frames': '100-250',
                'fps': 24,
                'chunk_size': 100,
                'render_output': '/tmp/render/spring/export/FILENAME.MKV',
                'filepath': '/spring/edit/sprloing.blend',
                'output_file_extension': extension,
                'images_or_video': 'video',
                'extract_audio': True,
            },
            'job_type': 'blender-video-chunks',
        })

        task_manager = mock.Mock()
        job_manager = mock.Mock()

        # Create a stable 'now' for testing.
        mock_datetime.now.side_effect = [self.mock_now, self.mock_now]

        # We expect:
        # - 1 move-out-of-way task
        # - 2 frame rendering chunks of resp. 100 and 51 frames each
        # - 2 video encoding chunks
        # - 1 concat-videos task
        # - 1 extract-audio task
        # - 1 encode-audio task (because extracting only works to FLAC at the moment)
        # - 1 mux-audio task
        # - 1 move-to-final task
        # so that's 10 tasks in total.
        task_ids = [ObjectId() for _ in range(10)]
        task_manager.api_create_task.side_effect = task_ids

        compiler = blender_video_chunks.BlenderVideoChunks(
            task_manager=task_manager, job_manager=job_manager)
        compiler.compile(job_doc)

        frames = '/tmp/render/spring/export/frames'
        expected_final_output = f'/tmp/render/spring/export/' \
                                f'{self.mock_now:%Y_%m_%d}-sprloing{extension}'
        task_manager.api_create_task.assert_has_calls([
            mock.call(  # 0
                job_doc,
                [commands.MoveOutOfWay(src=frames)],
                'move-out-of-way',
                status='under-construction',
                task_type='file-management',
            ),

            # Chunk (frames + video) tasks
            mock.call(  # 1
                job_doc,
                [commands.BlenderRender(
                    blender_cmd='{blender}',
                    filepath='/spring/edit/sprloing.blend',
                    render_output=f'{frames}/chunk-00100-00199/######.png',
                    format='PNG',
                    frames='100..199')],
                'frame-chunk-100-199',
                status='under-construction',
                task_type='blender-render',
                parents=[task_ids[0]],
            ),
            mock.call(  # 2
                job_doc,
                [commands.CreateVideo(
                    ffmpeg_cmd='{ffmpeg}',
                    input_files=f'{frames}/chunk-00100-00199/*.png',
                    output_file=f'{frames}/chunk-00100-00199{extension}',
                    fps=24)],
                'video-chunk-100-199',
                status='under-construction',
                task_type='video-encoding',
                parents=[task_ids[1]],
            ),
            mock.call(  # 3
                job_doc,
                [commands.BlenderRender(
                    blender_cmd='{blender}',
                    filepath='/spring/edit/sprloing.blend',
                    render_output=f'{frames}/chunk-00200-00250/######.png',
                    format='PNG',
                    frames='200..250')],
                'frame-chunk-200-250',
                status='under-construction',
                task_type='blender-render',
                parents=[task_ids[0]],
            ),
            mock.call(  # 4
                job_doc,
                [commands.CreateVideo(
                    ffmpeg_cmd='{ffmpeg}',
                    input_files=f'{frames}/chunk-00200-00250/*.png',
                    output_file=f'{frames}/chunk-00200-00250{extension}',
                    fps=24)],
                'video-chunk-200-250',
                status='under-construction',
                task_type='video-encoding',
                parents=[task_ids[3]],
            ),

            # Extract & encode the audio
            mock.call(  # 5
                job_doc,
                [commands.BlenderRenderAudio(
                    blender_cmd='{blender}',
                    filepath='/spring/edit/sprloing.blend',
                    render_output=f'{frames}/audio.flac',
                    frame_start=100,
                    frame_end=250)],
                'render-audio',
                status='under-construction',
                task_type='blender-render',
                parents=[task_ids[0]],
            ),
            mock.call(  # 6
                job_doc,
                [commands.EncodeAudio(
                    ffmpeg_cmd='{ffmpeg}',
                    input_file=f'{frames}/audio.flac',
                    codec='aac',
                    bitrate='192k',
                    output_file=f'{frames}/audio.aac',
                )],
                'encode-audio',
                status='under-construction',
                task_type='video-encoding',
                parents=[task_ids[5]],
            ),

            # Create a video of the chunks.
            mock.call(  # 7
                job_doc,
                [commands.ConcatenateVideos(
                    ffmpeg_cmd='{ffmpeg}',
                    input_files=f'{frames}/chunk-*{extension}',
                    output_file=f'{frames}/video.mkv',
                )],
                'concatenate-videos',
                status='under-construction',
                task_type='video-encoding',
                parents=[task_ids[2], task_ids[4]],
            ),

            # Mux the audio into the video.
            mock.call(  # 8
                job_doc,
                [commands.MuxAudio(
                    ffmpeg_cmd='{ffmpeg}',
                    audio_file=f'{frames}/audio.aac',
                    video_file=f'{frames}/video.mkv',
                    output_file=f'{frames}/muxed.mkv',
                )],
                'mux-audio-video',
                status='under-construction',
                task_type='video-encoding',
                parents=[task_ids[6], task_ids[7]],
            ),

            # Move the file to its final place
            mock.call(  # 9
                job_doc,
                [commands.MoveWithCounter(
                    src=f'{frames}/muxed.mkv',
                    dest=expected_final_output,
                )],
                'move-with-counter',
                status='under-construction',
                task_type='file-management',
                parents=[task_ids[8]],
            ),
        ])

        task_manager.api_set_task_status_for_job.assert_called_with(
            job_doc['_id'], 'under-construction', 'queued', now=self.mock_now)
        job_manager.api_set_job_status(job_doc['_id'], 'under-construction', 'queued',
                                       now=self.mock_now)
示例#2
0
    def create_video_without_proper_task_type_support(self):
        from flamenco.job_compilers import blender_render, commands

        with self.app.app_context():
            self.flamenco.db('managers').update_one(
                {'_id': self.mngr_id},
                # No video-encoding task type
                {'$set': {
                    'worker_task_types': ['blender-render']
                }})

        job_doc = JobDocForTesting({
            '_id': ObjectId(24 * 'f'),
            '_created': self.created,
            'manager': self.mngr_id,
            'settings': {
                'frames': '1-5',
                'chunk_size': 3,
                'render_output': '/render/out/frames-######',
                'format': 'OPEN_EXR',
                'filepath':
                '/agent327/scenes/someshot/somefile.flamenco.blend',
                'blender_cmd': '/path/to/blender --enable-new-depsgraph',

                # On top of pretty much the same settings as test_small_job(),
                # we add those settings that trigger the creation of the
                # create_video task.
                'fps': 24,
                'images_or_video': 'images',
                'output_file_extension': '.exr',
            },
            'job_type': 'blender-render',
        })

        task_manager = mock.Mock()
        job_manager = mock.Mock()

        # We expect:
        # - 2 chunk of 3 resp 2 frames.
        # - 1 create_video task.
        # - 1 move-to-final task.
        # so that's 4 tasks in total.
        task_ids = [ObjectId() for _ in range(4)]
        task_manager.api_create_task.side_effect = task_ids

        compiler = blender_render.BlenderRender(task_manager=task_manager,
                                                job_manager=job_manager)

        with self.app.app_context():
            compiler.compile(job_doc)

        task_manager.api_create_task.assert_has_calls([
            # Render tasks
            mock.call(
                job_doc,
                [
                    commands.BlenderRender(
                        blender_cmd='/path/to/blender --enable-new-depsgraph',
                        filepath=
                        '/agent327/scenes/someshot/somefile.flamenco.blend',
                        format='OPEN_EXR',
                        render_output=
                        '/render/out__intermediate-2018-07-06_115233/frames-######',
                        frames='1..3')
                ],
                'blender-render-1-3',
                status='under-construction',
                task_type='blender-render',
                parents=None,
            ),
            mock.call(
                job_doc,
                [
                    commands.BlenderRender(
                        blender_cmd='/path/to/blender --enable-new-depsgraph',
                        filepath=
                        '/agent327/scenes/someshot/somefile.flamenco.blend',
                        format='OPEN_EXR',
                        render_output=
                        '/render/out__intermediate-2018-07-06_115233/frames-######',
                        frames='4,5')
                ],
                'blender-render-4,5',
                status='under-construction',
                task_type='blender-render',
                parents=None,
            ),

            # Move to final location
            mock.call(
                job_doc,
                [
                    commands.MoveToFinal(
                        src='/render/out__intermediate-2018-07-06_115233',
                        dest='/render/out')
                ],
                'move-to-final',
                parents=task_ids[1:2],
                status='under-construction',
                task_type='file-management',
            ),
        ])

        task_manager.api_set_task_status_for_job.assert_called_with(
            job_doc['_id'], 'under-construction', 'queued', now=mock.ANY)
        job_manager.api_set_job_status(job_doc['_id'],
                                       'under-construction',
                                       'queued',
                                       now=mock.ANY)
示例#3
0
    def test_small_job(self, mock_datetime):
        from flamenco.job_compilers import blender_render, commands

        job_doc = JobDocForTesting({
            '_id': ObjectId(24 * 'f'),
            '_created': self.created,
            'settings': {
                'frames': '1-5',
                'chunk_size': 2,
                'render_output': '/render/out/frames-######',
                'format': 'EXR',
                'filepath': '/agent327/scenes/someshot/somefile.blend',
                'blender_cmd': '/path/to/blender --enable-new-depsgraph',
            },
            'job_type': 'blender-render',
        })

        task_manager = mock.Mock()
        job_manager = mock.Mock()

        # Create a stable 'now' for testing.
        mock_now = datetime.datetime.now(tz=tz_util.utc)
        mock_datetime.now.side_effect = [mock_now]

        # We expect:
        # - 3 frame chunks of 2 frames each
        # - 1 move-to-final task
        # so that's 4 tasks in total.
        task_ids = [ObjectId() for _ in range(4)]
        task_manager.api_create_task.side_effect = task_ids

        compiler = blender_render.BlenderRender(
            task_manager=task_manager, job_manager=job_manager)
        compiler.compile(job_doc)

        task_manager.api_create_task.assert_has_calls([
            # Render tasks
            mock.call(
                job_doc,
                [commands.BlenderRender(
                    blender_cmd='/path/to/blender --enable-new-depsgraph',
                    filepath='/agent327/scenes/someshot/somefile.blend',
                    format='EXR',
                    render_output='/render/out__intermediate-2018-07-06_115233/frames-######',
                    frames='1,2')],
                'blender-render-1,2',
                status='under-construction',
                task_type='blender-render',
            ),
            mock.call(
                job_doc,
                [commands.BlenderRender(
                    blender_cmd='/path/to/blender --enable-new-depsgraph',
                    filepath='/agent327/scenes/someshot/somefile.blend',
                    format='EXR',
                    render_output='/render/out__intermediate-2018-07-06_115233/frames-######',
                    frames='3,4')],
                'blender-render-3,4',
                status='under-construction',
                task_type='blender-render',
            ),
            mock.call(
                job_doc,
                [commands.BlenderRender(
                    blender_cmd='/path/to/blender --enable-new-depsgraph',
                    filepath='/agent327/scenes/someshot/somefile.blend',
                    format='EXR',
                    render_output='/render/out__intermediate-2018-07-06_115233/frames-######',
                    frames='5')],
                'blender-render-5',
                status='under-construction',
                task_type='blender-render',
            ),

            # Move to final location
            mock.call(
                job_doc,
                [commands.MoveToFinal(
                    src='/render/out__intermediate-2018-07-06_115233',
                    dest='/render/out')],
                'move-to-final',
                parents=task_ids[0:3],
                status='under-construction',
                task_type='file-management',
            ),
        ])

        task_manager.api_set_task_status_for_job.assert_called_with(
            job_doc['_id'], 'under-construction', 'queued', now=mock_now)
        job_manager.api_set_job_status(job_doc['_id'], 'under-construction', 'queued', now=mock_now)
示例#4
0
    def test_rna_overrides(self, mock_datetime):
        from flamenco.job_compilers import blender_render, commands

        job_doc = JobDocForTesting({
            '_id': ObjectId(24 * 'f'),
            '_created': self.created,
            'settings': {
                'frames':
                '1-5',
                'chunk_size':
                2,
                'render_output':
                '/render/out/frames-######',
                'format':
                'OPEN_EXR',
                'filepath':
                '/agent327/scenes/someshot/somefile.blend',
                'blender_cmd':
                '/path/to/blender --enable-new-depsgraph',
                'rna_overrides': [
                    'bpy.context.scene.render.stamp_note_text = "je moeder"',
                    'bpy.context.scene.render.use_stamp_note = True',
                    'bpy.context.scene.render.use_stamp = True',
                ],
            },
            'job_type': 'blender-render',
        })

        expect_rna_overrides = '\n'.join([
            blender_render.RNA_OVERRIDES_HEADER,
            *job_doc['settings']['rna_overrides'], ''
        ])

        task_manager = mock.Mock()
        job_manager = mock.Mock()

        # Create a stable 'now' for testing.
        mock_now = datetime.datetime.now(tz=tz_util.utc)
        mock_datetime.now.side_effect = [mock_now]

        # We expect:
        # - 1 RNA override task
        # - 3 frame chunks of 2 frames each
        # - 1 move-to-final task
        # so that's 5 tasks in total.
        task_ids = [ObjectId() for _ in range(5)]
        task_manager.api_create_task.side_effect = task_ids

        compiler = blender_render.BlenderRender(task_manager=task_manager,
                                                job_manager=job_manager)
        compiler.compile(job_doc)

        task_manager.api_create_task.assert_has_calls([
            # Override task
            mock.call(
                job_doc,
                [
                    commands.CreatePythonFile(
                        filepath=
                        '/agent327/scenes/someshot/somefile-overrides.py',
                        contents=expect_rna_overrides,
                    )
                ],
                blender_render.RNA_OVERRIDES_TASK_NAME,
                status='under-construction',
                task_type='file-management',
                parents=None,
            ),
            # Render tasks
            mock.call(
                job_doc,
                [
                    commands.BlenderRender(
                        blender_cmd='/path/to/blender --enable-new-depsgraph',
                        filepath='/agent327/scenes/someshot/somefile.blend',
                        format='OPEN_EXR',
                        render_output=
                        '/render/out__intermediate-2018-07-06_115233/frames-######',
                        frames='1,2')
                ],
                'blender-render-1,2',
                status='under-construction',
                task_type='blender-render',
                parents=[task_ids[0]],
            ),
            mock.call(
                job_doc,
                [
                    commands.BlenderRender(
                        blender_cmd='/path/to/blender --enable-new-depsgraph',
                        filepath='/agent327/scenes/someshot/somefile.blend',
                        format='OPEN_EXR',
                        render_output=
                        '/render/out__intermediate-2018-07-06_115233/frames-######',
                        frames='3,4')
                ],
                'blender-render-3,4',
                status='under-construction',
                task_type='blender-render',
                parents=[task_ids[0]],
            ),
            mock.call(
                job_doc,
                [
                    commands.BlenderRender(
                        blender_cmd='/path/to/blender --enable-new-depsgraph',
                        filepath='/agent327/scenes/someshot/somefile.blend',
                        format='OPEN_EXR',
                        render_output=
                        '/render/out__intermediate-2018-07-06_115233/frames-######',
                        frames='5')
                ],
                'blender-render-5',
                status='under-construction',
                task_type='blender-render',
                parents=[task_ids[0]],
            ),

            # Move to final location
            mock.call(
                job_doc,
                [
                    commands.MoveToFinal(
                        src='/render/out__intermediate-2018-07-06_115233',
                        dest='/render/out')
                ],
                'move-to-final',
                parents=task_ids[1:4],
                status='under-construction',
                task_type='file-management',
            ),
        ])

        task_manager.api_set_task_status_for_job.assert_called_with(
            job_doc['_id'], 'under-construction', 'queued', now=mock_now)
        job_manager.api_set_job_status(job_doc['_id'],
                                       'under-construction',
                                       'queued',
                                       now=mock_now)