Exemple #1
0
def export_gif(concat_file, filter_string, export_directory):
    """Export a GIF from the input frames, scaled down to 720p"""

    meta.write({"processing": "Exporting GIF"})
    benchmark = time()

    # GIF encoding technique taken from
    # http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html

    # TODO: Should we force-scale GIF for any reason (decision)
    # filter_string += ", scale=720:-1:flags=lanczos"

    palette_file = path.join(export_directory, "palette.png")
    subprocess.run([
        library["ffmpeg"], "-y", "-f", "concat", "-i", concat_file,
        "-filter_complex", filter_string + ", palettegen", palette_file
    ])

    export_file = path.join(export_directory, "exported.gif")
    subprocess.run([
        library["ffmpeg"], "-y", "-f", "concat", "-i", concat_file, "-i",
        palette_file, "-filter_complex",
        filter_string + " [comp]; [comp][1:v] paletteuse", export_file
    ])

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "gif": {
            "filePath": "exported.gif",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
def export_png_sequence(image_directory, export_directory):
    """Export all input frames as PNGs inside a ZIP"""

    meta.write({"processing": "Exporting PNG Sequence"})
    benchmark = time()

    raster_input_files = glob(path.join(image_directory, "*.png"))
    export_file = path.join(export_directory, "exported.png.zip")

    zip_file = ZipFile(export_file, "w")

    for frame in raster_input_files:
        zip_file.write(frame, path.basename(frame))

    filesize = path.getsize(export_file)
    meta.write(
        {
            "processing": False,
            "png.zip": {
                "filePath": "exported.png.zip",
                "exported": datetime.now().isoformat(),
                "processingTime": time() - benchmark,
                "fileSize": filesize,
            },
        }
    )
def export_svg_sequence(image_directory, export_directory):
    vector_input_files = glob(path.join(image_directory, "*.svg"))

    if len(vector_input_files) > 0:
        meta.write({"processing": "Exporting SVG Sequence"})
        benchmark = time()

        export_file = path.join(export_directory, "exported.svg.zip")

        zip_file = ZipFile(export_file, "w")

        for frame in vector_input_files:
            zip_file.write(frame, path.basename(frame))

        filesize = path.getsize(export_file)
        meta.write(
            {
                "processing": False,
                "svg.zip": {
                    "filePath": "exported.svg.zip",
                    "exported": datetime.now().isoformat(),
                    "processingTime": time() - benchmark,
                    "fileSize": filesize,
                },
            }
        )
Exemple #4
0
def export_thumbnail_animation(ffmpeg_input_options, export_directory):
    meta.write({"processing": "Exporting Thumbnail"})
    benchmark = time()

    # TODO: Use better algorithm if available like in export_gif

    export_file = path.join(export_directory, "thumbnail.gif")
    ffmpeg_call = ffmpeg_input_options + [
        "-vf", "scale=480:-1",
        "-gifflags", "+transdiff",
        export_file
    ]

    call(ffmpeg_call)

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "thumbnail": {
            "filePath": "thumbnail.gif",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #5
0
def render(target_time, device):

    if bpy.context.scene.render.engine == "BLEND4WEB":
        meta.write({
            "lastRender": datetime.now().isoformat()
        })
    else:
        render_frames(target_time, device)
def render(target_time, device):

    if bpy.context.scene.render.engine == "BLEND4WEB":
        meta.write({
            "lastRender": datetime.now().isoformat()
        })
    else:
        render_frames(target_time, device)
def export_gif(concat_file, filter_string, export_directory):
    """Export a GIF from the input frames, scaled down to 720p"""

    meta.write({"processing": "Exporting GIF"})
    benchmark = time()

    # GIF encoding technique taken from
    # http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html

    # TODO: Should we force-scale GIF for any reason (decision)
    # filter_string += ", scale=720:-1:flags=lanczos"

    palette_file = path.join(export_directory, "palette.png")
    call(
        [
            "ffmpeg",
            "-y",
            "-f",
            "concat",
            "-i",
            concat_file,
            "-filter_complex",
            filter_string + ", palettegen",
            palette_file,
        ]
    )

    export_file = path.join(export_directory, "exported.gif")
    call(
        [
            "ffmpeg",
            "-y",
            "-f",
            "concat",
            "-i",
            concat_file,
            "-i",
            palette_file,
            "-filter_complex",
            filter_string + " [comp]; [comp][1:v] paletteuse",
            export_file,
        ]
    )

    filesize = path.getsize(export_file)
    meta.write(
        {
            "processing": False,
            "gif": {
                "filePath": "exported.gif",
                "exported": datetime.now().isoformat(),
                "processingTime": time() - benchmark,
                "fileSize": filesize,
            },
        }
    )
def update_models():
    meta.write({"processing": "Updating models"})

    updates_occurred = False

    # Update existing models
    for obj in bpy.data.objects:
        if obj.get("elmyra-url") is not None:
            if update_object(obj):
                updates_occurred = True

    meta.write({"processing": False})

    return updates_occurred
Exemple #9
0
def update_models():
    meta.write({"processing": "Updating models"})

    updates_occurred = False

    # Update existing models
    for obj in bpy.data.objects:
        if obj.get("elmyra-url") is not None:
            if update_object(obj):
                updates_occurred = True

    meta.write({"processing": False})

    return updates_occurred
Exemple #10
0
def export_gif(ffmpeg_input_options, export_directory):

    meta.write({"processing": "Exporting GIF"})
    benchmark = time()

    ffmpeg_version = check_output(["ffmpeg", "-version"]).decode().split()[2]
    ffmpeg_version_major = int(ffmpeg_version.split(".")[0])
    ffmpeg_version_minor = int(ffmpeg_version.split(".")[1])

    export_file = path.join(export_directory, "animation.gif")

    if ffmpeg_version_major >= 2 and ffmpeg_version_minor >= 6:

        # Only available in ffmpeg 2.6+ (eg. in Ubuntu 15.10, Fedora 22)
        # http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html

        palette_file = path.join(export_directory, "palette.png")
        filters = "fps=15,scale=320:-1:flags=lanczos"

        ffmpeg_palette_call = ffmpeg_input_options + [
            "-vf", "{},palettegen".format(filters),
            palette_file
        ]

        ffmpeg_render_call = ffmpeg_input_options + [
            "-i", palette_file,
            "-lavfi", "{} [x]; [x][1:v] paletteuse".format(filters),
            export_file
        ]

        call(ffmpeg_palette_call)
        call(ffmpeg_render_call)
    else:
        ffmpeg_call = ffmpeg_input_options + [
            "-gifflags", "+transdiff",
            export_file
        ]

        call(ffmpeg_call)

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "gif": {
            "filePath": "animation.gif",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #11
0
def render_frame(render_directory, frame, samples, sample_step, stack_frame=None):
    benchmark = time()

    bpy.context.scene.frame_current = frame
    bpy.context.scene.cycles.samples = sample_step

    if stack_frame:
        filepath = path.join("//rendered_frames", ".render-cache.png")
        bpy.context.scene.render.filepath = filepath
        bpy.ops.render.render(write_still=True)

        stack_image = Image.open(stack_frame)
        stack_samples = samples

        blend_image = Image.open(path.join(render_directory, ".render-cache.png"))
        blend_samples = sample_step

        alpha = float(stack_samples) / float(stack_samples + blend_samples)

        stack_image = Image.blend(blend_image, stack_image, alpha)
        stack_samples = stack_samples + blend_samples

        blend_image.close()
        remove(path.join(render_directory, ".render-cache.png"))

        stack_filename = "{0:06}.{1}.png".format(frame, stack_samples)
        stack_image.save(path.join(render_directory, stack_filename))

        stack_image.close()
        remove(stack_frame)

    else:
        filename = "{0:06}.{1}.png".format(frame, sample_step)
        filepath = path.join("//rendered_frames", filename)
        bpy.context.scene.render.filepath = filepath
        bpy.ops.render.render(write_still=True)

    meta.write({
        "renderDevice": bpy.context.scene.cycles.device,
        "lastRenderedFrame": frame,
        "lastRenderDuration": time() - benchmark,
        "lastRender": datetime.now().isoformat(),
        "lastRenderedSamples": sample_step
    })
Exemple #12
0
def export_png(ffmpeg_input_options, export_directory):
    meta.write({"processing": "Exporting PNG"})
    benchmark = time()

    export_file = path.join(export_directory, "still.png")
    ffmpeg_call = ffmpeg_input_options + [export_file]

    call(ffmpeg_call)

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "png": {
            "filePath": "still.png",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #13
0
def export_png(ffmpeg_input_options, export_directory):
    meta.write({"processing": "Exporting PNG"})
    benchmark = time()

    export_file = path.join(export_directory, "exported.png")
    ffmpeg_call = ffmpeg_input_options + [export_file]

    subprocess.run(ffmpeg_call)

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "png": {
            "filePath": "exported.png",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #14
0
def export_web3d():
    meta.write({"processing": "Exporting HTML"})
    benchmark = time()

    export_directory = bpy.path.abspath("//")
    export_filepath = path.join(export_directory, "exported.html")

    bpy.ops.export_scene.b4w_html(filepath=export_filepath)

    filesize = path.getsize(export_filepath)
    meta.write({
        "processing": False,
        "html": {
            "filePath": "exported.html",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #15
0
def export_svg(image_directory, export_directory):
    vector_input_files = glob(path.join(image_directory, "*.svg"))

    if len(vector_input_files) > 0:
        meta.write({"processing": "Exporting SVG"})
        benchmark = time()

        export_file = path.join(export_directory, "exported.svg")

        copy(vector_input_files[0], export_file)

        filesize = path.getsize(export_file)
        meta.write({
            "processing": False,
            "svg": {
                "filePath": "exported.svg",
                "exported": datetime.now().isoformat(),
                "processingTime": time() - benchmark,
                "fileSize": filesize
            }
        })
def export_web3d():
    meta.write({"processing": "Exporting HTML"})
    benchmark = time()

    export_directory = bpy.path.abspath("//")
    export_filepath = path.join(export_directory, "exported.html")

    bpy.ops.export_scene.b4w_html(filepath=export_filepath)

    filesize = path.getsize(export_filepath)
    meta.write(
        {
            "processing": False,
            "html": {
                "filePath": "exported.html",
                "exported": datetime.now().isoformat(),
                "processingTime": time() - benchmark,
                "fileSize": filesize,
            },
        }
    )
Exemple #17
0
def update_models(options, min_interval=None):
    meta.write({"processing": "Updating models"})

    updates_occurred = False

    # First import - supplied via args
    if hasattr(options, "models"):
        for url in options.models.splitlines():
            bpy.ops.object.empty_add(type="CUBE")
            bpy.context.active_object["elmyra-url"] = url

        updates_occurred = True

    # Update existing models
    for obj in bpy.data.objects:
        if obj.get("elmyra-url") is not None:
            if update_object(obj, min_interval):
                updates_occurred = True

    meta.write({"processing": False, "update": {"lastUpdate": time(), "updatesOcurred": updates_occurred}})

    return updates_occurred
Exemple #18
0
def export_webm(concat_file, filter_string, export_directory):
    meta.write({"processing": "Exporting WEBM"})
    benchmark = time()

    export_file = path.join(export_directory, "exported.webm")

    subprocess.run([
        library["ffmpeg"], "-y", "-f", "concat", "-i", concat_file,
        "-filter_complex", filter_string, "-c:v", "libvpx-vp9", "-crf", "4",
        "-speed", "1", "-b:v", "32M", export_file
    ])

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "webm": {
            "filePath": "exported.webm",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #19
0
def export_ogv(concat_file, filter_string, export_directory):
    meta.write({"processing": "Exporting OGV"})
    benchmark = time()

    export_file = path.join(export_directory, "exported.ogv")

    subprocess.run([
        library["ffmpeg"], "-y", "-f", "concat", "-i", concat_file,
        "-filter_complex", filter_string, "-c:v", "libtheora", "-qscale:v",
        "10", export_file
    ])

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "ogv": {
            "filePath": "exported.ogv",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #20
0
def export_mp4(concat_file, filter_string, export_directory):
    meta.write({"processing": "Exporting MP4"})
    benchmark = time()

    export_file = path.join(export_directory, "exported.mp4")

    subprocess.run([
        library["ffmpeg"], "-y", "-f", "concat", "-i", concat_file,
        "-filter_complex", filter_string, "-c:v", "libx264", "-preset", "slow",
        "-crf", "4", export_file
    ])

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "mp4": {
            "filePath": "exported.mp4",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
def export_mp4(concat_file, filter_string, export_directory):
    meta.write({"processing": "Exporting MP4"})
    benchmark = time()

    export_file = path.join(export_directory, "exported.mp4")

    call(
        [
            "ffmpeg",
            "-y",
            "-f",
            "concat",
            "-i",
            concat_file,
            "-filter_complex",
            filter_string,
            "-c:v",
            "libx264",
            "-preset",
            "slow",
            "-crf",
            "4",
            export_file,
        ]
    )

    filesize = path.getsize(export_file)
    meta.write(
        {
            "processing": False,
            "mp4": {
                "filePath": "exported.mp4",
                "exported": datetime.now().isoformat(),
                "processingTime": time() - benchmark,
                "fileSize": filesize,
            },
        }
    )
def export_webm(concat_file, filter_string, export_directory):
    meta.write({"processing": "Exporting WEBM"})
    benchmark = time()

    export_file = path.join(export_directory, "exported.webm")

    call(
        [
            "ffmpeg",
            "-y",
            "-f",
            "concat",
            "-i",
            concat_file,
            "-filter_complex",
            filter_string,
            "-c:v",
            "libvpx",
            "-crf",
            "4",
            "-b:v",
            "32M",
            export_file,
        ]
    )

    filesize = path.getsize(export_file)
    meta.write(
        {
            "processing": False,
            "webm": {
                "filePath": "exported.webm",
                "exported": datetime.now().isoformat(),
                "processingTime": time() - benchmark,
                "fileSize": filesize,
            },
        }
    )
def export_svg(image_directory, export_directory):
    vector_input_files = glob(path.join(image_directory, "*.svg"))

    if len(vector_input_files) > 0:
        meta.write({"processing": "Exporting SVG"})
        benchmark = time()

        export_file = path.join(export_directory, "exported.svg")

        copy(vector_input_files[0], export_file)

        filesize = path.getsize(export_file)
        meta.write(
            {
                "processing": False,
                "svg": {
                    "filePath": "exported.svg",
                    "exported": datetime.now().isoformat(),
                    "processingTime": time() - benchmark,
                    "fileSize": filesize,
                },
            }
        )
Exemple #24
0
def export_ogv(ffmpeg_input_options, export_directory):
    meta.write({"processing": "Exporting OGV"})
    benchmark = time()

    export_file = path.join(export_directory, "animation.ogv")
    ffmpeg_call = ffmpeg_input_options + [
        "-codec:v", "libtheora",
        "-qscale:v", "7",
        export_file
    ]

    call(ffmpeg_call)

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "ogv": {
            "filePath": "animation.ogv",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #25
0
def export_png_sequence(image_directory, export_directory):
    """Export all input frames as PNGs inside a ZIP"""

    meta.write({"processing": "Exporting PNG Sequence"})
    benchmark = time()

    raster_input_files = glob(path.join(image_directory, "*.png"))
    export_file = path.join(export_directory, "exported.png.zip")

    zip_file = ZipFile(export_file, 'w')

    for frame in raster_input_files:
        zip_file.write(frame, path.basename(frame))

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "png.zip": {
            "filePath": "exported.png.zip",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
def export_ogv(concat_file, filter_string, export_directory):
    meta.write({"processing": "Exporting OGV"})
    benchmark = time()

    export_file = path.join(export_directory, "exported.ogv")

    call(
        [
            "ffmpeg",
            "-y",
            "-f",
            "concat",
            "-i",
            concat_file,
            "-filter_complex",
            filter_string,
            "-c:v",
            "libtheora",
            "-qscale:v",
            "10",
            export_file,
        ]
    )

    filesize = path.getsize(export_file)
    meta.write(
        {
            "processing": False,
            "ogv": {
                "filePath": "exported.ogv",
                "exported": datetime.now().isoformat(),
                "processingTime": time() - benchmark,
                "fileSize": filesize,
            },
        }
    )
Exemple #27
0
def export_svg_sequence(image_directory, export_directory):
    vector_input_files = glob(path.join(image_directory, "*.svg"))

    if len(vector_input_files) > 0:
        meta.write({"processing": "Exporting SVG Sequence"})
        benchmark = time()

        export_file = path.join(export_directory, "exported.svg.zip")

        zip_file = ZipFile(export_file, 'w')

        for frame in vector_input_files:
            zip_file.write(frame, path.basename(frame))

        filesize = path.getsize(export_file)
        meta.write({
            "processing": False,
            "svg.zip": {
                "filePath": "exported.svg.zip",
                "exported": datetime.now().isoformat(),
                "processingTime": time() - benchmark,
                "fileSize": filesize
            }
        })
Exemple #28
0
def export_zip(image_directory, export_directory):
    meta.write({"processing": "Exporting ZIP"})
    benchmark = time()

    export_file = path.join(export_directory, "animation.zip")
    zip_call = [
        "zip",
        "-r9",
        export_file,
        path.join(image_directory, "")
    ]

    call(zip_call)

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "zip": {
            "filePath": "animation.zip",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #29
0
def export_webm(ffmpeg_input_options, export_directory):
    meta.write({"processing": "Exporting WEBM"})
    benchmark = time()

    export_file = path.join(export_directory, "animation.webm")
    ffmpeg_call = ffmpeg_input_options + [
        "-c:v", "libvpx",
        "-crf", "4",
        "-b:v", "1M",
        export_file
    ]

    call(ffmpeg_call)

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "webm": {
            "filePath": "animation.webm",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
Exemple #30
0
def export_mp4(ffmpeg_input_options, export_directory):
    meta.write({"processing": "Exporting MP4"})
    benchmark = time()

    export_file = path.join(export_directory, "animation.mp4")
    ffmpeg_call = ffmpeg_input_options + [
        "-c:v", "libx264",
        "-preset", "slow",
        "-crf", "4",
        export_file
    ]

    call(ffmpeg_call)

    filesize = path.getsize(export_file)
    meta.write({
        "processing": False,
        "mp4": {
            "filePath": "animation.mp4",
            "exported": datetime.now().isoformat(),
            "processingTime": time() - benchmark,
            "fileSize": filesize
        }
    })
def render_frames(target_time, device):
    benchmark = time()

    bpy.context.scene.cycles.seed = int(benchmark) # Imagestacking random seed
    bpy.context.scene.cycles.device = device

    render_directory = path.join(bpy.path.abspath("//"), "rendered_frames")

    if not path.exists(render_directory):
        makedirs(render_directory)

    first = bpy.context.scene.frame_start
    last = bpy.context.scene.frame_end
    total_frames = last - first + 1

    rendered_frames = natsorted(glob(path.join(render_directory, "*.png")))
    requested_frames = []

    if len(rendered_frames) < total_frames:
        meta.write({"processing": "Rendering missing frames"})

        # Build the initial list of frames based on a binary split pattern:
        #
        #  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |  (10 example frame numbers)
        #  -----------------------------------------
        #  |   |   |   |   | 1 |   |   |   |   |   |
        #  |   |   | 2 |   |   |   |   | 3 |   |   |  (split pattern and
        #  | 4 |   |   | 5 |   | 6 |   |   | 7 |   |   render order)
        #  |   | 8 |   |   |   |   | 9 |   |   |10 |

        all_frames = range(first, last + 1)

        numbers = [int(path.basename(r).split(".")[0]) for r in rendered_frames]

        all_ranges = []
        buffer_range = []

        for frame in all_frames:
            if frame not in numbers:
                buffer_range.append(frame)
            elif len(buffer_range) > 0:
                all_ranges.append(buffer_range)
                buffer_range = []

        if len(buffer_range) > 0:
            all_ranges.append(buffer_range)
            buffer_range = []

        while len(all_ranges) > 0:
            largest_range = max(all_ranges, key=lambda r: [len(r), -min(r)])
            all_ranges.remove(largest_range)
            split_index = len(largest_range) // 2

            for index, frame in enumerate(largest_range):
                if index == split_index:
                    requested_frames.append({
                        "number": frame,
                        "available_samples": 0,
                        "requested_samples": SAMPLES_INITIAL,
                        "available_frame": None
                    })

                    if len(buffer_range) > 0:
                        all_ranges.append(buffer_range)
                        buffer_range = []
                else:
                    buffer_range.append(frame)

            if len(buffer_range) > 0:
                all_ranges.append(buffer_range)
                buffer_range = []

    else:
        samples = [int(path.basename(r).split(".")[1]) for r in rendered_frames]
        min_samples = min(samples)
        max_samples = max(samples)

        if min_samples < QUALITY_PREVIEW:
            render_quality = "draft"
        elif min_samples > QUALITY_PREVIEW:
            render_quality = "preview"
        elif min_samples > QUALITY_PRODUCTION:
            render_quality = "production"

        meta.write({
            "processing": "Rendering more samples",
            "minimumSamples": min_samples,
            "renderQuality": render_quality
        })

        if min_samples != max_samples:
            for frame in rendered_frames:
                frame_info = path.basename(frame).split(".")
                frame_number = int(frame_info[0])
                frame_samples = int(frame_info[1])

                if frame_samples < max_samples:
                    requested_frames.append({
                        "number": frame_number,
                        "available_samples": frame_samples,
                        "requested_samples": max_samples - frame_samples,
                        "available_frame": frame
                    })

        elif min_samples < SAMPLES_CAP:
            for frame in rendered_frames:
                frame_info = path.basename(frame).split(".")
                frame_number = int(frame_info[0])

                requested_frames.append({
                    "number": frame_number,
                    "available_samples": min_samples,
                    "requested_samples": int(min_samples * SAMPLES_MULTIPLIER),
                    "available_frame": frame
                })

    for frame in requested_frames:
        render_frame(render_directory,
                     frame["number"],
                     frame["available_samples"],
                     frame["requested_samples"],
                     frame["available_frame"])

        if time() - benchmark > target_time:
            break

    meta.write({"processing": False})
Exemple #32
0
def render_frames(target_time, device):
    benchmark = time()

    bpy.context.scene.cycles.seed = int(benchmark) # Imagestacking random seed
    bpy.context.scene.cycles.device = device

    render_directory = path.join(bpy.path.abspath("//"), "rendered_frames")

    if not path.exists(render_directory):
        makedirs(render_directory)

    first = bpy.context.scene.frame_start
    last = bpy.context.scene.frame_end
    total_frames = last - first + 1

    rendered_frames = natsorted(glob(path.join(render_directory, "*.png")))
    requested_frames = []

    if len(rendered_frames) < total_frames:
        meta.write({"processing": "Rendering missing frames"})

        # Build the initial list of frames based on a binary split pattern:
        #
        #  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |  (10 example frame numbers)
        #  -----------------------------------------
        #  |   |   |   |   | 1 |   |   |   |   |   |
        #  |   |   | 2 |   |   |   |   | 3 |   |   |  (split pattern and
        #  | 4 |   |   | 5 |   | 6 |   |   | 7 |   |   render order)
        #  |   | 8 |   |   |   |   | 9 |   |   |10 |

        all_frames = range(first, last + 1)

        numbers = [int(path.basename(r).split(".")[0]) for r in rendered_frames]

        all_ranges = []
        buffer_range = []

        for frame in all_frames:
            if frame not in numbers:
                buffer_range.append(frame)
            elif len(buffer_range) > 0:
                all_ranges.append(buffer_range)
                buffer_range = []

        if len(buffer_range) > 0:
            all_ranges.append(buffer_range)
            buffer_range = []

        while len(all_ranges) > 0:
            largest_range = max(all_ranges, key=lambda r: [len(r), -min(r)])
            all_ranges.remove(largest_range)
            split_index = len(largest_range) // 2

            for index, frame in enumerate(largest_range):
                if index == split_index:
                    requested_frames.append({
                        "number": frame,
                        "available_samples": 0,
                        "requested_samples": SAMPLES_INITIAL,
                        "available_frame": None
                    })

                    if len(buffer_range) > 0:
                        all_ranges.append(buffer_range)
                        buffer_range = []
                else:
                    buffer_range.append(frame)

            if len(buffer_range) > 0:
                all_ranges.append(buffer_range)
                buffer_range = []

    else:
        samples = [int(path.basename(r).split(".")[1]) for r in rendered_frames]
        min_samples = min(samples)
        max_samples = max(samples)

        if min_samples < QUALITY_PREVIEW:
            render_quality = "draft"
        elif min_samples > QUALITY_PREVIEW:
            render_quality = "preview"
        elif min_samples > QUALITY_PRODUCTION:
            render_quality = "production"

        meta.write({
            "processing": "Rendering more samples",
            "minimumSamples": min_samples,
            "renderQuality": render_quality
        })

        if min_samples != max_samples:
            for frame in rendered_frames:
                frame_info = path.basename(frame).split(".")
                frame_number = int(frame_info[0])
                frame_samples = int(frame_info[1])

                if frame_samples < max_samples:
                    requested_frames.append({
                        "number": frame_number,
                        "available_samples": frame_samples,
                        "requested_samples": max_samples - frame_samples,
                        "available_frame": frame
                    })

        elif min_samples < SAMPLES_CAP:
            for frame in rendered_frames:
                frame_info = path.basename(frame).split(".")
                frame_number = int(frame_info[0])

                requested_frames.append({
                    "number": frame_number,
                    "available_samples": min_samples,
                    "requested_samples": int(min_samples * SAMPLES_MULTIPLIER),
                    "available_frame": frame
                })

    for frame in requested_frames:
        render_frame(render_directory,
                     frame["number"],
                     frame["available_samples"],
                     frame["requested_samples"],
                     frame["available_frame"])

        if time() - benchmark > target_time:
            break

    meta.write({"processing": False})
Exemple #33
0
def render_frame(render_directory,
                 frame,
                 existing_samples,
                 additional_samples,
                 existing_frame=None):
    benchmark = time()

    bpy.context.scene.frame_current = frame
    bpy.context.scene.cycles.samples = additional_samples

    # Enable SVG export when using Freestyle
    if bpy.context.scene.render.use_freestyle:
        bpy.context.scene.svg_export.use_svg_export = True

    cache_filename = ".render-cache.png"
    cache_filepath = path.join(render_directory, cache_filename)

    bpy.context.scene.render.filepath = cache_filepath
    bpy.ops.render.render(write_still=True)

    if existing_frame:
        alpha = float(existing_samples) / float(existing_samples + additional_samples)

        result_samples = existing_samples + additional_samples
        result_filename = "{0:06}.{1}.png".format(frame, result_samples)
        result_filepath = path.join(render_directory, result_filename)

        ffmpeg_call = [
            library["ffmpeg"],
            "-y",
            "-i", existing_frame,
            "-i", cache_filepath,
            "-filter_complex",
            "[1:v][0:v]blend=all_expr='A*{0}+B*{1}'".format(alpha, 1 - alpha),
            result_filepath
        ]

        subprocess.run(ffmpeg_call)

        remove(existing_frame)
        remove(cache_filepath)

    else:
        result_filename = "{0:06}.{1}.png".format(frame, additional_samples)
        result_filepath = path.join(render_directory, result_filename)

        rename(cache_filepath, result_filepath)

    if bpy.context.scene.render.use_freestyle:
        svg_old_filepath = path.join(render_directory,
                                     "{0}{1:04}.svg".format(cache_filename, frame))
        svg_new_filepath = path.join(render_directory,
                                     "{0:06}.svg".format(frame))

        if existing_frame:
            remove(svg_new_filepath)

        rename(svg_old_filepath, svg_new_filepath)

    # Thumbnail creation

    thumbnail_filepath = path.join(render_directory, "..", "thumbnail.png")
    subprocess.run([
        library["ffmpeg"],
        "-y",
        "-f", "image2",
        "-i", result_filepath,
        "-vf", "scale=480:270:force_original_aspect_ratio=decrease",
        thumbnail_filepath
    ])

    meta.write({
        "renderDevice": bpy.context.scene.cycles.device,
        "lastRenderedFrame": frame,
        "lastRenderDuration": time() - benchmark,
        "lastRender": datetime.now().isoformat(),
        "lastRenderedSamples": additional_samples
    })
def render_frame(render_directory,
                 frame,
                 existing_samples,
                 additional_samples,
                 existing_frame=None):
    benchmark = time()

    bpy.context.scene.frame_current = frame
    bpy.context.scene.cycles.samples = additional_samples

    # Enable SVG export when using Freestyle
    if bpy.context.scene.render.use_freestyle:
        bpy.context.scene.svg_export.use_svg_export = True

    cache_filename = ".render-cache.png"
    cache_filepath = path.join(render_directory, cache_filename)

    bpy.context.scene.render.filepath = cache_filepath
    bpy.ops.render.render(write_still=True)

    if existing_frame:
        alpha = float(existing_samples) / float(existing_samples + additional_samples)

        result_samples = existing_samples + additional_samples
        result_filename = "{0:06}.{1}.png".format(frame, result_samples)
        result_filepath = path.join(render_directory, result_filename)

        ffmpeg_call = [
            "ffmpeg",
            "-y",
            "-i", existing_frame,
            "-i", cache_filepath,
            "-filter_complex",
            "[1:v][0:v]blend=all_expr='A*{0}+B*{1}'".format(alpha, 1 - alpha),
            result_filepath
        ]

        call(ffmpeg_call)

        remove(existing_frame)
        remove(cache_filepath)

    else:
        result_filename = "{0:06}.{1}.png".format(frame, additional_samples)
        result_filepath = path.join(render_directory, result_filename)

        rename(cache_filepath, result_filepath)

    if bpy.context.scene.render.use_freestyle:
        svg_old_filepath = path.join(render_directory,
                                     "{0}{1:04}.svg".format(cache_filename, frame))
        svg_new_filepath = path.join(render_directory,
                                     "{0:06}.svg".format(frame))

        if existing_frame:
            remove(svg_new_filepath)

        rename(svg_old_filepath, svg_new_filepath)

    # Thumbnail creation

    thumbnail_filepath = path.join(render_directory, "..", "thumbnail.png")
    call([
        "ffmpeg",
        "-y",
        "-f", "image2",
        "-i", result_filepath,
        "-vf", "scale=480:270:force_original_aspect_ratio=decrease",
        thumbnail_filepath
    ])

    meta.write({
        "renderDevice": bpy.context.scene.cycles.device,
        "lastRenderedFrame": frame,
        "lastRenderDuration": time() - benchmark,
        "lastRender": datetime.now().isoformat(),
        "lastRenderedSamples": additional_samples
    })
Exemple #35
0

args = parse_custom_args()

common.ensure_addons()

if args.blend:
    common.open_scene(args.blend)
    version.save_new(args.id)
    meta.write_media_info()
else:
    run_updates = True

    if args.min_interval:
        meta = meta.get()
        if "lastUpdate" in meta:
            run_updates = time() - meta["lastUpdate"] < args.min_interval

    if run_updates:
        version.open_latest(args.id)

        # TODO: Find problem: Why does it update although hash stayed the same?
        #       (Happened on update form external sources manually)
        #       (Note 06/03/2016 - not sure if still applies)

        if update.update_models():
            version.save_new(args.id)
            meta.write_media_info()
    else:
        meta.write({"lastUpdate": time()})
args = parse_custom_args()


common.ensure_addons()

if args.blend:
    common.open_scene(args.blend)
    version.save_new(args.id)
    meta.write_media_info()
else:
    run_updates = True

    if args.min_interval:
        meta = meta.get()
        if "lastUpdate" in meta:
            run_updates = time() - meta["lastUpdate"] < args.min_interval

    if run_updates:
        version.open_latest(args.id)

        # TODO: Find problem: Why does it update although hash stayed the same?
        #       (Happened on update form external sources manually)
        #       (Note 06/03/2016 - not sure if still applies)

        if update.update_models():
            version.save_new(args.id)
            meta.write_media_info()
    else:
        meta.write({"lastUpdate": time()})
Exemple #37
0
    source.generate(archives)
  return archives

def discover(meta, archives):
  for archive in archives.archives: 
    if not meta.contains(archive.meta_hash()):
      log.info("Adding archive meta (%s)" % archive)
      meta.add(archive.paths)

if __name__ == "__main__":
  top = boto.config.get('Ice', 'top')
  password = boto.config.get('Ice', 'password')
  bucket_name = boto.config.get('Ice', 'bucket')
  vault_name = boto.config.get('Ice', 'vault')

  s3 = meta.S3(password, bucket_name)
  meta = meta.Meta(s3)
  meta.read()
  archives = get_archive_set(top)
  discover(meta, archives)
  glacier = boto.connect_glacier()
  vault = glacier.create_vault(vault_name)
  for archive in archives.archives:
    log.info("Archive: %s" % archive)
    meta_hash = archive.meta_hash()
    sha1 = meta.get_sha1(meta_hash)
    archiver.upload_archive(vault, sha1, archive.paths, upload=True, dryRun=True)
  meta.write()

# EOF
Exemple #38
0
def render(abandon_after=60, device="GPU"):
    benchmark = time()

    bpy.context.scene.cycles.seed = int(benchmark) # Imagestacking random seed
    bpy.context.scene.cycles.device = device

    render_directory = path.join(bpy.path.abspath("//"), "rendered_frames")

    if not path.exists(render_directory):
        makedirs(render_directory)

    first = bpy.context.scene.frame_start
    last = bpy.context.scene.frame_end
    total_frames = last - first + 1

    rendered_frames = natsorted(glob(path.join(render_directory, "*")))
    requested_frames = []

    if len(rendered_frames) < total_frames:
        meta.write({"processing": "Rendering missing frames"})

        for number in range(first + len(rendered_frames), last + 1):
            requested_frames.append({
                "number": number,
                "available_samples": 0,
                "requested_samples": SAMPLES_INITIAL,
                "available_frame": None
            })
    else:
        samples = [int(path.basename(r).split(".")[1]) for r in rendered_frames]
        min_samples = min(samples)
        max_samples = max(samples)

        if min_samples < QUALITY_PREVIEW:
            render_quality = "draft"
        elif min_samples > QUALITY_PREVIEW:
            render_quality = "preview"
        elif min_samples > QUALITY_PRODUCTION:
            render_quality = "production"

        meta.write({
            "processing": "Rendering more samples",
            "minimumSamples": min_samples,
            "renderQuality": render_quality
        })

        if min_samples != max_samples:
            for frame in rendered_frames:
                frame_info = path.basename(frame).split(".")
                frame_number = int(frame_info[0])
                frame_samples = int(frame_info[1])

                if frame_samples < max_samples:
                    requested_frames.append({
                        "number": frame_number,
                        "available_samples": frame_samples,
                        "requested_samples": max_samples - frame_samples,
                        "available_frame": frame
                    })

        elif min_samples < SAMPLES_CAP:
            for frame in rendered_frames:
                frame_info = path.basename(frame).split(".")
                frame_number = int(frame_info[0])

                requested_frames.append({
                    "number": frame_number,
                    "available_samples": min_samples,
                    "requested_samples": min_samples * SAMPLES_MULTIPLIER,
                    "available_frame": frame
                })

    for frame in requested_frames:
        render_frame(render_directory,
                     frame["number"],
                     frame["available_samples"],
                     frame["requested_samples"],
                     frame["available_frame"])

        if time() - benchmark > abandon_after:
            break

    meta.write({"processing": False})