function renderFrames(records, options) {
  return new Promise(function (resolve, reject) {
    // The number of frames
    var framesCount = records.length;

    // Track execution time
    var start = Date.now();

    // Create a progress bar
    var progressBar = getProgressBar(
      "Rendering",
      Math.ceil(framesCount / options.step)
    );

    // Execute the rendering process
    var render = di.spawn(
      di.electron,
      [di.path.join(ROOT_PATH, "render/index.js"), renderDir, options.step,],
      { detached: false }
    );

    render.stdout.on('data', onData);
    render.stderr.on('data', onError);
    render.on('close', onClose); 

    // Track progress of rendering through stdout
    function onData(data) {

      // Is not a recordIndex (to skip Electron's logs or new lines)
      if (isNaN(parseInt(data.toString()))) {
        return;
      }

      progressBar.tick();
    }

    // Track rendering errors observed on stderr
    function onError(error) {

      // If error is Buffer, print it, otherwise reject
      if (!!error && error instanceof Buffer) {
        console.log(di.chalk.yellow(`[render] ${error.toString('utf8').trim()}`));
      } else {
        render.kill();
        reject(new Error("Unknown error [" + typeof error + "]: " + error));
      }
    } 

    // React when rendering process finishes
    function onClose(code) {
      if (code !== 0) {
        reject(new Error("Rendering exited with code " + code));
      } else {
        if (progressBar.complete) {
          console.log(di.chalk.green('[render] Process successfully completed in ' + (Date.now() - start) + 'ms.'));
        } else {
          console.log(di.chalk.yellow('[render] Process completion unverified'));
        }

        resolve();
      }
    };
  });
}
Render the frames into PNG images

@param  {Array}   records [{delay, content}, ...]
@param  {Object}  options {step}
@return {Promise}