Время ожидания оценки Nightmare Js истекло после нескольких оценок - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь настроить разрабатываемое мной приложение, которое включает в себя запись HTML-виджета (с анимацией) и превращение его в mp4.Локально работает отлично.У меня есть Nightmare Js, обрабатывающие снимки экрана, и FFMPEG, преобразующий снимки экрана в mp4, что занимает около 90 секунд на моем ПК.

Я устанавливаю его в докер-контейнер через службу хостинга и не могу пройти через этовопрос.Мой тестовый скрипт на данный момент выглядит примерно так:

const Nightmare = require('nightmare')
const Xvfb = require('xvfb')

module.exports = function(app) {
  app.get('/api/nightmare', async (req, res) => {
    console.log('GET request to /api/nightmare')

    try {
      // Start xvfb and create our nightmare object
      const close = await xvfb()
      const nightmare = Nightmare({ executionTimeout: 1000 })

      const [err, result] = await poss(run(nightmare))
      if (err) {
        // Cleanup before throwing error
        await nightmare.end()
        await close()
        throw err
      }

      // shut'er down
      await nightmare.end()
      await close()
      res.status(200).send('Completed')
    } catch (error) {
      console.log(error)
      res.status(500).send(error)
    }
  })  
}

async function run(nightmare) {
  var data = {
    'id': '2OWBTMUL',
    'somedata': 'blah'
    // More data pulled from the database goes here
  }

  // Create folder to hold images
  var procName = new Date().getTime() + '_testing_' + data.id
  fs.mkdirSync(path.resolve(__dirname, '../processing/', procName))

  // URL to inject into webpage so the webpage can access the data
  var url = `http://example.com?` +
    `id=${data.id}&` +
    `somedata=${data.somedata}`

  console.log('Starting NightmareJs')
  await nightmare
    .viewport(1920, 1080)
    .goto('file:///' + path.resolve(__dirname, '../templates/example.html'))
    .evaluate(newUrl => {
      // Set url and get the page ready for recording
      url = new URL(newUrl)
      initiate()
      start()
      timeline.pause()
    }, url)
    .catch(error => { console.log(error) })

  // Take 200 screenshots (8s @ 25fps)
  var frames = 200
  for (var i = 0; i < frames; i++) {
    console.log('Taking screenshot ' + i)

    await nightmare
      .screenshot(path.resolve(__dirname, '../processing/', procName, 'screen_' + i + '.png'))
      .evaluate(shot => { timeline.seek((8 / 200) * shot) }, i)
      .catch(error => { console.log(error) })
  }

  console.log('Done.')
}

// xvfb wrapper
function xvfb(options) {
  var xvfb = new Xvfb(options)

  function close() {
    return new Promise((resolve, reject) => {
      xvfb.stop(err => (err ? reject(err) : resolve()))
    })
  }

  return new Promise((resolve, reject) => {
    xvfb.start(err => (err ? reject(err) : resolve(close)))
  })
}

// try/catch helper
async function poss(promise) {
  try {
    const result = await promise
    return [null, result]
  } catch (err) {
    return [err, null]
  }
}

Некоторые подробности среды:
Ubuntu 18.04.1
Supervisor
Узел 8.12.0 (DEBUG = * set)

Проблема: после примерно 17 циклов Nightmare выдает две разные ошибки.В моем файле nodejs-stderr.log я получаю

Taking screenshot x
Error: Evaluation timed out after 1000msec.  Are you calling done() or resolving your promises?

Тестирование с обратным вызовом done () или обещанием в оценке ничего не изменило, поэтому я оставил его простым

В моем файле nodejs-stdout.log я получаю это для каждого успешного цикла

Mon, 19 Nov 2018 09:37:06 GMT nightmare:actions .screenshot()
Mon, 19 Nov 2018 09:37:06 GMT nightmare:log subscribing to browser window frames
Mon, 19 Nov 2018 09:37:06 GMT nightmare:log Highlighting page to trigger rendering.
Mon, 19 Nov 2018 09:37:06 GMT nightmare:log unsubscribing from browser window frames
Mon, 19 Nov 2018 09:37:07 GMT nightmare:actions .screenshot() captured with length 1092963
Mon, 19 Nov 2018 09:37:07 GMT nightmare:actions .evaluate() fn on the page
Mon, 19 Nov 2018 09:37:07 GMT nightmare queueing action "screenshot"
Mon, 19 Nov 2018 09:37:07 GMT nightmare queueing action "evaluate"
Mon, 19 Nov 2018 09:37:07 GMT nightmare running

А затем примерно через 17 или около того циклов я получаю:

Mon, 19 Nov 2018 09:37:07 GMT nightmare:actions .screenshot()
Mon, 19 Nov 2018 09:37:07 GMT nightmare:log subscribing to browser window frames
Mon, 19 Nov 2018 09:37:07 GMT nightmare:log Highlighting page to trigger rendering.
Tue, 20 Nov 2018 02:11:43 GMT nightmare:log crashed [{},false]
Mon, 19 Nov 2018 09:37:12 GMT nightmare:log FrameManager timing out after 1000 ms with no new rendered frames
Mon, 19 Nov 2018 09:37:12 GMT nightmare:log unsubscribing from browser window frames
Mon, 19 Nov 2018 09:37:12 GMT nightmare:actions .screenshot() captured with length 0
Mon, 19 Nov 2018 09:37:12 GMT nightmare:actions .evaluate() fn on the page
Mon, 19 Nov 2018 09:37:13 GMT nightmare queueing action "screenshot"
Mon, 19 Nov 2018 09:37:13 GMT nightmare queueing action "evaluate"
Mon, 19 Nov 2018 09:37:13 GMT nightmare running

А остальные все терпят неудачу, без сообщения crashed [{},false].
Удаление .evaluate(shot => { timeline.seek((8 / 200) * shot) }, i) в цикле решает проблему, но мне нужно, чтобы это было просто неподвижное видео!Я пробовал отдельные вызовы (не цепочки оценки и скриншота), помещая .wait (200) между вещами, но я не могу понять это или найти какую-либо помощь по этому вопросу.

1 Ответ

0 голосов
/ 20 ноября 2018

Оказалось, что общая память слишком мала.Я предполагаю, что когда все изображения были загружены, он превысил предел памяти, и Electron потерпел крах.После увеличения общей памяти с 64 МБ до 128 МБ проблема решена.

...