<commit_before>const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn
const exec = require('child_process').exec
const execSync = require('child_process').execSync

const {pad, timestamp} = require('./utils')
const {app, Tray, Menu} = require('electron')

let isRecording = false
let tray = null
let win = null
let ffmpeg = null

function startRecording (window) {
  win = window // keep a reference for async operations, etc.

  // check if ffmpeg is around
  try {
    execSync('ffmpeg -h')
  } catch (err) {
    win.rpc.emit('status:error', {
      'body': 'Can\'t find ffmpeg'
    })
    return
  }

  win.setResizable(false)
  app.dock.setBadge('R')

  let args = [
    '-y',
    '-f', 'image2pipe',
    '-r', '' + (+60),
    '-vcodec', 'mjpeg',
    '-i', '-'
  ]

  // format
  args.push('-f', 'matroska')

  // output
  args.push(app.getPath('downloads') + '/' + 'test.mp4')

  ffmpeg = spawn('ffmpeg', args)
  // ffmpeg.stdout.on('data', (data) => console.log('[camera]', data.toString()))
  // ffmpeg.stderr.on('data', (data) => console.log('[camera]', data.toString()))

  isRecording = true
  win.rpc.emit('recorder:start')
  win.webContents.beginFrameSubscription(addFrame)

  showTray()
  console.log('[camera] Recording...')
}

function addFrame(frameBuffer) {
  console.log(frameBuffer.length)
  if(!isRecording) return // avoid trail frames
  try {
    win.capturePage( (image) => {
      let jpeg = image.toJpeg(100)
      try {
        ffmpeg.stdin.write(jpeg, (err) => {
          if (err) throw err
          console.log('[camera] .')
        })
      } catch (err) {
        console.log('[ffmpeg]', err)
      }
    })
  }
  catch (err) {
    console.log('[camera]', err)
  }
}

function showTray () {
  tray = new Tray(path.join(__dirname, '/assets/tray-icon-blackTemplate.png'))
  tray.setPressedImage(path.join(__dirname, '/assets/tray-icon-whiteTemplate.png'))

  let contextMenu = Menu.buildFromTemplate([
    {
      label: 'Ōryōki is recording',
      enabled: false
    },
    {
      type: 'separator'
    },
    {
      label: 'Stop Recording',
      accelerator: 'Cmd+Alt+Shift+P',
      click () {
        stopRecording()
      }
    }
  ])
  tray.setToolTip('Ōryōki • REC')
  tray.setContextMenu(contextMenu)
}

function stopRecording () {
  isRecording = false
  win.webContents.endFrameSubscription()
  ffmpeg.stdin.end()
  // ffmpeg = null
  win.setResizable(false)
  hideTray()
  app.dock.setBadge('')
  console.log('[camera] Recording stopped.')
}

function hideTray () {<commit_msg>almost there, dont wanna loose progress<commit_after>const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn
const stream = require('stream')
const exec = require('child_process').exec
const execSync = require('child_process').execSync

const {pad, timestamp} = require('./utils')
const {app, Tray, Menu} = require('electron')

let isRecording = false
let tray = null
let win = null

let ffmpeg = null
let imageStream = null

function startRecording (window) {
  win = window // keep a reference for async operations, etc.

  // check if ffmpeg is around
  try {
    execSync('ffmpeg -h')
  } catch (err) {
    win.rpc.emit('status:error', {
      'body': 'Can\'t find ffmpeg'
    })
    return
  }

  win.setResizable(false)
  app.dock.setBadge('R')

  // video size
  const electronScreen = require('electron').screen
  let currentDisplay = electronScreen.getDisplayMatching(win.getBounds())
  let width = win.getSize()[0] * currentDisplay.scaleFactor
  let height = win.getSize()[1] * currentDisplay.scaleFactor
  let size = width + 'x' + height

  let args = [
    // input
    '-y',
    '-f', 'rawvideo',           // no codec, just raw data
    '-s', size,
    '-framerate', 60,
    '-pix_fmt', 'rgb32',        // that's what electron gives us
    '-i', '-',
    '-vcodec', 'mjpeg',
    '-q:v', '2',                // max out quality
    // output
    '-r', 30,                   // 30fps keeps the file size down
    '-pix_fmt', 'yuvj420p'      // legacy (?) fmt to enable preview in macOS
    '-vcodec', 'libx264',       // h264 codec
    '-preset', 'slow',          // no compromise quality for speed
  ]

  // output prores (change ext to .mov)
  // '-framerate', 30,
  // '-vcodec', 'prores_ks',
  // '-pix_fmt', 'yuvj420p'

  // format
  // args.push()

  // output
  args.push(app.getPath('downloads') + '/' + 'test.mp4')

  imageStream = new stream.PassThrough()

  ffmpeg = spawn('ffmpeg', args)
  // ffmpeg.stdout.on('data', (data) => console.log('[camera]', data.toString()))
  // ffmpeg.stderr.on('data', (data) => console.log('[camera]', data.toString()))

  imageStream.pipe(ffmpeg.stdin)

  isRecording = true
  win.rpc.emit('recorder:start')
  win.webContents.beginFrameSubscription(addFrame)

  showTray()
  console.log('[camera] Recording...')
}

function addFrame(frameBuffer) {
  if(!isRecording) return // avoid trail frames
  try {
    imageStream.write(frameBuffer, 'utf8')
  }
  catch (err) {
    console.log('[camera]', err)
  }
}

function showTray () {
  tray = new Tray(path.join(__dirname, '/assets/tray-icon-blackTemplate.png'))
  tray.setPressedImage(path.join(__dirname, '/assets/tray-icon-whiteTemplate.png'))

  let contextMenu = Menu.buildFromTemplate([
    {
      label: 'Ōryōki is recording',
      enabled: false
    },
    {
      type: 'separator'
    },
    {
      label: 'Stop Recording',
      accelerator: 'Cmd+Alt+Shift+P',
      click () {
        stopRecording()
      }
    }
  ])
  tray.setToolTip('Ōryōki • REC')
  tray.setContextMenu(contextMenu)
}

function stopRecording () {
  isRecording = false
  win.webContents.endFrameSubscription()
  imageStream.end()
  // ffmpeg = null
  win.setResizable(false)
  hideTray()
  app.dock.setBadge('')
  console.log('[camera] Recording stopped.')
}

function hideTray () {
{'fraction_non_alphanumeric': 0.16561809216119708, 'fraction_numerical': 0.005781329705832341, 'mean_word_length': 2.971640783254558, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5776985', 'n_tokens_mistral': 2061, 'n_tokens_neox': 2014, 'n_words': 433}