Create a screencast with exactly one image per animation frame
My preferred method would be to use a frame_change handler and an update method on a bool to turn it on off.

import bpy
import os

from bpy.props import BoolProperty

def remove_handler_function(handler, name):
    ''' Removes all functions with name starting with name '''
    fns = [f for f in handler
                   if f.__name__.startswith(name)]
    for f in fns:    
        handler.remove(f)  


def screenshot(scene):
    frame = scene.frame_current
    in_frame =  scene.frame_start &lt;= frame &lt;= scene.frame_end
    if not in_frame:
        return None

    folder = scene.render.filepath
    format = scene.render.image_settings.file_format.lower()
    filepath = os.path.join(folder,"%04d.%s" % (frame, format))
    print("render %d" % frame)
    bpy.ops.screen.screenshot(
        filepath=filepath,
        check_existing=False)

def capture_screen(self, context):
    # turn on the handler
    handler = bpy.app.handlers.frame_change_post
    if self.render_screencast:
        handler.append(screenshot)
    else:
        remove_handler_function(handler, "screenshot")




bpy.types.Scene.render_screencast = BoolProperty(default=False,
                                                 name="Screen Shot Cast",
                                                 update=capture_screen)

#testing
bpy.context.scene.render_screencast = False


My testing shows that the operator will do as desired with

        bpy.ops.screen.screenshot(
            filepath=filepath,
            check_existing=False)
        for area in context.screen.areas:
            area.tag_redraw()


but it will lock up blender until finished.  Pretty sure there is no need to call scene.update() after scene.frame_set(f), and not sure how much this effects performance, if at all.

Another is a modal timer operator, which enables the chance to cancel. (The handler is much better).  The link of @ideasman42 I mentioned is here How to handle modal operator events in a single loop?  Which may make handling canceling easier.

class ModalTimerOperator(bpy.types.Operator):
    """Operator which runs its self from a timer"""
    bl_idname = "wm.modal_timer_operator"
    bl_label = "Modal Timer Operator"
    wait = 10
    _timer = None
    renderframe = -1
    def modal(self, context, event):
        scene = context.scene
        rendering = self.renderframe == scene.frame_current
        folder = scene.render.filepath
        format = scene.render.image_settings.file_format.lower()

        if event.type in {'RIGHTMOUSE', 'ESC'} or scene.frame_current &gt; scene.frame_end:
            self.cancel(context)
            return {'CANCELLED'}
        if event.type == 'TIMER' and self.wait:
            self.wait -= 1
            return {'PASS_THROUGH'}

        if rendering:
            return {'PASS_THROUGH'}

        else:
            self.renderframe = scene.frame_current

            print("render %d" % scene.frame_current)
            self.report({'INFO'}, "Render: %4d" % scene.frame_current)
            filepath = os.path.join(folder,"%04d.%s" % (scene.frame_current, format))
            bpy.ops.screen.screenshot(
                filepath=filepath,
                check_existing=False)

            scene.frame_set(scene.frame_current + 1)
            self.wait = 10
            for area in context.screen.areas:
                area.tag_redraw()            

        return {'PASS_THROUGH'}

    def execute(self, context):
        scene = context.scene
        wm = context.window_manager
        self._timer = wm.event_timer_add(0.1, context.window)
        wm.modal_handler_add(self)
        scene.frame_set(scene.frame_start)
        return {'RUNNING_MODAL'}